set a b; (stack; align names with rename= if needed)
bind_rows(..., .id = "SRC")
set a b indsname=src;
bind_rows() by column name
PROC SQLOUTER UNION CORR
Traps: bind_rows() matches columns by name, not position. Character versus numeric on the same name errors in dplyr; fix types before stacking. SAS SET takes character length from the first dataset and can truncate later values; bind_rows() does not truncate.
Worked examples below.
Stack two tables
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
data all;
set ae_site_a ae_site_b indsname=src;
site = src;
run;
INDSNAME= is the dataset name that contributed the row (often WORK.AE_SITE_A style). Rename or scan that value if you need a short code like .id.
ImportantMatch by name, not position
bind_rows() does not line up column 1 with column 1. Rename first when the same concept has different names. Character versus numeric on the same name is an error in dplyr. Fix the type before stacking.
SAS truncates; bind_rows() does not
The first SAS dataset in SET sets character lengths. A later dataset with a longer value is truncated to that length. bind_rows() keeps the full string:
AETERM is the full term on both rows. In SAS, set ae_short ae_long; would cut MYOCARDIAL INFARCTION to the length of NAUSEA unless you set length first.
For side-by-side combines on keys, use joins (see Joins), not bind_rows().