Descriptive tables

Start with the expanded example for each command. Open the variants for options and alternative R approaches. Read the qualifications before adapting the code.

collapse

Replace rows with group nonmissing counts

Stata

collapse (count) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=sum(!is.na(x)),.by=g)
11 more examples and alternatives

Replace rows with group first values including missing

Stata

collapse (first) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=dplyr::first(x),.by=g)

Replace rows with group first nonmissing values

Stata

collapse (firstnm) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=dplyr::first(x[!is.na(x)]),.by=g)

Replace rows with group last values including missing

Stata

collapse (last) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=dplyr::last(x),.by=g)

Replace rows with group last nonmissing values

Stata

collapse (lastnm) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=dplyr::last(x[!is.na(x)]),.by=g)

Replace rows with group maxima

Stata

collapse (max) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data, z = if (all(is.na(x))) NA_real_ else max(x, na.rm = TRUE), .by = g)

Collapse integer-frequency-weighted values to a mean

Stata

collapse (mean) x [fw=w]

R Package:stats

data <- data.frame(x=stats::weighted.mean(data$x,data$w))

Differs from Stata Frequency-weighted mean only; no inference or weighted-variance formula is implied.

Use common complete cases for group summaries

Stata

collapse (mean) x y, cw by(g)

R Package:dplyr

data <- data[stats::complete.cases(data[c('x','y')]),]; data <- dplyr::summarise(data,dplyr::across(c(x,y),mean),.by=g)

Replace rows with group means

Stata

collapse (mean) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=mean(x,na.rm=TRUE),.by=g)

Replace rows with group medians

Stata

collapse (median) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=stats::median(x,na.rm=TRUE),.by=g)

Replace rows with group minima

Stata

collapse (min) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data, z = if (all(is.na(x))) NA_real_ else min(x, na.rm = TRUE), .by = g)

Replace rows with group totals

Stata

collapse (sum) z=x, by(g)

R Package:dplyr

data <- dplyr::summarise(data,z=sum(x,na.rm=TRUE),.by=g)

contract

Count observed combinations of two categories

Stata

contract g h, freq(n)

R Package:dplyr

data <- dplyr::count(data,g,h,name='n')

Include unobserved combinations with zero frequency

Stata

contract g h, freq(n) zero

R Package:base

data <- as.data.frame(table(data$g,data$h)); names(data) <- c('g','h','n')

Replace observations with category frequencies

Stata

contract g, freq(n)

R Package:dplyr

data <- dplyr::count(data,g,name='n')

Create cumulative frequencies and percentages

Stata

contract g, freq(n) cfreq(cn) cpercent(cp)

R Package:dplyr

data <- dplyr::count(data,g,name='n'); data$cn <- cumsum(data$n); data$cp <- 100*data$cn/sum(data$n)

Create category frequencies and percentages

Stata

contract g, freq(n) percent(p)

R Package:dplyr

data <- dplyr::count(data,g,name='n'); data$p <- 100*data$n/sum(data$n)
2 more examples and alternatives

Create category counts from integer frequency weights

Stata

contract g [fw=w], freq(n)

R Package:dplyr

data <- dplyr::summarise(data,n=sum(w),.by=g)

Exclude missing categories before contracting

Stata

contract g, nomiss

R Package:dplyr

data <- dplyr::count(data[!is.na(data$g)&data$g!='',,drop=FALSE],g,name='_freq')

Differs from Stata Excludes both empty strings and R NA to match Stata’s nonmissing string categories.

summarize

Get detailed empirical percentiles

Stata

summarize x, detail

R Package:base

stats::quantile(data$x,c(.01,.05,.1,.25,.5,.75,.9,.95,.99),na.rm=TRUE,type=2)

Differs from Stata Percentile portion of summarize detail, using R type 2; skewness/kurtosis are not returned here.

1 more examples and alternatives

Compute mean-only summary components

Stata

summarize x, meanonly

R Package:base

c(n=sum(!is.na(data$x)),mean=mean(data$x,na.rm=TRUE),min=min(data$x,na.rm=TRUE),max=max(data$x,na.rm=TRUE))

tab1

Make separate one-way frequency tables

Stata

tab1 g h

R Package:base

lapply(data[c('g','h')],table)

tab2

Make each pairwise contingency table

Stata

tab2 g h k

R Package:base

pairs <- utils::combn(c('g','h','k'),2,simplify=FALSE); lapply(pairs,function(p) table(data[[p[1]]],data[[p[2]]]))

tabdisp

Display a complete table of precomputed cell values

Stata

tabdisp g h, cellvar(value)

R Package:stats

stopifnot(!anyDuplicated(data[c('g','h')])); stats::xtabs(value~g+h,data=data,na.action=stats::na.pass)

Differs from Stata Requires one row for every cell and unique keys; xtabs would otherwise sum duplicates or fill absent cells with zero.

tabstat

Compare count, mean and spread across numeric columns

Stata

tabstat x y, statistics(n mean sd) columns(statistics)

R Package:base

sapply(data[c('x','y')],function(z) c(n=sum(!is.na(z)),mean=mean(z,na.rm=TRUE),sd=stats::sd(z,na.rm=TRUE)))
14 more examples and alternatives

Summarize nonmissing counts and means by category

Stata

tabstat x, by(g) statistics(n mean)

R Package:dplyr

data |> dplyr::group_by(g) |> dplyr::summarise(n=sum(!is.na(x)),mean=mean(x,na.rm=TRUE),.groups='drop')

Return the interquartile range as a descriptive statistic

Stata

tabstat x, statistics(iqr)

R Package:base

with(data,diff(stats::quantile(x,c(.25,.75),na.rm=TRUE,type=2)))

Differs from Stata Uses the Stata-default empirical percentile rule through R quantile type 2.

Return the maximum as a descriptive statistic

Stata

tabstat x, statistics(max)

R Package:base

with(data,max(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the mean as a descriptive statistic

Stata

tabstat x, statistics(mean)

R Package:base

with(data,mean(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the minimum as a descriptive statistic

Stata

tabstat x, statistics(min)

R Package:base

with(data,min(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the nonmissing count as a descriptive statistic

Stata

tabstat x, statistics(n)

R Package:base

with(data,sum(!is.na(x)))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the 25th percentile as a descriptive statistic

Stata

tabstat x, statistics(p25)

R Package:base

with(data,as.numeric(stats::quantile(x,.25,na.rm=TRUE,type=2)))

Differs from Stata Uses the Stata-default empirical percentile rule through R quantile type 2.

Return the median as a descriptive statistic

Stata

tabstat x, statistics(p50)

R Package:base

with(data,stats::median(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the 75th percentile as a descriptive statistic

Stata

tabstat x, statistics(p75)

R Package:base

with(data,as.numeric(stats::quantile(x,.75,na.rm=TRUE,type=2)))

Differs from Stata Uses the Stata-default empirical percentile rule through R quantile type 2.

Return the range as a descriptive statistic

Stata

tabstat x, statistics(range)

R Package:base

with(data,diff(range(x,na.rm=TRUE)))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the sample standard deviation as a descriptive statistic

Stata

tabstat x, statistics(sd)

R Package:base

with(data,stats::sd(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the standard error of the mean as a descriptive statistic

Stata

tabstat x, statistics(semean)

R Package:base

with(data,stats::sd(x,na.rm=TRUE)/sqrt(sum(!is.na(x))))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the sum as a descriptive statistic

Stata

tabstat x, statistics(sum)

R Package:base

with(data,sum(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

Return the sample variance as a descriptive statistic

Stata

tabstat x, statistics(variance)

R Package:base

with(data,stats::var(x,na.rm=TRUE))

Differs from Stata Unweighted descriptive statistic; no survey or sampling-design correction is applied.

tabulate

Count a single categorical variable

Stata

tabulate g

R Package:base

table(data$g)
7 more examples and alternatives

Tabulate integer frequency weights

Stata

tabulate g [fw=w]

R Package:stats

stats::xtabs(w~g,data=data,na.action=stats::na.pass)

Count a two-way contingency table

Stata

tabulate g h

R Package:base

table(data$g,data$h)

Compute percentages of all table cells

Stata

tabulate g h, cell

R Package:base

100*prop.table(table(data$g,data$h))

Compute percentages within each table column

Stata

tabulate g h, column

R Package:base

100*prop.table(table(data$g,data$h),margin=2)

Compute percentages within each table row

Stata

tabulate g h, row

R Package:base

100*prop.table(table(data$g,data$h),margin=1)

Create a full set of category indicators

Stata

tabulate g, generate(d)

R Package:tidystata

indicators <- tidystata::as_dummy(dplyr::select(data, g), g, .remove = TRUE)

Differs from Stata Keeps all observations; a missing category gives NA in every dummy. R returns a separate data frame with category-based names; the Stata stub d is not a templated output name.

Include missing categories in a frequency table

Stata

tabulate g, missing

R Package:base

table(data$g,useNA='ifany')

Differs from Stata Maps R NA to an explicit table category; empty character strings remain a separate R value.