Overview

The jfa package allows you to plan, select, and evaluate an audit sample using classical and Bayesian statistics.

Below it is explained how to install and use the jfa package.

Installation

Install jfa from CRAN

or from GitHub

devtools::install_github("koenderks/jfa")

Load data

We can try out some examples with the BuildIt data set that is included in the package. It includes a population of 3500 transactions from a fictional construction company BuildIt, which we can use to illustrate statistical audit sampling using the jfa package (for more info, see ?BuildIt).

library(jfa)

data("BuildIt")
BuildIt <- BuildIt[, c("ID", "bookValue")] # Let's remove the auditValue column for this example
head(BuildIt, n = 10)
##       ID bookValue
## 1  82884    242.61
## 2  25064    642.99
## 3  81235    628.53
## 4  71769    431.87
## 5  55080    620.88
## 6  93224    501.76
## 7  24331    466.01
## 8  81460    295.20
## 9  14608    216.48
## 10 79064    243.43

Because this data set contains the Ist values of the transactions, we need to consider each monetary unit in the population as a possible unit of inference.

For an example of the jfa’s audit sampling workflow see The audit sampling workflow.

Using planning(): The basics

Planning a sample using the planning() function requires that you have knowledge of the goal of the analysis and the statistical distribution of your data (poisson, binomial, or hypergeometric).

Testing against a performance materiality

Let’s take the goal of testing against a performance materiality with the poisson distribution as an example.

Analysis goal: Plan a sample such that, when zero misstatements are found in the sample, you can be 95% confident that the total misstatement in the population is lower than 5% of its total value.

Planning a sample with this goal can be done using the code below (specifically using the materiality argument). As you can see, the required sample size for this goal is 60 monetary units.

planning(confidence = 0.95, expectedError = 0, likelihood = "poisson", N = 3500, materiality = 0.05)
## # ------------------------------------------------------------
## #              jfa Planning Summary (Frequentist)
## # ------------------------------------------------------------     
## # Input:
## # 
## # Confidence:              95% 
## # Materiality:             5% 
## # Minimum precision:       Not specified 
## # Likelihood:              poisson 
## # Expected sample errors:  0 
## # ------------------------------------------------------------
## # Output:
## #
## # Sample size:             60 
## # ------------------------------------------------------------
## # Statistics:
## #
## # Expected upper bound:    4.99% 
## # Expected precision:      4.99% 
## # ------------------------------------------------------------

Obtaining a minimum required precision

The goal of the analysis can also involve obtaining a minimum precision about the estimate of the misstatement.

Analysis goal: Plan a sample such that, when zero misstatements are found in the sample, you can be 95% confident that the inaccuracy of your estimate is at most 2%.

Planning a sample with this goal can be done using the code below (specifically using the minPrecision argument). As you can see, the required sample size for this goal is 150 monetary units.

planning(confidence = 0.95, expectedError = 0, likelihood = "poisson", N = 3500, minPrecision = 0.02)
## # ------------------------------------------------------------
## #              jfa Planning Summary (Frequentist)
## # ------------------------------------------------------------     
## # Input:
## # 
## # Confidence:              95% 
## # Materiality:             Not specified 
## # Minimum precision:       2% 
## # Likelihood:              poisson 
## # Expected sample errors:  0 
## # ------------------------------------------------------------
## # Output:
## #
## # Sample size:             150 
## # ------------------------------------------------------------
## # Statistics:
## #
## # Expected upper bound:    2% 
## # Expected precision:      2% 
## # ------------------------------------------------------------

Using selection(): The basics

Selecting a sample using the selection() function requires that you have knowledge of the sampling units. Transactions can be selected using record sampling (also called attribute sampling) with units = "records", or using monetary unit sampling with units = "mus".

It also requires knowledge of the sampling algorithm. Transactions can be selected using random sampling with algorithm = "random", using cell sampling with algorithm = "cell", or using fixed interval sampling (also known as systematic sampling) with algorithm = "interval".

Record sampling

For example, the code below samples 60 monetary units from the BuildIt data set using a random record sampling scheme.

selection(population = BuildIt, sampleSize = 150, units = "records", algorithm = "random")
## # ------------------------------------------------------------
## #                  jfa Selection Summary
## # ------------------------------------------------------------
## # Input:
## #       
## # Population size:         3500 
## # Requested sample size:   150 
## # Sampling units:          Records 
## # Algorithm:               Random sampling   
## # ------------------------------------------------------------ 
## # Output:
## # 
## # Obtained sample size:    150 
## # ------------------------------------------------------------
## # Statistics:
## #
## # Proportion n/N:          0.04 
## # ------------------------------------------------------------

Monetary unit sampling

As another example, the code below samples 150 monetary units from the BuildIt data set using a fixed interval monetary unit sampling scheme.

selection(population = BuildIt, sampleSize = 150, units = "mus", algorithm = "interval", 
          bookValues = "bookValue")
## # ------------------------------------------------------------
## #                  jfa Selection Summary
## # ------------------------------------------------------------
## # Input:
## #      
## # Population size:         3500 
## # Requested sample size:   150 
## # Sampling units:          Monetary units 
## # Algorithm:               Fixed interval sampling 
## # Interval:                9354.81
## # Starting point:          1  
## # ------------------------------------------------------------ 
## # Output:
## #
## # Obtained sample size:    150 
## # ------------------------------------------------------------
## # Statistics:
## #
## # Proportion n/N:          0.04 
## # Percentage of value:     5.29% 
## # ------------------------------------------------------------

Extracting the sample

The selected sample is saved in the object that is returned by the selection() function and can be extracted via $sample.

result <- selection(population = BuildIt, sampleSize = 150, units = "mus", algorithm = "interval", 
                    bookValues = "bookValue")

sample <- result$sample
head(sample, n = 10)
##    rowNumber count    ID bookValue
## 1          1     1 30568     14.47
## 2        107     1 89715    112.19
## 3        182     1  2309    135.77
## 4        246     1 95807    153.56
## 5        305     1  5143    167.73
## 6        359     1 69174    178.04
## 7        410     1 43352    188.72
## 8        459     1 78666    195.23
## 9        506     1 64142    202.72
## 10       551     1 12379    209.45

Using evaluation(): The basics

After executing the audit and annotating the transactions in the sample with their Soll values, you can evaluate whether you have achieved your analysis goal via the evaluation() function. The function can be used with summary statistics from the sample, or with an annotated sample as input.

For more details on how to use this function see the package vignettes: Estimating the misstatement and Testing the misstatement

Summary statistics from the sample

Suppose that in 60 transactions, you have found 1 misstatement. Using nSumstats = 60 and kSumstats = 1 you can specify the outcomes of the sample in the evaluation() function. Do not forget to specify your analysis goal using the materiality or minPrecision arguments.

evaluation(confidence = 0.95, method = "binomial", N = 3500, nSumstats = 60, kSumstats = 1, materiality = 0.05)
## # ------------------------------------------------------------ 
## #             jfa Evaluation Summary (Frequentist)
## # ------------------------------------------------------------ 
## # Input: 
## #
## # Confidence:               95%   
## # Materiality:              5% 
## # Minium precision:         Not specified 
## # Sample size:              60 
## # Sample errors:            1 
## # Sum of taints:            1 
## # Method:                   binomial 
## # ------------------------------------------------------------
## # Output:
## #
## # Most likely error:        1.67% 
## # Upper bound:              7.66% 
## # Precision:                6% 
## # Conclusion:               Do not approve population 
## # ------------------------------------------------------------

Annotated sample

Suppose that you have audited the transactions in the sample and have found no deviations from the ist values.

sample$auditValue <- sample$bookValue

You can evaluate the annotated sample using the sample, bookValues, auditValues, and counts arguments. The code below evaluates the analysis goal using the popular Stringer bound. You can find more information about which methods are implemented on the home page.

evaluation(confidence = 0.95, method = "stringer", N = 3500, materiality = 0.05,
           sample = sample, bookValues = "bookValue", auditValues = "auditValue", counts = sample$count)
## # ------------------------------------------------------------ 
## #             jfa Evaluation Summary (Frequentist)
## # ------------------------------------------------------------ 
## # Input: 
## #
## # Confidence:               95%   
## # Materiality:              5% 
## # Minium precision:         Not specified 
## # Sample size:              150 
## # Sample errors:            0 
## # Sum of taints:            0 
## # Method:                   stringer 
## # ------------------------------------------------------------
## # Output:
## #
## # Most likely error:        0% 
## # Upper bound:              1.98% 
## # Precision:                1.98% 
## # Conclusion:               Approve population 
## # ------------------------------------------------------------

Using auditPrior(): Prior probability distributions

The auditPrior() function allows you to perform the workflow as discussed above in a Bayesian fashion. Using a prior distribution is fairly simple, you only have to insert the returned object from the auditPrior() function as an argument for the prior argument in the planning() and evaluation() functions.

For more information about how to create a prior distribution, see the vignettes Constructing a prior distribution.