03-内置funcion介绍¶
字段截取:fct_cut_text和fct_split_long_vars¶
fct_split_long_vars会自动识别数据中字节长度超过bytes_limit(默认200)的字符变量并进行分割;fct_cut_text为其内置函数,用于将单个字段按照固定字节长度进行分割,支持按词边界或指定分隔符切分。
调用案例:
## 最简调用(默认按词边界切分,分隔符为 ,.;!?)
ds_all2 <- fct_split_long_vars(ds_all1)
## 按指定分隔符切分(不保留词边界)
ds_all2 <- fct_split_long_vars(ds_all1, bytes_limit = 200, keepwordfl = "N", dlmchars = ",.;")
## 每个分段必须以分隔符结尾(适用于CM等Domian字段处理)
ds_all2 <- fct_split_long_vars(ds_all1, bytes_limit = 200, endchar_dlmchars_fl = "Y", dlmchars = ";")
| 参数 | 默认值 | 说明 |
|---|---|---|
data | — | 传入数据 |
bytes_limit | 200 | 每个变量允许的最大字节数 |
keepwordfl ⭐ | "Y" | 是否按词边界切分:"Y" 时,截断处若为词中间则将末尾不完整的词移至下一分段,与SAS u_string_split keepwordfl=Y 行为一致 |
endchar_dlmchars_fl ⭐ | "N" | "Y" 时每个分段必须以 dlmchars 中指定的字符结尾(同时强制 keepwordfl="N") |
dlmchars ⭐ | ",.;!?" (keepwordfl="Y" 时)/ NULL | 分隔符字符集,如 ",.;!?";keepwordfl="Y" 时默认为 ",.;!?",空格始终作为词分隔符 |
exclude_vars | NULL | 可传入字符向量排除无需处理的变量,如 c("AETERM", "AEDECOD") |

匹配epoch:fct_add_epoch / fct_compute_epoch¶
匹配epoch,需具备变量XXSEQ(
fct_add_epoch)。
fct_compute_epoch为新增部门function版本,epoch匹配逻辑更精确。【推荐使用】
调用案例:
## 旧版
ds_final <- fct_add_epoch(ds_all4, se_ds = sdtmqc$se, compdtc = "DSSTDTC")
## 新版(推荐,逻辑更精确)
ds_final <- fct_compute_epoch(ds_all4, compdtc = "DSSTDTC", se_ds = sdtmqc$se)
fct_add_epoch 参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
data | — | 传入数据 |
se_ds | sdtmqc$se | SE数据集,可修改为 sdtmprt$se |
compdtc | — | 数据集中用于判断epoch的日期变量名 |
seqname | 当前Domain的SEQ变量名 | 如不存在则无法进行后续匹配处理 |
fct_compute_epoch 参数(推荐):
| 参数 | 默认值 | 说明 |
|---|---|---|
df | — | 传入数据,需包含 USUBJID 及 compdtc 指定的日期变量 |
compdtc | — | 用于判断epoch的日期变量名(ISO 8601格式字符变量) |
se_ds | sdtmqc$se | SE数据集,需包含 USUBJID、EPOCH、SESTDTC、SEENDTC、TAETORD |
debug | FALSE | 保留参数,暂未启用 |
排序并添加序号:fct_sort_addseq / fct_sort_add_seq¶
基于spec(metacore)中定义的key_seq进行排序;可选是否按SAS风格将NA排在前面,并可自动添加当前domain的
--SEQ变量。
fct_sort_add_seq为新增部门function版本,增加了var_ord参数支持手动指定排序变量,并使用logger记录日志;旧版fct_sort_addseq仍可用。
调用案例:
## 旧版
ds_all4 <- fct_sort_addseq(ds_all3, na.last = FALSE, add_seq = TRUE,
spec_metacore = spec_metacore, domain = Domain)
## 新版(推荐)
ds_all4 <- fct_sort_add_seq(ds_all3, na.last = FALSE, add_seq = TRUE,
spec_metacore = spec_metacore, domain = Domain)
| 参数 | 默认值 | 说明 |
|---|---|---|
df / inds | — | 传入数据 |
na.last | TRUE | NA值排最后;设为 FALSE 则按SAS风格将NA排前面 |
add_seq | FALSE | 设为 TRUE 时自动新增对应domain的SEQ变量,如 AESEQ、DSSEQ |
var_ord ⭐ | NULL | 【fct_sort_add_seq 新增】 从spec中读取排序变量;可传入字符向量手动指定,如 c("USUBJID", "AESEQ") |
spec_metacore | 自动读取 | 内置变量,会自动从运行环境读取;也可手动传入 |
domain | Domain | 默认从环境变量 Domain 中获取;var_ord 为NULL时用于从spec提取排序变量,add_seq=TRUE 时用于确定SEQ变量名 |
debug | FALSE | 【fct_sort_add_seq 新增】 保留参数,暂未启用 |
**注意事项:**在R中使用arrange排序时,NA值默认排在最后;sort排序可通过na.last参数控制NA值位置。该函数基于类似逻辑,调整NA排序位置,以满足和SAS一致的输出需求。
进行codelist转换:fct_apply_ct¶
根据spec中填写的CT和codelist,对数据集中变量进行CT转换;仅处理type为code_decode的变量,将code值转换为decode值。
调用案例:
| 参数 | 默认值 | 说明 |
|---|---|---|
domain | — | 对应domain名,如 "DM"、"AE" |
inds | — | 传入数据 |
spec_metacore | 自动读取 | 内置变量,会自动从运行环境读取 |
tolerant ⭐ | FALSE | 严格模式:codelist中未找到的值转为NA;设为 TRUE(宽容模式)则保留未匹配的原始值 |
vars ⭐ | NULL | 处理该domain下所有code_decode类型变量;可传入字符向量指定只处理特定变量,如 c("SEX", "RACE") |
[v1.1 新增]
tolerant和vars参数: -tolerant = TRUE适用于部分变量值已是decode格式、不需要转换的情况,避免转为NA -vars参数可限定只转换特定变量,提高灵活性
TIPS: 关于如何查看codelist¶
可通过view(ds_spec$codelist)查看spec,type中能看到两种类型code_decode和permitted_val。当codelist中decode=charcode时,type为permitted_val,不相同时为code_decode,可调用上述函数进行decode_to_code的转换。NA值为spec中需要的CT,但codelist文件并未识别到对应值。 
点击右边的小框框可查看CT包含的具体值。
TIPS: 当codelist缺失时¶
-
对于在codelist未勾选,但spec中存在的CT,会在运行fct_apply_ct时出现如下警告。

-
对于type=code_decode的变量,如果codelist中勾选的值缺失或大小写不一致,则无法成功进行转换,只会输出NA值(如下图)。在运行fct_apply_ct时会出现如下警告,需注意辨识。


-
对于type=permitted_val的变量,可使用check_ct_data检查CT中勾选的codelist值和数据集中变量值是否一致。下图为变量中存在codelist中未勾选值时的error输出。
结果输出:fct_final_output2xpt¶
用于输出domain数据至xpt文件
调用案例:
| 参数 | 默认值 | 说明 |
|---|---|---|
domain | — | 对应domain名,如 "SV"、"DM" |
inds | — | 最终版的domain数据,需已完成CT处理 |
qc | FALSE | 设为 TRUE 输出至qc文件夹,FALSE 输出至main文件夹 |
spec_metacore | 自动读取 | 内置变量,会自动从运行环境读取 |
path | 自动读取 | 内置变量,会自动从运行环境读取 |
settings | 自动读取 | 内置变量,会自动从运行环境读取 |
内置逻辑:
- 识别所需变量是否齐全
- 对输入数据进行处理,依次进行以下操作:
- 将变量转化为spec规定格式
- 检查是否包含spec所需变量并删除无关变量
- 按照spec变量顺序进行展示
- 按照TOC中keys变量进行排序
- 规范输出变量的长度,label等信息,输出为xpt格式文件
- 如存在supp变量,将生成对应supp数据集,并按照上述步骤进行输出。
- 输出内容同时保存至04_sdtmdata/xx.xpt和01_setup/sdtmdata-31DEC2025.rds文件中存档,同时更新Environment中的sdtmprt/sdtmqc内容。

TIPS: 关于如何使用sas读取r中输出的xpt文件¶
libname xptin xport "Z:\projects\onc-prj-shr-a1811\sub-csr\shr-a1811-ii-206\20_qc\04_sdtmdata\ds.xpt";
libname datasets 'Z:\projects\onc-prj-shr-a1811\sub-csr\shr-a1811-ii-206\20_qc\04_sdtmdata\sas'; *输出文件夹;
proc copy in=xptin out=datasets;
run;
结果QC:fct_qc¶
用于QC数据集,并将结果输出至11_output文件夹
调用案例:
fct_qc(domain = Domain, output_txt = T, show_result = T,
key_vars = c("STUDYID", "USUBJID", "SUBJID", "DSSEQ"),
path = path)
| 参数 | 默认值 | 说明 |
|---|---|---|
domain | — | 对应domain名,如 "DC"、"DM" |
output_txt | TRUE | 是否输出比对结果至txt文件 |
show_result | TRUE | 是否在console中打印比对结果 |
key_vars | NULL | 定义主域比对唯一行的变量,需确保唯一性;为NULL时按数据集行顺序比对 |
key_vars_supp ⭐ | c("USUBJID", "IDVAR", "IDVARVAL", "QNAM", "QLABEL") | SUPP域比对时的唯一key变量 |
exclude_vars ⭐ | NULL | 排除不参与比对的变量 |
keep_data ⭐ | TRUE | 是否在环境中保留比对结果数据 |
path_main / path_qc | 自动判断 | 内置变量,根据Domain自动判断使用sdtm还是adam路径 |
path_qclog | path$outqc | 输出路径,默认为11_output;如需输出至10_log可设为 path$logqc |
path | 自动读取 | 内置变量,会自动从运行环境读取 |
内置逻辑:
-
读取MAIN和QC数据,会对sas数据或xpt数据文件进行读取
-
使用diffdf::diffdf函数对数据进行比对
-
整理并输出比对结果为v_xx.txt文件
比对文件参考:

输出部分调用案例¶
来源ds.R
## 5. together ----
ds_all1 <- bind_rows(ds1, ds2, ds3, ds4) %>%
left_join(sdtmqc$dc %>% select(USUBJID, SUBJID, STUDYID), by = "SUBJID") %>%
left_join(sdtmqc$dm %>% select(USUBJID, RFSTDTC), by = "USUBJID") %>%
mutate(DOMAIN = Domain,
DSDY = as.numeric(ymd(DSDTC) - ymd(substr(RFSTDTC, 1, 10))) + as.numeric(DSDTC >= substr(RFSTDTC, 1, 10)),
DSSTDY = as.numeric(ymd(DSSTDTC) - ymd(substr(RFSTDTC, 1, 10))) + as.numeric(DSSTDTC >= substr(RFSTDTC, 1, 10)))
## substring
ds_all2 <- fct_split_long_vars(ds_all1)
## apply CT ----
ds_all3 <- fct_apply_ct(domain = Domain, inds = ds_all2,
spec_metacore = spec_metacore)
ds_all3 %>% check_ct_data(ds_spec, na_acceptable = T) ##检查是否符合CT,直接输出数据集表示无CT不一致问题
## ADD XXSEQ
ds_all4 <- ds_all3 %>%
sort_by_key(ds_spec) %>% # 等于arrange(STUDYID, USUBJID,SUBJID, DSDECOD, DSSTDTC, DSSCAT),已TOC中keys变量顺序为准
group_by(USUBJID) %>%
mutate(DSSEQ = 1:n()) %>%
ungroup()
## ADD EPOCH
ds_final <- fct_add_epoch(ds_all4, se_ds = sdtmqc$se, compdtc = "DSSTDTC")
## export as xpt ----
fct_final_output2xpt(domain = Domain, inds = ds_final, qc = T,
settings = settings)
## qc & output as txt ----
fct_qc(domain = Domain, output_txt = T, show_result = T,
key_vars = c("STUDYID", "USUBJID", "SUBJID", "DSSEQ"),
path=path)