Data management
Start with the expanded example for each command. Open the variants for options and alternative R approaches. Read the qualifications before adapting the code.
append
Append tables allowing different column sets
Stata
append using other.dtaR Package:dplyr
data <- dplyr::bind_rows(data,other)Fixed workflow example; adapt the object and column names together.
2 more examples and alternatives
Append only selected columns from the using table
Stata
append using other.dta, keep(x)R Package:dplyr
data <- dplyr::bind_rows(data,other['x'])Record origin while appending several datasets
Stata
append using second.dta third.dta, generate(source)R Package:dplyr
data <- dplyr::bind_rows(list('0'=data,'1'=second,'2'=third),.id='source'); data$source <- as.integer(data$source)assertnested
Assert a group attribute is constant for each identifier
Stata
assertnested id, within(g)R Package:base
stopifnot(all(vapply(split(data$g,data$id),function(z) length(unique(z))==1L,logical(1))))Assert that districts belong to one region
Stata
assertnested region districtR Package:base
stopifnot(all(vapply(split(data$region,data$district),function(z) length(unique(z))==1L,logical(1))))cf
Locate differing rows in a selected column
Stata
cf x using other.dta, verboseR Package:base
which(data$x != other$x | xor(is.na(data$x),is.na(other$x)))Workflow inspects x only; compare each column for the complete verbose report.
Assert selected dataset values match
Stata
cf x y using other.dtaR Package:base
stopifnot(identical(unname(as.matrix(data[c('x','y')])),unname(as.matrix(other[c('x','y')]))))Differs from Stata Compares the supplied in-memory other table in row order; ignores metadata as cf does.
clonevar
Copy a column and its attributes
Stata
clonevar copy = xR Package:base
data$copy <- data$xcodebook
Describe observed count, distinct count and range
Stata
codebook x, compactR Package:base
c(nonmissing=sum(!is.na(data$x)),unique=length(unique(data$x[!is.na(data$x)])),min=min(data$x,na.rm=TRUE),max=max(data$x,na.rm=TRUE))Differs from Stata Numeric codebook subset; does not reproduce Stata’s variable-label and format report.
compare
Compare value ordering and missingness
Stata
compare x yR Package:base
c(less=sum(data$x<data$y,na.rm=TRUE),equal=sum(data$x==data$y,na.rm=TRUE),greater=sum(data$x>data$y,na.rm=TRUE),x_missing_only=sum(is.na(data$x)&!is.na(data$y)),both_missing=sum(is.na(data$x)&is.na(data$y)))Differs from Stata Produces the principal comparison counts; not Stata’s formatted difference summary.
Compare ordering inside a subset
Stata
compare x y if g == 1R Package:base
with(subset(data,g==1),table(sign(x-y),useNA='ifany'))Differs from Stata Returns ordering counts only; use a separate summary for difference magnitudes.
compress
Reduce safe whole-number storage to R integers
Stata
compress xR Package:base
stopifnot(all(is.na(data$x) | (data$x==trunc(data$x) & abs(data$x)<=.Machine$integer.max))); data$x <- as.integer(data$x)Manual whole-number optimization only. R has no Stata byte/int storage classes or general compress equivalent.
count
Count rows complete on selected columns
Stata
count if !missing(x, y)R Package:base
sum(stats::complete.cases(data[c('x','y')]))3 more examples and alternatives
Count missing values
Stata
count if missing(x)R Package:base
sum(is.na(data$x))Count observed values above a threshold
Stata
count if x > 2 & x < .R Package:base
sum(data$x > 2,na.rm=TRUE)Count a row interval
Stata
count in 2/5R Package:base
nrow(data[2:5,,drop=FALSE])Fixed workflow example; adapt the object and column names together.
cross
Form the Cartesian product of two datasets
Stata
cross using other.dtaR Package:dplyr
data <- dplyr::cross_join(data,other)Fixed workflow example; adapt the object and column names together.
cumul
Create the empirical cumulative distribution of a variable
Stata
cumul x, generate(c)R Package:dplyr
data$c <- dplyr::row_number(data$x) / sum(!is.na(data$x))Differs from Stata Missing values stay missing and are excluded from the denominator. By default Stata gives tied values distinct cumulatives in an arbitrary order; R breaks ties by row order. Weights and by() need an explicit grouped or weighted version.
1 more examples and alternatives
Cumulative distribution with equal values for ties
Stata
cumul x, generate(c) equalR Package:dplyr
data$c <- dplyr::cume_dist(data$x)Tied values share the largest cumulative proportion, as ecdf(x)(x) does; missing values stay missing.
datasignature
Assert data match a stored R signature
Stata
datasignature confirmR Package:base
stopifnot(identical(signature,serialize(data,NULL,version=2)))R-specific byte comparison; not interoperable with Stata .dtasig files.
Store an exact R serialization for later comparison
Stata
datasignature setR Package:base
signature <- serialize(data,NULL,version=2)R-specific serialized snapshot; not Stata’s checksum algorithm, and R metadata is included.
describe
Inspect storage types of selected columns
Stata
describe x yR Package:base
vapply(data[c('x','y')],typeof,character(1))1 more examples and alternatives
Get dataset dimensions compactly
Stata
describe, shortR Package:base
c(observations=nrow(data),variables=ncol(data))Fixed workflow example; adapt the object and column names together.
destring
Parse clean numeric strings
Stata
destring s, generate(x)R Package:base
data$x <- as.numeric(data$s)3 more examples and alternatives
Parse a decimal-comma field
Stata
destring s, generate(x) dpcommaR Package:base
data$x <- as.numeric(sub(',','.',data$s,fixed=TRUE))Parse numbers containing grouping commas
Stata
destring s, generate(x) ignore(",")R Package:base
data$x <- as.numeric(gsub(',','',data$s,fixed=TRUE))Convert percentage text to proportions
Stata
destring s, generate(x) percentR Package:base
data$x <- as.numeric(sub('%$','',data$s))/100drop
Drop a category of rows
Stata
drop if g == 2R Package:base
data <- data[data$g != 2, , drop=FALSE]5 more examples and alternatives
Drop rows missing a value
Stata
drop if missing(x)R Package:base
data <- data[!is.na(data$x), , drop=FALSE]Drop rows incomplete on selected columns
Stata
drop if missing(x, y)R Package:tidyr
data <- tidyr::drop_na(data, x, y)Drop low values while retaining missing rows
Stata
drop if x <= 2R Package:dplyr
data <- dplyr::filter(data, is.na(x) | x > 2)Differs from Stata Stata numeric missing sorts above finite values; the explicit is.na branch preserves those rows.
Drop a row interval
Stata
drop in 2/4R Package:base
data <- data[-(2:4), , drop=FALSE]Fixed workflow example; adapt the object and column names together.
Remove selected columns
Stata
drop s yR Package:base
data <- data[setdiff(names(data),c('s','y'))]ds
Find columns outside an exclusion list
Stata
ds id g, notR Package:base
setdiff(names(data),c('id','g'))2 more examples and alternatives
Find names of numeric columns
Stata
ds, has(type numeric)R Package:base
names(data)[vapply(data,is.numeric,logical(1))]Fixed workflow example; adapt the object and column names together.
Find names of character columns
Stata
ds, has(type string)R Package:base
names(data)[vapply(data,is.character,logical(1))]Fixed workflow example; adapt the object and column names together.
duplicates
Retain the first observation per duplicated key
Stata
duplicates drop id, forceR Package:base
data <- data[!duplicated(data$id),,drop=FALSE]3 more examples and alternatives
Inspect all members of duplicated keys
Stata
duplicates list idR Package:base
data[duplicated(data$id)|duplicated(data$id,fromLast=TRUE),,drop=FALSE]Summarize copies, observations and duplicate surplus
Stata
duplicates report idR Package:base
counts <- as.integer(table(data$id)); data.frame(copies=sort(unique(counts)),observations=vapply(sort(unique(counts)),function(k) sum(counts[counts==k]),integer(1)),surplus=vapply(sort(unique(counts)),function(k) sum(counts==k)*(k-1L),integer(1)))Tag all group members with duplicate surplus count
Stata
duplicates tag id, generate(dup)R Package:dplyr
data <- dplyr::mutate(data,dup=dplyr::n()-1L,.by=id)egen
Attach group means without collapsing rows
Stata
bysort g: egen z = mean(x)R Package:dplyr
data <- dplyr::mutate(data,z=mean(x,na.rm=TRUE),.by=g)30 more examples and alternatives
Attach group totals without collapsing rows
Stata
bysort g: egen z = total(x)R Package:dplyr
data <- dplyr::mutate(data,z=sum(x,na.rm=TRUE),.by=g)Count listed values across columns
Stata
egen z = anycount(x y), values(2 4)R Package:base
data$z <- rowSums(cbind(data$x %in% c(2,4),data$y %in% c(2,4)))Flag any listed value across columns
Stata
egen z = anymatch(x y), values(2 4)R Package:base
data$z <- as.integer(data$x %in% c(2,4) | data$y %in% c(2,4))Concatenate numeric and string columns
Stata
egen z = concat(g s), punct("-")R Package:base
data$z <- paste(data$g,ifelse(is.na(data$s),'',data$s),sep='-')Differs from Stata Treats R NA strings as Stata empty strings; numeric formatting is simple decimal here.
Repeat the nonmissing count in a column
Stata
egen z = count(x)R Package:base
data$z <- sum(!is.na(data$x))Bin values and label bins by lower endpoint
Stata
egen z = cut(x), at(0,3,7)R Package:base
data$z <- as.numeric(as.character(cut(data$x,breaks=c(0,3,7),right=FALSE,labels=c(0,3))))Flag differing values across two columns
Stata
egen z = diff(x y)R Package:base
data$z <- as.integer(!(data$x==data$y | (is.na(data$x)&is.na(data$y)))); data$z[xor(is.na(data$x),is.na(data$y))] <- 1LDiffers from Stata Ordinary missing is handled explicitly; extended Stata missing categories need separate comparison.
Repeat the first nonmissing value
Stata
egen z = firstnm(x)R Package:base
data$z <- data$x[which(!is.na(data$x))[1]]Encode combinations of group keys
Stata
egen z = group(g s)R Package:base
data$z <- as.integer(interaction(data$g,data$s,drop=TRUE,lex.order=TRUE)); data$z[is.na(data$s) | data$s==''] <- NA_integer_Differs from Stata Combination IDs identify groups; exact numeric codes and string collation may differ from Stata.
Repeat the interquartile range
Stata
egen z = iqr(x)R Package:base
data$z <- diff(stats::quantile(data$x,c(.25,.75),na.rm=TRUE,type=2))Differs from Stata Uses R quantile type 2 for Stata’s default empirical percentile rule.
Repeat the last nonmissing value
Stata
egen z = lastnm(x)R Package:base
data$z <- utils::tail(c(NA_real_, data$x[!is.na(data$x)]), 1)Repeat the maximum in a column
Stata
egen z = max(x)R Package:base
data$z <- if (all(is.na(data$x))) NA_real_ else max(data$x, na.rm=TRUE)Repeat the mean in a column
Stata
egen z = mean(x)R Package:base
data$z <- mean(data$x,na.rm=TRUE)Repeat the median in a column
Stata
egen z = median(x)R Package:base
data$z <- stats::median(data$x,na.rm=TRUE)Repeat the minimum in a column
Stata
egen z = min(x)R Package:base
data$z <- if (all(is.na(data$x))) NA_real_ else min(data$x, na.rm=TRUE)Express values as percentages of the column total
Stata
egen z = pc(x)R Package:base
data$z <- 100*data$x/sum(data$x,na.rm=TRUE)Requires a nonzero observed total; this is a share calculation, not survey estimation.
Repeat a specified empirical percentile
Stata
egen z = pctile(x), p(25)R Package:base
data$z <- as.numeric(stats::quantile(data$x,.25,na.rm=TRUE,type=2))Differs from Stata Uses R quantile type 2 for Stata’s default empirical percentile rule.
Rank observed values using average ties
Stata
egen z = rank(x)R Package:base
data$z <- rank(data$x,na.last='keep',ties.method='average')Rank highest value first with competition ties
Stata
egen z = rank(x), fieldR Package:base
data$z <- rank(-data$x,na.last='keep',ties.method='min')Find the available row maximum
Stata
egen z = rowmax(x y)R Package:base
data$z <- pmax(data$x,data$y,na.rm=TRUE)Average available values across columns
Stata
egen z = rowmean(x y)R Package:base
data$z <- rowMeans(data[c('x','y')],na.rm=TRUE); data$z[is.nan(data$z)] <- NA_real_Find the available row minimum
Stata
egen z = rowmin(x y)R Package:base
data$z <- pmin(data$x,data$y,na.rm=TRUE)Count missing cells in each row
Stata
egen z = rowmiss(x y)R Package:base
data$z <- rowSums(is.na(data[c('x','y')]))Count observed cells in each row
Stata
egen z = rownonmiss(x y)R Package:base
data$z <- rowSums(!is.na(data[c('x','y')]))Sum available values across columns
Stata
egen z = rowtotal(x y)R Package:base
data$z <- rowSums(data[c('x','y')],na.rm=TRUE)Return missing for entirely missing row totals
Stata
egen z = rowtotal(x y), missingR Package:base
data$z <- rowSums(data[c('x','y')],na.rm=TRUE); data$z[rowSums(!is.na(data[c('x','y')]))==0] <- NA_real_Repeat the sample standard deviation in a column
Stata
egen z = sd(x)R Package:base
data$z <- stats::sd(data$x,na.rm=TRUE)Standardize using the sample standard deviation
Stata
egen z = std(x)R Package:base
data$z <- as.numeric(scale(data$x))Tag the first observed row of each group
Stata
egen z = tag(g)R Package:base
data$z <- as.integer(!is.na(data$g) & !duplicated(data$g))Repeat the sum in a column
Stata
egen z = total(x)R Package:base
data$z <- sum(data$x,na.rm=TRUE)expandcl
Duplicate whole groups with fresh group identifiers
Stata
expandcl 2, cluster(g) generate(newg)R Package:base
parts <- split(data,data$g); data <- do.call(rbind,lapply(seq_along(parts),function(k) do.call(rbind,lapply(1:2,function(j) transform(parts[[k]],newg=(k-1L)*2L+j)))))Differs from Stata Validates cluster membership and copy counts; the numeric assignment/order of new IDs may differ from Stata.
fcollapse
Collapse means with the ftools public helper
Stata
fcollapse (mean) z=x, by(g)R Package:dplyr
data <- dplyr::summarise(data,z=mean(x,na.rm=TRUE),.by=g)Merge fcollapse group summaries back into original rows
Stata
fcollapse (mean) z=x, by(g) mergeR Package:dplyr
data <- dplyr::mutate(data,z=mean(x,na.rm=TRUE),.by=g)Preserve missing for entirely missing group sums
Stata
fcollapse (nansum) z=x, by(g)R Package:dplyr
data <- dplyr::summarise(data,z=if(all(is.na(x))) NA_real_ else sum(x,na.rm=TRUE),.by=g)fillin
Insert absent combinations of categorical keys
Stata
fillin g hR Package:tidyr
data <- tidyr::complete(data,g,h)Differs from Stata Returns the rectangularized table without Stata’s _fillin indicator; factor levels may add unused R categories.
1 more examples and alternatives
Mark rows inserted during categorical rectangularization
Stata
fillin g hR Package:tidyr
data$`_fillin` <- 0L; data <- tidyr::complete(data,g,h,fill=list(`_fillin`=1L))flevelsof
Store observed categories from the ftools levels helper
Stata
flevelsof g, local(groups)R Package:base
groups <- sort(unique(data$g[!is.na(data$g)]))fmerge
Perform a validated ftools-style one-to-one merge
Stata
fmerge 1:1 id using other.dta, nogenerateR Package:dplyr
data <- dplyr::full_join(data,other,by='id',relationship='one-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
fralias
Read linked values dynamically without storing a copied column
Stata
fralias add score, from(link)R Package:base
get_score <- function() lookup$score[match(data$id,lookup$id)]R accessor-function workflow, not an alias column: call get_score() each time; modifications belong in lookup.
frget
Rename a linked value when copying it
Stata
frget newscore=score, from(link)R Package:base
data$newscore <- lookup$score[data$link]Value-copy workflow; frame linkage and Stata metadata are not carried into R.
Copy a value through an established table link
Stata
frget score, from(link)R Package:base
data$score <- lookup$score[data$link]Differs from Stata Copies values using the precomputed link. Stata display formats and metadata require explicit copying in R.
frlink
Validate and construct a one-to-one table link
Stata
frlink 1:1 id, frame(lookup)R Package:base
stopifnot(!anyDuplicated(data$id),!anyDuplicated(lookup$id)); link <- match(data$id,lookup$id)link is a fixed R object name; unmatched keys produce NA. Rebuild after source changes.
Build a many-to-one row link to a lookup table
Stata
frlink m:1 id, frame(lookup) generate(link)R Package:base
stopifnot(!anyDuplicated(lookup$id)); data$link <- match(data$id,lookup$id)R match indices are a snapshot and must be rebuilt after lookup row reordering.
frunalias
Materialize a dynamically looked-up value as a column
Stata
frunalias scoreR Package:base
data$score <- lookup$score[match(data$id, lookup$id)]Materialize an ordinary R column snapshot. Requires data and lookup tables with matching id keys and a lookup score column; later lookup changes do not change this column.
gcollapse
Collapse group means using the gcollapse workflow
Stata
gcollapse (mean) z=x, by(g)R Package:dplyr
data <- dplyr::summarise(data,z=mean(x,na.rm=TRUE),.by=g)Keep raw group row counts beside collapsed means
Stata
gcollapse (mean) z=x, by(g) freq(n)R Package:dplyr
data <- dplyr::summarise(data,z=mean(x,na.rm=TRUE),n=dplyr::n(),.by=g)Add collapsed group means back to all original rows
Stata
gcollapse (mean) z=x, by(g) mergeR Package:dplyr
data <- dplyr::mutate(data,z=mean(x,na.rm=TRUE),.by=g)Collapse group missing-value counts
Stata
gcollapse (nmissing) n=x, by(g)R Package:dplyr
data <- dplyr::summarise(data,n=sum(is.na(x)),.by=g)Collapse group distinct-value counts on complete data
Stata
gcollapse (nunique) n=x, by(g)R Package:dplyr
data <- dplyr::summarise(data,n=dplyr::n_distinct(x,na.rm=TRUE),.by=g)Differs from Stata Complete values in this fixture; treatment of missing categories is not asserted.
gcontract
Count jointly observed category combinations
Stata
gcontract g h, freq(n)R Package:dplyr
data <- dplyr::count(data,g,h,name='n')Create category counts and percentages with gcontract
Stata
gcontract g, freq(n) percent(p)R Package:dplyr
data <- dplyr::count(data,g,name='n'); data$p <- 100*data$n/sum(data$n)gdistinct
Count distinct values separately for several columns
Stata
gdistinct g hR Package:base
vapply(data[c('g','h')],function(z) length(unique(z[!is.na(z)])),integer(1))Count distinct complete combinations jointly
Stata
gdistinct g h, jointR Package:base
nrow(unique(data[stats::complete.cases(data[c('g','h')]),c('g','h')]))gduplicates
Keep the first row of each compound key
Stata
gduplicates drop g h, forceR Package:base
data <- data[!duplicated(data[c('g','h')]),,drop=FALSE]Tag all duplicates of compound keys
Stata
gduplicates tag g h, generate(dup)R Package:dplyr
data <- dplyr::mutate(data,dup=dplyr::n()-1L,.by=c(g,h))gegen
Create identifiers for complete combinations of keys
Stata
gegen groupid = group(g h)R Package:base
data$groupid <- as.integer(interaction(data$g,data$h,drop=TRUE,lex.order=TRUE))Differs from Stata Complete numeric keys only; exact identifier ordering follows the demonstrated lexicographic keys.
Tag one observation in each nonmissing group
Stata
gegen tag = tag(g)R Package:base
data$tag <- as.integer(!is.na(data$g)&!duplicated(data$g))Attach group means using a gegen-style workflow
Stata
gegen z = mean(x), by(g)R Package:dplyr
data <- dplyr::mutate(data,z=mean(x,na.rm=TRUE),.by=g)generate
Create a running sum ignoring missing values
Stata
generate cumulative = sum(x)R Package:base
data$cumulative <- cumsum(replace(data$x,is.na(data$x),0))Stata’s generate sum() treats missing contributions as zero, unlike raw cumsum().
11 more examples and alternatives
Number observations within sorted groups
Stata
bysort g (id): generate row = _nR Package:dplyr
data <- dplyr::arrange(data,g,id); data <- dplyr::mutate(data,row=dplyr::row_number(),.by=g)Compute running totals within groups
Stata
bysort g (id): generate total = sum(x)R Package:dplyr
data <- dplyr::arrange(data,g,id); data <- dplyr::mutate(data,total=cumsum(replace(x,is.na(x),0)),.by=g)Attach group row counts
Stata
bysort g: generate n = _NR Package:dplyr
data <- dplyr::mutate(data,n=dplyr::n(),.by=g)Mark the first observation within sorted groups
Stata
bysort id (year): generate first = _n == 1R Package:dplyr
{ data <- dplyr::arrange(data, id, year); dplyr::mutate(data, first = as.integer(dplyr::row_number() == 1L), .by = id) }Differs from Stata Sorts by id and year, then marks one first row per id, including a missing-id group. Ties in year use input order in R; add a tie-break variable for a reproducible cross-system choice.
Create a binary indicator retaining missing values
Stata
generate byte high = x > 3 if x < .R Package:base
data$high <- ifelse(is.na(data$x),NA_integer_,as.integer(data$x > 3))Create a nonmissing indicator
Stata
generate byte observed = !missing(x)R Package:base
data$observed <- as.integer(!is.na(data$x))Square a variable preserving missing values
Stata
generate double z = x^2R Package:base
data$z <- data$x^2Repeat the total row count
Stata
generate n = _NR Package:base
data$n <- nrow(data)Shift a column by row position
Stata
generate prior = x[_n-1]R Package:dplyr
data$prior <- dplyr::lag(data$x)Differs from Stata Position-based shift; this does not use time-series spacing or tsset semantics.
Create row numbers
Stata
generate row = _nR Package:base
data$row <- seq_len(nrow(data))Add columns with missing propagation
Stata
generate z = x + yR Package:base
data$z <- data$x + data$ygetmata
Convert a matrix into named data columns
Stata
getmata (x y)=XR Package:base
data <- as.data.frame(X); names(data) <- c('x','y')Creates a new R table rather than importing from a separate Mata workspace; X is fixed.
gisid
Validate compound-key uniqueness allowing ordinary missing
Stata
gisid g h, missokR Package:base
stopifnot(!anyDuplicated(data[c('g','h')]))Differs from Stata Ordinary missing is allowed as a key value; extended Stata missing categories are not represented here.
Assert a unique complete identifier with gisid
Stata
gisid idR Package:base
stopifnot(!anyNA(data$id),!anyDuplicated(data$id))glevelsof
List distinct complete multi-column keys
Stata
glevelsof g hR Package:base
levels <- unique(data[c('g','h')]); levels <- levels[do.call(order,levels),,drop=FALSE]Differs from Stata Returns a key table rather than a space-delimited local macro; fixture keys contain no missing values.
Store sorted distinct categories with glevelsof
Stata
glevelsof g, local(levels)R Package:base
levels <- sort(unique(data$g[!is.na(data$g)]))gquantiles
Assign four empirical quantile categories
Stata
gquantiles quartile=x, xtile nquantiles(4)R Package:base
cuts <- stats::quantile(data$x,c(.25,.5,.75),type=2); data$quartile <- as.integer(cut(data$x,breaks=c(-Inf,cuts,Inf),right=TRUE))Differs from Stata Unweighted distinct finite values; uses explicit R type-2 cutoffs and right-closed categories. Ties can prevent equal group sizes.
Return selected empirical percentile cutpoints
Stata
gquantiles x, _pctile percentiles(25 50 75)R Package:base
stats::quantile(data$x,c(.25,.5,.75),type=2)Differs from Stata Explicit R type-2 unweighted percentile workflow; no alternative-definition or weighted numerical parity is asserted.
greshape
Gather explicitly named wide columns with greshape
Stata
greshape gather x1 x2, keys(measure) values(value)R Package:tidyr
data <- tidyr::pivot_longer(data,c(x1,x2),names_to='measure',values_to='value')Drop missing measurements while reshaping one stub
Stata
greshape long x, by(id) keys(wave) dropmissR Package:tidyr
data <- tidyr::pivot_longer(data,c(x1,x2),names_to='wave',names_prefix='x',names_transform=list(wave=as.integer),values_to='x',values_drop_na=TRUE)Differs from Stata Single-stub fixed workflow; for multiple stubs drop a row only when every reshaped value is missing.
Spread text-keyed values into columns with greshape
Stata
greshape spread value, keys(measure)R Package:tidyr
data <- tidyr::pivot_wider(data,names_from=measure,values_from=value)gsort
Sort descending with Stata missing first
Stata
gsort -xR Package:base
data <- data[order(-data$x,na.last=FALSE), , drop=FALSE]Numeric missing sorts first in Stata descending order; use na.last=FALSE deliberately.
1 more examples and alternatives
Sort by ascending group and descending value
Stata
gsort g -yR Package:dplyr
data <- dplyr::arrange(data, g, dplyr::desc(y))gstats
Cap tails separately inside each group
Stata
gstats winsor x, by(g) cuts(25 75) replaceR Package:dplyr
data <- dplyr::mutate(data,x={b <- stats::quantile(x,c(.25,.75),na.rm=TRUE,type=2); pmax(b[1],pmin(b[2],x))},.by=g)Differs from Stata Groups use independent unweighted R type-2 cutoffs; all-missing groups require an explicit policy.
Cap both tails at explicitly selected empirical quartiles
Stata
gstats winsor x, cuts(25 75) generate(z)R Package:base
bounds <- stats::quantile(data$x,c(.25,.75),na.rm=TRUE,type=2); data$z <- pmax(bounds[1],pmin(bounds[2],data$x))Differs from Stata Unweighted workflow with an explicit R type-2 empirical percentile rule; no cross-software numerical certification is claimed.
Set values outside empirical quartiles to missing
Stata
gstats winsor x, cuts(25 75) trim generate(z)R Package:base
bounds <- stats::quantile(data$x,c(.25,.75),na.rm=TRUE,type=2); data$z <- data$x; data$z[!is.na(data$x) & (data$x<bounds[1] | data$x>bounds[2])] <- NA_real_Differs from Stata Trimming sets tails to missing while retaining rows; percentile rule is explicit R type 2 and no weighted parity is asserted.
gtoplevelsof
Find the two most frequent complete categories
Stata
gtoplevelsof g, ntop(2)R Package:dplyr
counts <- dplyr::count(data,g,name='n'); counts <- counts[order(-counts$n,counts$g),]; top <- utils::head(counts,2)Differs from Stata Returns the leading categories and counts only; Stata cumulative/Other rows are not generated. gtop is an alias and is not counted separately.
gunique
Count unique complete row-key combinations
Stata
gunique g hR Package:base
nrow(unique(data[c('g','h')]))Differs from Stata Complete keys in this fixture; unlike gdistinct without joint, gunique treats all listed columns jointly.
Attach distinct-value counts within each group
Stata
gunique h, by(g) generate(nunique)R Package:dplyr
data <- dplyr::mutate(data,nunique=dplyr::n_distinct(h),.by=g)Differs from Stata Complete group and value columns in this example; no missing-category behavior is asserted.
hashsort
Stably sort by ascending group and descending value
Stata
hashsort g -xR Package:base
data <- data[order(data$g,-data$x,method='radix'),,drop=FALSE]Differs from Stata Complete numeric keys only; R radix sort preserves original order for equal keys. No comparative speed claim is made.
insobs
Insert a missing row after a position
Stata
insobs 1, after(2)R Package:base
data <- rbind(data[seq_len(2),,drop=FALSE],data[NA_integer_,,drop=FALSE],data[-seq_len(2),,drop=FALSE])Fixed workflow example; adapt the object and column names together.
Insert a missing row before a position
Stata
insobs 1, before(3)R Package:base
data <- rbind(data[1:2,,drop=FALSE],data[NA_integer_,,drop=FALSE],data[3:6,,drop=FALSE])Fixed workflow example; adapt the object and column names together.
Append two entirely missing observations
Stata
insobs 2R Package:base
data <- rbind(data,data[rep(NA_integer_,2),,drop=FALSE])Fixed workflow example; adapt the object and column names together.
inspect
Count signs and missing values
Stata
inspect xR Package:base
c(negative=sum(data$x<0,na.rm=TRUE),zero=sum(data$x==0,na.rm=TRUE),positive=sum(data$x>0,na.rm=TRUE),missing=sum(is.na(data$x)))Differs from Stata Sign/missing counts only; Stata’s histogram and integer diagnostic are not included.
ipolate
Keep boundary missing values outside the interpolation range
Stata
ipolate y x, generate(z)R Package:base
data$z <- stats::approx(data$x,data$y,xout=data$x,rule=1)$yisid
Assert a compound key uniquely identifies rows
Stata
isid g hR Package:base
stopifnot(!anyNA(data[c('g','h')]),!anyDuplicated(data[c('g','h')]))2 more examples and alternatives
Assert a key is unique and nonmissing
Stata
isid idR Package:base
stopifnot(!anyNA(data$id),!anyDuplicated(data$id))Allow one ordinary missing value in a unique key
Stata
isid id, missokR Package:base
stopifnot(!anyDuplicated(data$id))joinby
Form every matching pair within groups
Stata
joinby g using other.dtaR Package:dplyr
data <- dplyr::inner_join(data,other,by='g',relationship='many-to-many')1 more examples and alternatives
Keep unmatched master rows while forming group pairs
Stata
joinby g using other.dta, unmatched(master)R Package:dplyr
data <- dplyr::left_join(data,other,by='g',relationship='many-to-many')Differs from Stata Returns paired rows without the Stata _merge indicator.
keep
Keep named columns in order
Stata
keep id xR Package:base
data <- data[c('id','x')]7 more examples and alternatives
Keep complete rows on selected columns
Stata
keep if !missing(x, y)R Package:base
data <- data[stats::complete.cases(data[c('x','y')]), , drop=FALSE]Filter to a category with dplyr
Stata
keep if g == 2R Package:dplyr
data <- dplyr::filter(data, g == 2)Keep a set of categories
Stata
keep if inlist(g, 1, 3)R Package:base
data <- data[data$g %in% c(1,3), , drop=FALSE]Keep rows missing a value
Stata
keep if missing(x)R Package:base
data <- data[is.na(data$x), , drop=FALSE]Keep nonempty strings
Stata
keep if s != ""R Package:base
data <- data[!is.na(data$s) & data$s != '', , drop=FALSE]Differs from Stata Stata string missing is empty text; this excludes both empty text and R NA.
Keep observed values above a threshold
Stata
keep if x > 2 & x < .R Package:base
data <- data[!is.na(data$x) & data$x > 2, , drop=FALSE]Keep a row interval by position
Stata
keep in 2/4R Package:base
data <- data[2:4, , drop=FALSE]Fixed workflow example; adapt the object and column names together.
levelsof
Store distinct observed numeric categories
Stata
levelsof g, local(groups)R Package:base
groups <- sort(unique(data$g[!is.na(data$g)]))1 more examples and alternatives
List distinct values including ordinary missing
Stata
levelsof x, missingR Package:base
sort(unique(data$x),na.last=TRUE)list
Inspect selected rows and columns
Stata
list id x if g == 2R Package:base
data[data$g==2,c('id','x'),drop=FALSE]2 more examples and alternatives
Show selected columns from the first rows
Stata
list id x in 1/3R Package:utils
utils::head(data[c('id','x')],3)Show the last rows
Stata
list in -2/lR Package:utils
utils::tail(data,2)Fixed workflow example; adapt the object and column names together.
lookfor
Search column names without case sensitivity
Stata
lookfor incomeR Package:base
names(data)[grepl('income',names(data),ignore.case=TRUE)]Differs from Stata Searches names only; include each column’s label attribute to search variable labels too.
memory
Measure the memory occupied by one R table
Stata
memoryR Package:utils
utils::object.size(data)Reports one object’s estimated memory, not Stata’s process-wide memory allocation report.
merge
Record master-only, using-only and matched status
Stata
merge 1:1 id using other.dta, generate(status)R Package:dplyr
data$.master <- TRUE; other$.using <- TRUE; data <- dplyr::full_join(data,other,by='id',relationship='one-to-one'); data$status <- ifelse(is.na(data$.master),2L,ifelse(is.na(data$.using),1L,3L)); data$.master <- NULL; data$.using <- NULLRequires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
7 more examples and alternatives
Keep all master rows in a one-to-one merge
Stata
merge 1:1 id using other.dta, keep(master match) nogenerateR Package:dplyr
data <- dplyr::left_join(data,other,by='id',relationship='one-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Keep only matched keys in a one-to-one merge
Stata
merge 1:1 id using other.dta, keep(match) nogenerateR Package:dplyr
data <- dplyr::inner_join(data,other,by='id',relationship='one-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Limit using-table columns during merge
Stata
merge 1:1 id using other.dta, keepusing(y) nogenerateR Package:dplyr
data <- dplyr::full_join(data,other[c('id','y')],by='id',relationship='one-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Perform a validated one-to-one full merge
Stata
merge 1:1 id using other.dta, nogenerateR Package:dplyr
stopifnot(!anyDuplicated(data$id),!anyDuplicated(other$id)); data <- dplyr::full_join(data,other,by='id',relationship='one-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Fill master missing values from matched using values
Stata
merge 1:1 id using other.dta, update nogenerateR Package:dplyr
data <- dplyr::full_join(data,other,by='id',suffix=c('','.using'),relationship='one-to-one'); data$x <- dplyr::coalesce(data$x,data$x.using); data$x.using <- NULLDiffers from Stata Shows value update only; Stata update conflict status codes 4/5 are not generated. Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Expand unique master keys to multiple matching rows
Stata
merge 1:m id using other.dta, nogenerateR Package:dplyr
data <- dplyr::full_join(data,other,by='id',relationship='one-to-many')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
Attach unique group attributes to many rows
Stata
merge m:1 g using groups.dta, keep(master match) nogenerateR Package:dplyr
data <- dplyr::left_join(data,groups,by='g',relationship='many-to-one')Requires disjoint non-key column names unless update is explicitly shown. dplyr suffixes overlapping names; ordinary Stata merge preserves master values, including master missing values, on matched rows.
missings
Drop rows missing on every selected numeric variable
Stata
missings dropobs x y, forceR Package:base
data <- data[rowSums(!is.na(data[c('x','y')]))>0,,drop=FALSE]Drop entirely missing numeric columns
Stata
missings dropvars, forceR Package:base
data <- data[!vapply(data,function(z) all(is.na(z)),logical(1))]Differs from Stata Numeric-only fixture; Stata string missing is empty text and would require an additional R test for empty strings.
Report missing-value counts by numeric variable
Stata
missings report x yR Package:base
colSums(is.na(data[c('x','y')]))Differs from Stata Numeric columns only. The R result includes zero counts; Stata report defaults to showing counts at least one.
Count numeric missing values within each row
Stata
missings tag x y, generate(nmiss)R Package:base
data$nmiss <- rowSums(is.na(data[c('x','y')]))misstable
Count joint missingness patterns
Stata
misstable patterns x yR Package:base
table(apply(is.na(data[c('x','y')]),1,paste0,collapse=''))Differs from Stata TRUE marks missing in the R pattern string; Stata’s displayed symbols/order differ.
1 more examples and alternatives
Count missing values for each selected column
Stata
misstable summarize x yR Package:base
colSums(is.na(data[c('x','y')]))mvdecode
Convert multiple sentinel codes to missing
Stata
mvdecode x, mv(-99 -98)R Package:base
data$x[data$x %in% c(-99,-98)] <- NA_real_1 more examples and alternatives
Convert a sentinel to tagged missing
Stata
mvdecode x, mv(-99=.a)R Package:haven
data$x[data$x %in% -99] <- haven::tagged_na('a')Differs from Stata Tagged missing preserves the label but R comparisons still follow NA semantics.
mvencode
Encode missing values with a sentinel
Stata
mvencode x, mv(-99)R Package:base
data$x[is.na(data$x)] <- -991 more examples and alternatives
Encode one tagged missing category
Stata
mvencode x, mv(.a=-99)R Package:haven
data$x[haven::is_tagged_na(data$x,'a')] <- -99order
Alphabetize column order
Stata
order _all, alphabeticR Package:base
data <- data[sort(names(data))]Fixed workflow example; adapt the object and column names together.
3 more examples and alternatives
Move a column to the end
Stata
order id, lastR Package:dplyr
data <- dplyr::relocate(data, id, .after=dplyr::last_col())Move a column after another
Stata
order s, after(id)R Package:dplyr
data <- dplyr::relocate(data, s, .after=id)Move selected columns to the front
Stata
order y id, firstR Package:base
data <- data[c('y','id',setdiff(names(data),c('y','id')))]putmata
Copy numeric columns into an R matrix
Stata
putmata X=(x y)R Package:base
X <- as.matrix(data[c('x','y')])R matrix workflow replaces the separate Mata workspace; X is a fixed matrix name.
Copy complete numeric rows into a matrix
Stata
putmata X=(x y), omitmissingR Package:base
X <- as.matrix(data[stats::complete.cases(data[c('x','y')]),c('x','y')])R matrix workflow replaces Mata; rows are removed jointly over the selected columns.
range
Create an evenly spaced grid including endpoints
Stata
range z 0 1 5R Package:base
data <- data.frame(z=seq(0,1,length.out=5))Attach a grid using the current row count
Stata
range z 0 10R Package:base
data$z <- seq(0,10,length.out=nrow(data))Create a decreasing numeric grid
Stata
range z 10 0 6R Package:base
data <- data.frame(z=seq(10,0,length.out=6))rangestat
Compute a mean over each closed numeric-key neighborhood
Stata
rangestat (mean) z=x, interval(key -1 1)R Package:base
data$z <- vapply(data$key,function(k) mean(data$x[data$key>=k-1 & data$key<=k+1]),numeric(1))Differs from Stata Small complete-data workflow with inclusive key offsets and self included; quadratic scanning is not intended for large datasets.
Exclude the current row from numeric-range means
Stata
rangestat (mean) z=x, interval(key -1 1) excludeselfR Package:base
data$z <- vapply(seq_len(nrow(data)),function(i) mean(data$x[seq_len(nrow(data))!=i & data$key>=data$key[i]-1 & data$key<=data$key[i]+1]),numeric(1))Differs from Stata Excludes row identity rather than all tied keys. Every fixture neighborhood has another observation; empty neighborhoods need NA handling.
Compute a sum over each closed numeric-key neighborhood
Stata
rangestat (sum) z=x, interval(key -1 1)R Package:base
data$z <- vapply(data$key,function(k) sum(data$x[data$key>=k-1 & data$key<=k+1]),numeric(1))Differs from Stata Complete finite keys/values only in this fixture; missing bounds, by-groups and weights need explicit extensions.
recast
Convert an integer column to double
Stata
recast double xR Package:base
data$x <- as.double(data$x)1 more examples and alternatives
Store whole-number values as R integers
Stata
recast long xR Package:base
data$x <- as.integer(data$x)Differs from Stata Only use when values are whole numbers in R’s integer range; Stata storage ranges differ.
recode
Collapse integer categories to two groups
Stata
recode x (1/2=0) (3/6=1), generate(binary)R Package:base
data$binary <- ifelse(is.na(data$x),NA_real_,ifelse(data$x<=2,0,1))Differs from Stata Fixture values are integers 1 through 6; specify additional branches for values outside those ranges.
1 more examples and alternatives
Recode selected values and retain all others
Stata
recode x (1=10) (2=20), generate(z)R Package:base
data$z <- data$x; data$z[data$x %in% 1] <- 10; data$z[data$x %in% 2] <- 20rename
Rename several columns together
Stata
rename (x y) (income hours)R Package:base
names(data)[match(c('x','y'),names(data))] <- c('income','hours')4 more examples and alternatives
Lowercase all column names
Stata
rename *, lowerR Package:base
names(data) <- tolower(names(data))Fixed workflow example; adapt the object and column names together.
Uppercase all column names
Stata
rename *, upperR Package:base
names(data) <- toupper(names(data))Fixed workflow example; adapt the object and column names together.
Replace a column-name prefix
Stata
rename old* new*R Package:base
names(data) <- sub('^old','new',names(data))Fixed workflow example; adapt the object and column names together.
Rename a column with dplyr
Stata
rename x incomeR Package:dplyr
data <- dplyr::rename(data, income=x)replace
Replace empty text without replacing NA
Stata
replace s = "unknown" if s == ""R Package:base
data$s[!is.na(data$s) & data$s==''] <- 'unknown'Differs from Stata R distinguishes empty text from NA; this example targets empty text only.
4 more examples and alternatives
Convert a sentinel to missing
Stata
replace x = . if x == 2R Package:base
data$x[data$x %in% 2] <- NA_real_Replace numeric missing by zero
Stata
replace x = 0 if missing(x)R Package:base
data$x[is.na(data$x)] <- 0Modify values only inside a category
Stata
replace x = x * 100 if g == 1R Package:base
data$x[data$g %in% 1] <- data$x[data$g %in% 1] * 100Fill missing values from another column
Stata
replace x = y if missing(x)R Package:base
data$x[is.na(data$x)] <- data$y[is.na(data$x)]reshape
Reshape multiple parallel measurement stubs
Stata
reshape long x y, i(id) j(wave)R Package:tidyr
data <- tidyr::pivot_longer(data,cols=c(x1,x2,y1,y2),names_to=c('.value','wave'),names_pattern='([xy])([12])',names_transform=list(wave=as.integer))Fixed two-stub example; all name patterns and source names must be changed together.
3 more examples and alternatives
Convert a wide measurement stub to long rows
Stata
reshape long x, i(id) j(wave)R Package:tidyr
data <- tidyr::pivot_longer(data,cols=c(x1,x2),names_to='wave',names_prefix='x',names_transform=list(wave=as.integer),values_to='x')Fixed x1/x2 stub example; source names, stub and output names must be changed together.
Use text suffixes when widening measurements
Stata
reshape wide x, i(id) j(group) stringR Package:tidyr
data <- tidyr::pivot_wider(data,id_cols=id,names_from=group,values_from=x,names_prefix='x')Differs from Stata Fixed string-suffix workflow; pair keys must be unique.
Convert unique long measurements to wide columns
Stata
reshape wide x, i(id) j(wave)R Package:tidyr
data <- tidyr::pivot_wider(data,id_cols=id,names_from=wave,values_from=x,names_prefix='x')Differs from Stata Requires unique id-wave pairs; duplicates must be resolved explicitly rather than silently aggregated.
separate
Create group-specific copies of a numeric column
Stata
separate x, by(g)R Package:base
for (k in sort(unique(data$g))) data[[paste0('x',k)]] <- ifelse(data$g==k,data$x,NA_real_)Separate a column by a binary expression
Stata
separate y, by(g == 1) generate(z)R Package:base
data$z0 <- ifelse(data$g!=1,data$y,NA_real_); data$z1 <- ifelse(data$g==1,data$y,NA_real_)The generated stub z is fixed here; z0 and z1 are the false and true branches.
seqvar
Leave remaining rows missing after a short integer sequence
Stata
seqvar z = 1/3R Package:base
data$z <- rep(NA_integer_,nrow(data)); data$z[seq_len(min(3L,nrow(data)))] <- seq_len(min(3L,nrow(data)))Create a specified integer sequence with a deliberate gap
Stata
seqvar z = 1/3 5/7R Package:base
data$z <- c(1:3,5:7)snapshot
Restore a temporary data snapshot
Stata
snapshot restore 1R Package:base
data <- readRDS(path)Restores an explicitly supplied RDS path rather than a numbered Stata snapshot.
Save a temporary on-disk data snapshot
Stata
snapshot saveR Package:base
path <- tempfile(fileext='.rds'); saveRDS(data,path)Uses an RDS file path rather than Stata’s numbered interactive snapshot manager.
sort
Sort lexicographically on two columns
Stata
sort g xR Package:base
data <- data[order(data$g,data$x,na.last=TRUE), , drop=FALSE]2 more examples and alternatives
Keep original order within equal keys
Stata
sort g, stableR Package:base
data <- data[order(data$g,method='radix'), , drop=FALSE]Sort a numeric column with missing last
Stata
sort xR Package:base
data <- data[order(data$x, na.last=TRUE), , drop=FALSE]splitsample
Assign a balanced random half-split
Stata
splitsample, generate(sample)R Package:base
data$sample <- sample(rep(1:2,length.out=nrow(data)))Differs from Stata Random assignments differ across R and Stata; this fixture has even sample size.
Assign three equal random subsamples
Stata
splitsample, generate(sample) nsplit(3)R Package:base
data$sample <- sample(rep(1:3,each=nrow(data)/3))Differs from Stata Requires the fixture row count to be divisible by three; random assignments differ across systems.
stack
Stack pairs of columns together
Stata
stack x a y b, into(value amount) clearR Package:base
data <- rbind(data.frame(value=data$x,amount=data$a,`_stack`=1L,check.names=FALSE),data.frame(value=data$y,amount=data$b,`_stack`=2L,check.names=FALSE))Stack two columns vertically with a source indicator
Stata
stack x y, into(value) clearR Package:base
data <- data.frame(value=c(data$x,data$y),`_stack`=rep(1:2,each=nrow(data)),check.names=FALSE)tostring
Format numeric identifiers with leading zeros
Stata
tostring x, generate(s) format(%06.0f)R Package:base
data$s <- sprintf('%06.0f',data$x)1 more examples and alternatives
Format numeric text to two decimal places
Stata
tostring x, generate(s) format(%9.2f)R Package:base
data$s <- sprintf('%.2f',data$x)Differs from Stata R example omits field-width padding; values are rounded for display and stored as text.
xi
Create indicator variables omitting the lowest category
Stata
xi i.gR Package:tidystata
data <- dplyr::select(tidystata::as_dummy(data, g, .names = "index"), -tidyselect::any_of("g_1"))Differs from Stata Keeps the original columns and omits the first observed category. Numeric categories are ordered by value; R factors follow their level order, which must match Stata’s omitted category. Stata names indicators by category code; R numbers observed categories with .names=“index”. Use factor(g) in models; xi: interactions are not reproduced.
xpose
Transpose an entirely numeric table
Stata
xpose, clearR Package:base
data <- as.data.frame(t(as.matrix(data)))Differs from Stata Numeric-only input; R output column names differ from Stata’s v1, v2 names.
1 more examples and alternatives
Transpose values while retaining original column names
Stata
xpose, clear varnameR Package:base
oldnames <- names(data); data <- as.data.frame(t(as.matrix(data))); data[['_varname']] <- oldnamesDiffers from Stata Numeric-only input. Original names are copied into _varname; R transposed column names may differ.