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.
Install jfa
from CRAN
install.packages("jfa")
or from GitHub
devtools::install_github("koenderks/jfa")
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.
planning()
: The basicsPlanning 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
).
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%
## # ------------------------------------------------------------
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%
## # ------------------------------------------------------------
selection()
: The basicsSelecting 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"
.
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
## # ------------------------------------------------------------
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%
## # ------------------------------------------------------------
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
evaluation()
: The basicsAfter 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
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
## # ------------------------------------------------------------
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
## # ------------------------------------------------------------
auditPrior()
: Prior probability distributionsThe 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.