Standard Benfords
Executive Summary

Executive Summary

Benford's Law read on 4,941 values from Amount

Values Analyzed
4941
MAD
0.0234
Conformity
nonconformity
Chi-Square p
<0.001
Digits Flagged
9
Verdict
deviates (investigate)
Verdict: the first-digit distribution of Amount deviates (investigate). Across 4,941 values the mean absolute deviation from the Benford curve is 0.0234, which lands in Nigrini's nonconformity band, and the chi-square goodness-of-fit gives p < 0.001. Digits 1, 2, 3, 4, 5, 6, 7, 8, 9 carry the deviation — see the deviations table for direction. Benford deviation is a screening signal, not proof of fabrication — a deviating digit pattern says where an auditor should look, nothing more.
What this means

The short answer

These 4,941 transaction amounts deviate from Benford's Law. The mean absolute deviation of 0.0234 falls in the nonconformity band, and the chi-square test yields p < 0.001, signaling a first-digit pattern that departs from the expected log10(1 + 1/d) curve more than chance would explain.

The detail

All 9 digits carry the deviation. The MAD of 0.0234 is the aggregate distance from the Benford curve across all digits; Nigrini's conformity bands classify this as nonconformity. The chi-square p-value < 0.001 confirms the deviation is statistically detectable across the 4,941 values analyzed. The deviations table (in the full report) shows which individual digits are elevated or suppressed.

What this can't tell you

A Benford deviation is a screening signal—it points to where an auditor should look—but does not establish the reason. Legitimate business rules, rounding, or systematic numbering can produce deviations identical to those from data quality issues. Investigate the flagged digits in context: compare them against your transaction generation process, pricing rules, and historical patterns.

Overview

Analysis Overview

Benford's Law screening of 4,941 values from Amount.

N Observations4941
Mad0.0234
Digits Flagged9
What this means

The short answer

The first-digit distribution of these 4,941 transaction amounts deviates from Benford's Law. Organically generated numbers—transactions, invoices, expenses—tend to start with small digits in a predictable pattern (about 30.1% with digit 1, only 4.6% with digit 9). This dataset's first-digit pattern diverges from that curve enough to warrant investigation, though deviation is a screening signal, not proof of fabrication.

The detail

The chi-square goodness-of-fit test yields p < 0.001, well below the threshold for random variation. The mean absolute deviation (MAD) is 0.0234, which places the dataset in Nigrini's nonconformity band—the threshold band that flags datasets as deviating rather than conforming. All nine digits (1 through 9) carry the deviation; the deviations table specifies which digits are over- or under-represented.

What this can't tell you

The analysis confirms the digit pattern does not match Benford's curve; it does not identify the source of the deviation. Benford deviation can arise from legitimate causes—rounding conventions, currency conversions, invoice numbering systems, or business rules that naturally skew transaction sizes—as well as from data entry errors or intentional misstatement. The next step is domain inspection: compare the flagged digits against your transaction workflows and controls.

Data Preparation

Data Quality

How the amounts were cleaned before digit extraction.

Initial Rows5000
Final Rows4941
Rows Removed59
What this means

The short answer

Of 5,000 rows loaded, 4,941 values were usable for digit screening. The main exclusion was 59 zero values, which carry no first digit; all other data quality checks left the sample intact.

The detail

Zero-value rows (59 total) were dropped because a zero has no first digit to extract. No blank or non-numeric entries were present, and no negative values required absolute-value conversion. A total of 279 values below 1 were retained because the digit is defined as the first significant digit — so 0.0042 counts as a 4 just as 4,200 does. This preserves small fractional amounts that may carry real information. The final count of 4,941 values exceeds the 100-value minimum required for Benford screening to be valid.

What this can't tell you

The preprocessing captures what was dropped and why, but does not reveal whether any of the 59 zeros represent missing or suppressed data rather than genuine zero amounts. A transaction-level export showing the reason codes for zero values would clarify whether they are structural (e.g., refunds netted to zero) or data-entry gaps.

Visualization

First Digits: Observed vs Expected

Share of values starting with each digit 1-9, against Benford's Law.

What this means

The short answer

The observed first-digit bars break sharply from the downward Benford slope. Digit 1 is over-represented at 36.6% versus 30.1% expected, while digits 2 through 6 fall consistently short of the curve, and digits 7, 8, 9 spike above expectation.

The detail

Benford expects a smooth decline from digit 1 (30.1%) to digit 9 (4.6%). The observed distribution peaks at digit 1 (36.6%), drops steeply to digit 3 (9.2% observed vs. 12.5% expected — the largest single shortfall), and then does not resume the expected decline. Instead, digits 7 (7.14% vs. 5.8%), 8 (5.95% vs. 5.12%), and 9 (6.46% vs. 4.58%) all exceed their Benford values. This non-monotonic pattern — a bulge at the low end and an unexpected rise at the high end — is the signature of the deviation.

What this can't tell you

The chart shows where the digit pattern diverges but not why. Over-representation of digit 1 can reflect naturally small amounts, contractual minimums, or rounding practices; over-representation of 7, 8, 9 can point to round numbers or specific pricing conventions. Only transaction context would reveal the cause.

Data Table

Per-Digit Deviations

Observed vs expected share per digit with standardized residuals.

DigitObservedExpectedStd ResidualFlag
10.36590.3019.94deviates high
20.14840.1761-5.12deviates low
30.09170.1249-7.07deviates low
40.08440.0969-2.97deviates low
50.0640.0792-3.96deviates low
60.05020.0669-4.71deviates low
70.07140.0584.05deviates high
80.05950.05122.66deviates high
90.06460.04586.33deviates high
What this means

The short answer

Digit 1 stands out as the largest deviation: it appears 9.94 standard errors above its Benford expectation. Digits 2 through 6 all fall below expectation, with digit 3 the deepest shortfall at −7.07 standard errors. Digits 7, 8, 9 also over-appear.

The detail

All 9 digits flag beyond the ±1.96 threshold. Digit 1: observed 36.6%, expected 30.1%, standardized residual +9.94 (deviates high). Digit 3: observed 9.2%, expected 12.5%, standardized residual −7.07 (deviates low). Digit 2: −5.12. Digit 4: −2.97. Digit 5: −3.96. Digit 6: −4.71. Digit 7: +4.05. Digit 8: +2.66. Digit 9: +6.33. The pattern shows a systematic excess of 1 and 7–9, and a systematic deficit of 2–6.

What this can't tell you

A standardized residual measures distance from expectation in the context of sample size, but does not explain the cause. Over-representation of digit 1 is consistent with many legitimate patterns (small natural amounts, contractual floors, rounding down). Over-representation of 7–9 can indicate round numbers or specific pricing tiers. Audit procedures on the underlying transactions would be needed to rule out or confirm any particular mechanism.

Data Table

Data Hygiene

What was dropped, what was kept, and why.

ReasonRows AffectedAction
Blank or non-numeric entries0dropped — no digits to read
Zero values59dropped — a zero has no first digit
Negative values0kept — absolute value used
Values below 1279kept — first significant digit used
Values analyzed4941screened against Benford's Law
What this means

The short answer

The dataset is clean at the preprocessing stage: 59 zero values were dropped (no first digit), and 279 sub-1 values were kept (first significant digit rule). No blanks, non-numeric entries, or negative values required correction.

The detail

Of 5,000 loaded rows: 0 blank or non-numeric entries (dropped — no digits to read); 59 zero values (dropped — a zero has no first digit); 0 negative values (kept via absolute value, but none were present); 279 values below 1 (kept — first significant digit definition applies, e.g., 0.0042 → digit 4). Final count: 4,941 values screened. The only material exclusion was the 59 zeros; all other adjustments were either absent or preserving of valid data.

What this can't tell you

The data-hygiene table does not distinguish between zero values that represent genuine zero amounts (e.g., refunds or reversals) and those that may be missing or suppressed. A breakdown by transaction type or source would clarify whether the 59 zeros are expected or anomalous. Consider requesting a transaction-level export that shows the reason or category for each zero value.

Data Table

Method and Thresholds

Nigrini's conformity bands, the tests run, and when Benford applies.

BandMad CutoffMeaningThis Data
Close conformity0.006MAD below 0.006 — observed digits track the Benford curve closely
Acceptable conformity0.012MAD from 0.006 up to 0.012 — ordinary sampling wobble, no cause for review
Marginal conformity0.015MAD from 0.012 up to 0.015 — borderline; worth a look if other signals agree
Nonconformity0.015MAD of 0.015 or more — the digit pattern departs from Benford; investigateyes
What this means

The short answer

The analysis used a chi-square goodness-of-fit test (p < 0.001) and the mean absolute deviation (0.0234) against Nigrini's published conformity bands. The MAD falls in the nonconformity band (≥0.015), confirming the digit pattern departs from Benford's Law. A second-digit test (p < 0.001) corroborates the finding.

The detail

Chi-square test: 8 degrees of freedom, p < 0.001, rejecting the hypothesis that the first-digit distribution follows log₁₀(1 + 1/d). Mean absolute deviation: 0.0234, compared against Nigrini's thresholds — close conformity ≤0.006, acceptable ≤0.012, marginal ≤0.015, nonconformity ≥0.015. This data lands in nonconformity. Individual digits flagged when standardized residual > 1.96. First-two-digit test (90 combinations, 10–99): chi-square p < 0.001, first-two-digit MAD 0.0048, agreeing that the digit pattern departs from Benford. Applicability: amounts span 5.8 orders of magnitude across 2,504 distinct values — wide enough for Benford to apply.

What this can't tell you

Benford's Law does not apply to assigned identifiers, capped or floored ranges, or single-price lists; this dataset passes the applicability check. The tests confirm deviation but do not identify its cause. A qualitative review of the transactions themselves would be needed to distinguish legitimate patterns (e.g., contractual minimums, round pricing) from data anomalies.

Rate this report Was this the answer you needed?
The exact source that produced this report — yours to keep, read, and re-run.
Download PDF
How this was computed method · R source · citation
The code that did it

Benford's Law Screening — Do These Numbers Look Fabricated?

Screens a numeric amount column against Benford's Law: the observed first-significant-digit distribution versus the expected log10(1 + 1/d) curve, a chi-square goodness-of-fit test, the mean absolute deviation (MAD) read against Nigrini's conformity bands, per-digit standardized residuals flagging which digits deviate most, and an optional first-two-digit test when there is enough data.

Why This Method?

Organic amounts that grow multiplicatively — transactions, expenses, invoice totals — start with 1 about 30 percent of the time and with 9 under 5 percent of the time. Invented numbers rarely follow that curve, which makes the first-digit test a fast, standard screen in forensic accounting and audit. Deviation is a SCREENING signal that says "look closer here", never proof of manipulation.

What This Analysis Covers

  • Observed versus expected share for each first digit 1-9
  • Chi-square goodness-of-fit against the Benford expectation
  • MAD with Nigrini's conformity bands (close / acceptable / marginal /

nonconformity)

  • Per-digit standardized residuals with deviates-high / deviates-low flags
  • First-two-digit test when at least 1,000 usable values are present
  • A computed applicability check: narrow-range data violates Benford

naturally and is warned about, not accused

Standard Library

Platform standard-library module (LAT-1441): runs on ANY dataset via the semantic mapping {value}. All narrative is derived from the user's own column name and computed values.

suppressPackageStartupMessages(library(DT))
suppressPackageStartupMessages(library(htmlwidgets))
suppressPackageStartupMessages(library(arrow))
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(rmarkdown))
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(tidyr))
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(stringr))
suppressPackageStartupMessages(library(lubridate))
suppressPackageStartupMessages(library(broom))
suppressPackageStartupMessages(library(Matrix))
suppressPackageStartupMessages(library(cluster))
suppressPackageStartupMessages(library(data.table))

Core Analysis Pipeline

Step 1: Locate the mapped amount column

initial_rows <- nrow(df)
  if (!("value" %in% names(df))) {
    stop("column_mapping must map the value column — the numeric amounts to screen.")
  }
  hv <- humanize_semantic("value", col_map)

Step 2: Data hygiene — every drop is counted and reported.

Blanks and non-numeric entries are dropped; zeros are dropped (a zero has no first digit); negatives are KEPT via absolute value (a refund of -420 still leads with a 4); values below 1 are KEPT because the digit is defined as the first SIGNIFICANT digit (0.0042 counts as a 4).

v_raw <- df$value
  ch <- as.character(v_raw)
  blank_mask <- is.na(v_raw) | is.na(ch) | trimws(ch) == ""
  conv <- suppressWarnings(as.numeric(ch))
  nonnum_mask <- !blank_mask & is.na(conv)
  n_blank <- as.integer(sum(blank_mask) + sum(nonnum_mask))
  n_nonblank <- sum(!blank_mask)
  if (n_nonblank > 0 && sum(!blank_mask & !is.na(conv)) < 0.95 * n_nonblank) {
    stop(paste0(hv, " does not look numeric: fewer than 95 percent of its ",
                "non-blank entries could be read as numbers. Benford ",
                "screening needs a numeric amount column such as ",
                "transaction amounts, expenses, or invoice totals."))
  }
  x0 <- conv[!blank_mask & !nonnum_mask]
  n_zero <- as.integer(sum(x0 == 0))
  n_neg  <- as.integer(sum(x0 < 0))
  x <- abs(x0[x0 != 0])
  n_sub1 <- as.integer(sum(x < 1))
  n <- length(x)
  final_rows <- n
  rows_removed <- initial_rows - final_rows

Step 3: Volume guard — Benford needs volume to mean anything.

if (n < 100) {
    stop(sprintf(paste0(
      "Benford screening needs at least 100 usable values to be meaningful, ",
      "but %s has only %d after removing blank and zero entries. First-digit ",
      "proportions are far too noisy below that volume for the conformity ",
      "thresholds to carry any signal — gather more records and re-run."),
      hv, n))
  }

Step 4: First significant digits, extracted robustly.

sprintf("%.6e", x) yields the normalized mantissa, so the first (and second) significant digits are positional characters — immune to the floating-point trap where floor(log10(1000)) evaluates to 2.

e_str <- sprintf("%.6e", x)
  d1 <- as.integer(substr(e_str, 1, 1))
  d2 <- as.integer(substr(e_str, 3, 3))

Step 5: First-digit test — chi-square, MAD, Nigrini bands, residuals

digits <- 1:9
  benford_p <- log10(1 + 1 / digits)
  obs_counts <- tabulate(d1, nbins = 9)
  obs_p <- obs_counts / n

  chi <- suppressWarnings(chisq.test(obs_counts, p = benford_p, rescale.p = TRUE))
  chi_stat <- as.numeric(chi$statistic)
  chi_p <- as.numeric(chi$p.value)

  mad_val <- mean(abs(obs_p - benford_p))

Nigrini's first-digit conformity bands (Nigrini 2012): MAD < 0.006 close; < 0.012 acceptable; < 0.015 marginal; else nonconformity

band <- if (mad_val < 0.006) "close conformity" else
          if (mad_val < 0.012) "acceptable conformity" else
          if (mad_val < 0.015) "marginal conformity" else "nonconformity"
  verdict <- if (band %in% c("close conformity", "acceptable conformity")) {
    "conforms"
  } else {
    "deviates(investigate)"
  }

  se <- sqrt(benford_p * (1 - benford_p) / n)
  z <- (obs_p - benford_p) / se
  flag <- ifelse(z > 1.96, "deviates high", ifelse(z < -1.96, "deviates low", ""))
  n_flagged <- as.integer(sum(flag != ""))

Step 6: Applicability — computed against the data, not assumed.

Benford's Law only arises in amounts spanning several orders of magnitude. Assigned numbers, capped or floored ranges, and single-price data violate it NATURALLY — deviation there is not suspicious.

span_oom <- log10(max(x) / min(x))
  n_distinct <- length(unique(x))
  range_warning <- is.finite(span_oom) && span_oom < 2
  applicability_notes <- character(0)
  if (range_warning) {
    applicability_notes <- c(applicability_notes, paste0(
      "Warning: the amounts in ", hv, " span only ", sprintf("%.1f", span_oom),
      " orders of magnitude(from ", fmt_num(min(x)), " to ", fmt_num(max(x)),
      "), and Benford&#x27;s Law may not apply to numbers confined to such a ",
      "narrow band — assigned numbers, capped or floored amounts, and ",
      "single-price data all depart from Benford naturally. Treat the ",
      "conformity reading with caution: the deviation here can be a ",
      "property of the data&#x27;s range, not of anyone's behavior."))
  } else if (n_distinct < 50) {
    applicability_notes <- c(applicability_notes, paste0(
      "Warning: ", hv, " holds only ", n_distinct, " distinct amounts, ",
      "which suggests a fixed price list or assigned values rather than ",
      "organically generated amounts — a situation where Benford&#x27;s Law may ",
      "not apply. Treat the conformity reading with caution."))
  }

Step 7: First-two-digit test — only with volume (n >= 1000).

ftd_ran <- n >= 1000
  ftd_chi_p <- NA_real_
  ftd_mad <- NA_real_
  if (ftd_ran) {
    ftd <- 10L * d1 + d2
    ftd_counts <- tabulate(ftd, nbins = 99)[10:99]
    ftd_exp_p <- log10(1 + 1 / (10:99))
    ftd_chi <- suppressWarnings(chisq.test(ftd_counts, p = ftd_exp_p, rescale.p = TRUE))
    ftd_chi_p <- as.numeric(ftd_chi$p.value)
    ftd_mad <- mean(abs(ftd_counts / n - ftd_exp_p))
    ftd_note <- paste0(
      "The first-two-digit test ran on the same ", format(n, big.mark = ","),
      " values(it requires at least 1,000): chi-square across the 90 ",
      "two-digit combinations 10 through 99 gives ", fmt_pp(ftd_chi_p),
      ", with a first-two-digit MAD of ", sprintf("%.4f", ftd_mad), ". ",
      if (!is.na(ftd_chi_p) && ftd_chi_p < 0.05) {
        "It agrees with the first-digit read that the digit pattern departs from the Benford expectation."
      } else {
        "It finds no additional departure beyond first-digit sampling noise."
      })
  } else {
    ftd_note <- paste0(
      "The first-two-digit test was skipped: it requires at least 1,000 ",
      "usable values and this data has ", format(n, big.mark = ","),
      " — the 90 two-digit proportions are too noisy below that volume to ",
      "read against an expectation.")
  }

Step 9: Metrics + computed answer

metrics <- list(
    `Values Analyzed` = as.integer(n),
    `MAD`             = round(mad_val, 4),
    `Conformity`      = band,
    `Chi-Square p`    = fmt_p(chi_p),
    `Digits Flagged`  = n_flagged,
    `Verdict`         = verdict
  )

  flagged_digits <- digits[flag != ""]
  flag_txt <- if (n_flagged > 0) {
    paste0(n_flagged, " digit", .s(n_flagged), " (",
           paste(flagged_digits, collapse = ", "), ") deviate",
           if (n_flagged == 1) "s" else "",
           " beyond the 1.96 standardized-residual line. ")
  } else {
    "No individual digit deviates beyond the 1.96 standardized-residual line. "
  }

  json_output <- list(
    answer = paste0(
      "Benford&#x27;s Law screening of ", format(n, big.mark = ","),
      " values from ", hv, ": mean absolute deviation ",
      sprintf("%.4f", mad_val), " — ", band,
      " on Nigrini&#x27;s thresholds — with a chi-square goodness-of-fit ",
      fmt_pp(chi_p), ". Verdict: ", verdict, ". ", flag_txt,
      if (length(applicability_notes) > 0)
        paste0(paste(applicability_notes, collapse = " "), " ") else "",
      "Benford deviation is a screening signal that says where to look ",
      "closer; it is not proof of fabrication or manipulation."
    ),
    cards = lapply(
      c("tldr", "overview", "preprocessing", "digit_distribution",
        "deviations", "data_hygiene", "methods"),
      function(cid) list(id = cid, metrics = metrics)
    )
  )

  list(
    initial_rows = initial_rows, final_rows = final_rows,
    rows_removed = rows_removed,
    hv = hv, n = n,
    n_blank = n_blank, n_zero = n_zero, n_neg = n_neg, n_sub1 = n_sub1,
    obs_p = obs_p, benford_p = benford_p, obs_counts = obs_counts,
    chi_stat = chi_stat, chi_p = chi_p,
    mad_val = mad_val, band = band, verdict = verdict,
    z = z, flag = flag, n_flagged = n_flagged,
    flagged_digits = flagged_digits,
    span_oom = span_oom, n_distinct = n_distinct,
    range_warning = range_warning,
    applicability_notes = applicability_notes,
    ftd_ran = ftd_ran, ftd_chi_p = ftd_chi_p, ftd_mad = ftd_mad,
    ftd_note = ftd_note,
    digit_distribution_df = digit_distribution_df,
    deviations_df = deviations_df,
    data_hygiene_df = data_hygiene_df,
    conformity_bands_df = conformity_bands_df,
    metrics = metrics, json_output = json_output
  )
}
Your data has more stories to tell.Run any analysis on your own data — validated R modules, interactive reports, AI insights, and PDF export. 500 free credits on signup.
Try Free — No SignupSign Up Free

Cite this analysis

Report an Issue

Tell us what's wrong. You'll get a free re-run of this analysis so you can try again with different parameters. If the re-run still doesn't meet your expectations, we'll refund your credits.

Want to run this analysis on your own data? Upload CSV — Free Analysis See Pricing