Summarise selected variables, with one row per variable and group:
summ(): Report counts, distinct-value counts, minimum, mean, standard deviation, and maximum by default.tabstat(): Report means by default, using the same calculations and options assumm().
Both support .detail = TRUE for a fuller summary or .stat to select
statistics.
Usage
summ(
.data,
...,
.by = NULL,
.keep_all = FALSE,
.detail = FALSE,
.stat = character(0),
.missing = TRUE,
.name = FALSE,
.type = c("list", "table"),
.duration_format = c("long", "compact"),
.sort = TRUE,
.drop_empty = FALSE,
.wt = NULL,
.wt_type = c("frequency", "analytic")
)
tabstat(
.data,
...,
.by = NULL,
.keep_all = FALSE,
.detail = FALSE,
.stat = "mean",
.missing = TRUE,
.name = FALSE,
.type = c("list", "table"),
.duration_format = c("long", "compact"),
.sort = TRUE,
.drop_empty = FALSE,
.wt = NULL,
.wt_type = c("frequency", "analytic")
)Arguments
- .data
A data frame, tibble, data.table, or vector. For
sfdata, only attributes are summarised; geometry columns are excluded.- ...
Variables selected with tidyselect, or named expressions such as
income_k = income / 1000. Defaults to all nongrouping columns.- .by
Optional grouping columns, selected with tidyselect. Existing
dplyr::group_by()groups are used unless.byis supplied. Grouping columns are excluded from the variables being summarised.- .keep_all
If
TRUE, retain character and list columns for counts and distinct values; other statistics for these columns areNA. By default, unsupported columns are omitted with a warning.- .detail
If
TRUE, report all supported statistics unless.statspecifies a subset. Defaults toFALSE.- .stat
Character vector of statistics to report. See Details for the complete list and calculation methods. An explicit selection determines the statistics and their order. Use
p0top100for percentiles, including decimals such asp2.5.- .missing
If
TRUE(default), retain observations with missing grouping keys as a separate group. IfFALSE, exclude them. Missing measured values are always omitted from numeric calculations.- .name
If
TRUE, always include thenamecolumn. By default, it is omitted when exactly one variable is summarised.- .type
"list"(default) separates numeric and calendar variable families where necessary;"table"combines them into one table.- .duration_format
Retained for compatibility; no longer changes the output format of calendar spread statistics.
- .sort
If
TRUE(default), sort groups by their keys. IfFALSE, preserve the order in which groups appear in the data.- .drop_empty
If
TRUE, omit variable-group rows withn = 0, including rows with no observed measured values or zero total weight. Defaults toFALSE.- .wt
Optional numeric weights, supplied as a column or a vector. Rows with missing weights are excluded; negative weights are invalid.
- .wt_type
"frequency"(default) treats weights as frequencies;"analytic"rescales weights to the number of observed values within each variable and group. See Details for the calculation differences.
Value
An ungrouped table, or a list of tables, with one row per variable
and group. Each table contains grouping keys (if any), name (when
applicable), type, and the selected statistics.
By default, summ() returns n, unique, min, mean, sd, and max;
tabstat() returns mean. With .type = "list", results are split into
numeric, date, datetime, and time tables only when multiple type
families occur. With .type = "table", all types are combined in one table.
Results retain the input's usual table class where supported.
Details
Statistics are calculated separately for each selected variable and group.
The formulas below use non-missing measured values x1, ..., xn, with
n denoting their count and xbar their arithmetic mean. Unless weights
are supplied, calculations are unweighted.
Counts and completeness
type: Variable type (metadata, not a calculated statistic).n: Number of non-missing values.unique: Number of distinct non-missing values.miss_n: Number of missing values (alias:missing).valid_pct: Proportion of rows with a non-missing value, between 0 and 1;n / (n + miss_n)without weights. It is not multiplied by 100.
Location and totals
min,max: Smallest and largest observed values.sum: Arithmetic total,sum(x). Available for numeric variables only.mean: Arithmetic mean,sum(x) / n.q1(p25),median(p50),q3(p75): 25th, 50th, and 75th percentiles, respectively.p0top100: Any requested percentile, including decimal percentages such asp2.5. Percentiles follow Stata's rule, not R's defaultstats::quantile()type 7. For sorted observations and percentilep, seth = n * p / 100. Ifhis not an integer, use the observation at positionceiling(h); ifhis an integer between 1 andn - 1, average the observations at positionshandh + 1. The endpoints are the minimum (p0) and maximum (p100). For example, the 25th percentile of1:4is 1.5, rather than 1.75 from type 7.
Variation and precision
sd: Sample standard deviation,sqrt(sum((x - xbar)^2) / (n - 1)).se: Standard error of the mean,sd / sqrt(n).mad: Median absolute deviation from the median, multiplied by 1.4826, as instats::mad(). This is not a statistic reported by Stata'ssummarizecommand.iqr: Interquartile range,q3 - q1, using the percentiles above.
Distribution shape
Define mk = sum((x - xbar)^k) / n, the kth population central moment.
skew: Skewness,m3 / m2^(3/2).kurtosis: Pearson kurtosis,m4 / m2^2. A normal distribution has kurtosis 3, not 0 (this is not excess kurtosis).
Undefined statistics are NA (for example, sd when n < 2 and the
shape statistics for constant variables). Columns with no observed values
have n = 0, unique = 0, and NA for numeric statistics, including sum.
When weights are supplied
Let w be the weights and W = sum(w) over non-missing measured values.
Frequency weights (
.wt_type = "frequency") use weights as given. The reportednisW; non-integer weights are permitted.Analytic weights (
.wt_type = "analytic") are rescaled within each variable and group so thatWequals the number of observed values. Thusnremains on the sample-count scale.Mean and spread:
mean = sum(w * x) / W,sd = sqrt(sum(w * (x - mean)^2) / (W - 1)), andse = sd / sqrt(W). The two weight types give the same mean but can give differentsdandsevalues.Quantiles and MAD: Percentiles use Stata's weighted percentile rule, replacing positions with cumulative weights; weighted
maduses the corresponding weighted medians.minandmaxexclude zero-weight rows.Totals and counts:
sumissum(w * x)using the original, unrescaled weights, even for analytic weights.unique,miss_n, andvalid_pctcontinue to use unweighted row counts.
The reported se is descriptive and does not account for a complex survey
design. For survey inference, use functions such as survey::svymean().
Data types and grouping
Missingness follows is.na(), including SPSS user-missing codes. Logical
variables are treated as 0/1; factors use their underlying numeric codes;
labelled numeric variables use their stored values. Warnings flag such
conversions. Variable names are marked with * for labelled variables,
** for factors, and *** for retained nonnumeric variables. Numeric
calculations use double precision, which may affect large integer64 values.
Dates and datetimes support location and spread statistics, but not sum,
skew, or kurtosis. Calendar locations are displayed as dates or times;
their spreads (sd, se, mad, iqr) are difftime values in list mode.
In combined table mode, calendar locations are text and spreads are numeric
durations (days for Dates, seconds for datetimes and times of day).
Expressions in ... are evaluated before statistics are calculated by
group. For group-specific expressions, first create columns with grouped
dplyr::mutate().
Examples
summ(lifeexp)
#> Warning: country is non-numeric and thus removed.
#> Warning: region is a labelled variable (*).
#> # A tibble: 5 x 8
#> name type n unique min mean sd max
#> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 *region dbl+lbl 68 3 1 1.5 0.743 3
#> 2 popgrowth dbl 68 32 -2.5 0.553 1.06 2.6
#> 3 lexp dbl 68 20 57 71.7 5.16 79
#> 4 gnppc dbl 67 64 170 9137. 11497. 46650
#> 5 safewater dbl 54 32 36 77.2 20.6 100
summ(lifeexp, .by = region)
#> Warning: country is non-numeric and thus removed.
#> # A tibble: 12 x 9
#> region name type n unique min mean sd max
#> <dbl+lbl> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 [Europe & C. Asia] popgrow~ dbl 44 25 -2.5 7.05e-2 9.10e-1 1.8 e0
#> 2 1 [Europe & C. Asia] lexp dbl 44 17 62 7.25e+1 4.95e+0 7.9 e1
#> 3 1 [Europe & C. Asia] gnppc dbl 43 42 170 1.13e+4 1.29e+4 4.66e4
#> 4 1 [Europe & C. Asia] safewat~ dbl 42 25 36 8.16e+1 1.86e+1 1 e2
#> 5 2 [North America] popgrow~ dbl 14 11 0.3 1.33e+0 7.80e-1 2.6 e0
#> 6 2 [North America] lexp dbl 14 13 57 6.97e+1 6.14e+0 7.9 e1
#> 7 2 [North America] gnppc dbl 14 14 410 6.29e+3 9.08e+3 3.20e4
#> 8 2 [North America] safewat~ dbl 6 5 40 5.8 e+1 2.40e+1 9.9 e1
#> 9 3 [South America] popgrow~ dbl 10 7 0.5 1.59e+0 4.89e-1 2.2 e0
#> 10 3 [South America] lexp dbl 10 8 61 7.07e+1 4.06e+0 7.6 e1
#> 11 3 [South America] gnppc dbl 10 9 960 3.88e+3 2.43e+3 7.96e3
#> 12 3 [South America] safewat~ dbl 6 6 45 6.53e+1 1.70e+1 9.1 e1
tabstat(lifeexp, .by = region)
#> Warning: country is non-numeric and thus removed.
#> # A tibble: 12 x 4
#> region name type mean
#> <dbl+lbl> <chr> <chr> <dbl>
#> 1 1 [Europe & C. Asia] popgrowth dbl 0.0705
#> 2 1 [Europe & C. Asia] lexp dbl 72.5
#> 3 1 [Europe & C. Asia] gnppc dbl 11284.
#> 4 1 [Europe & C. Asia] safewater dbl 81.6
#> 5 2 [North America] popgrowth dbl 1.33
#> 6 2 [North America] lexp dbl 69.7
#> 7 2 [North America] gnppc dbl 6294.
#> 8 2 [North America] safewater dbl 58
#> 9 3 [South America] popgrowth dbl 1.59
#> 10 3 [South America] lexp dbl 70.7
#> 11 3 [South America] gnppc dbl 3881
#> 12 3 [South America] safewater dbl 65.3
# Compare frequency and analytic weights
survey <- tibble::tibble(income = c(10, 20, 40), w = c(3, 1, 1))
summ(survey, income, .wt = w, .stat = c("n", "mean", "sd", "p50"))
#> # A tibble: 1 x 5
#> type n mean sd p50
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 dbl 5 18 13.0 10
summ(survey, income, .wt = w, .wt_type = "analytic", .stat = c("n", "sd"))
#> # A tibble: 1 x 3
#> type n sd
#> <chr> <dbl> <dbl>
#> 1 dbl 3 14.3
lifeexp |>
summ(
dplyr::where(is.numeric),
.by = region,
.stat = c("n", "mean", "sd", "p50")
)
#> # A tibble: 12 x 7
#> region name type n mean sd p50
#> <dbl+lbl> <chr> <chr> <int> <dbl> <dbl> <dbl>
#> 1 1 [Europe & C. Asia] popgrowth dbl 44 0.0705 0.910 0.1
#> 2 1 [Europe & C. Asia] lexp dbl 44 72.5 4.95 72.5
#> 3 1 [Europe & C. Asia] gnppc dbl 43 11284. 12920. 4150
#> 4 1 [Europe & C. Asia] safewater dbl 42 81.6 18.6 88.5
#> 5 2 [North America] popgrowth dbl 14 1.33 0.780 1.35
#> 6 2 [North America] lexp dbl 14 69.7 6.14 70.5
#> 7 2 [North America] gnppc dbl 14 6294. 9080. 2680
#> 8 2 [North America] safewater dbl 6 58 24.0 46
#> 9 3 [South America] popgrowth dbl 10 1.59 0.489 1.8
#> 10 3 [South America] lexp dbl 10 70.7 4.06 71.5
#> 11 3 [South America] gnppc dbl 10 3881 2432. 2990
#> 12 3 [South America] safewater dbl 6 65.3 17.0 65
# Exclude rows with missing group keys
summ(lifeexp, .by = region, .missing = FALSE)
#> Warning: country is non-numeric and thus removed.
#> # A tibble: 12 x 9
#> region name type n unique min mean sd max
#> <dbl+lbl> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 [Europe & C. Asia] popgrow~ dbl 44 25 -2.5 7.05e-2 9.10e-1 1.8 e0
#> 2 1 [Europe & C. Asia] lexp dbl 44 17 62 7.25e+1 4.95e+0 7.9 e1
#> 3 1 [Europe & C. Asia] gnppc dbl 43 42 170 1.13e+4 1.29e+4 4.66e4
#> 4 1 [Europe & C. Asia] safewat~ dbl 42 25 36 8.16e+1 1.86e+1 1 e2
#> 5 2 [North America] popgrow~ dbl 14 11 0.3 1.33e+0 7.80e-1 2.6 e0
#> 6 2 [North America] lexp dbl 14 13 57 6.97e+1 6.14e+0 7.9 e1
#> 7 2 [North America] gnppc dbl 14 14 410 6.29e+3 9.08e+3 3.20e4
#> 8 2 [North America] safewat~ dbl 6 5 40 5.8 e+1 2.40e+1 9.9 e1
#> 9 3 [South America] popgrow~ dbl 10 7 0.5 1.59e+0 4.89e-1 2.2 e0
#> 10 3 [South America] lexp dbl 10 8 61 7.07e+1 4.06e+0 7.6 e1
#> 11 3 [South America] gnppc dbl 10 9 960 3.88e+3 2.43e+3 7.96e3
#> 12 3 [South America] safewat~ dbl 6 6 45 6.53e+1 1.70e+1 9.1 e1
# Summarise existing and computed columns together
summ(lifeexp, lexp, gnppc_thousands = gnppc / 1000, .by = region)
#> # A tibble: 6 x 9
#> region name type n unique min mean sd max
#> <dbl+lbl> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 [Europe & C. Asia] lexp dbl 44 17 62 72.5 4.95 79
#> 2 1 [Europe & C. Asia] gnppc_thousan~ dbl 43 42 0.17 11.3 12.9 46.6
#> 3 2 [North America] lexp dbl 14 13 57 69.7 6.14 79
#> 4 2 [North America] gnppc_thousan~ dbl 14 14 0.41 6.29 9.08 32.0
#> 5 3 [South America] lexp dbl 10 8 61 70.7 4.06 76
#> 6 3 [South America] gnppc_thousan~ dbl 10 9 0.96 3.88 2.43 7.96
tabstat(lifeexp, lexp, gnppc_thousands = gnppc / 1000)
#> # A tibble: 2 x 3
#> name type mean
#> <chr> <chr> <dbl>
#> 1 lexp dbl 71.7
#> 2 gnppc_thousands dbl 9.14
# Separate numeric and calendar summaries
mixed <- tibble::tibble(x = c(1, 3), day = as.Date("2024-01-01") + 0:1)
summ(mixed, .type = "list")
#> A list is returned as statistics are heterogeneous.
#> $numeric
#> # A tibble: 1 x 8
#> name type n unique min mean sd max
#> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 x dbl 2 2 1 2 1.41 3
#>
#> $date
#> # A tibble: 1 x 8
#> name type n unique mean sd min max
#> <chr> <chr> <int> <int> <chr> <drtn> <chr> <chr>
#> 1 day date 2 2 2024-01-01 0.7071068 days 2024-01-01 2024-01-02
#>
# Preserve a variable name when starting from a vector
scores <- c(4, 6, NA, 8)
tibble::tibble(score = scores) |> summ(.name = TRUE)
#> # A tibble: 1 x 8
#> name type n unique min mean sd max
#> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 score dbl 3 3 4 6 2 8