如何在R数据框中实现对应Stata逻辑的多药物分类
在R中实现Stata风格的多标签药物分类逻辑
没问题,我帮你把Stata里的药物分类逻辑转到R,还支持多标签分类——这比Stata里每次replace覆盖的方式更灵活,正好满足你要保留多个分类的需求。
第一步:理解原Stata代码逻辑
你的Stata代码是通过strmatch(upper(drug), "XXX*")匹配药物名称(转大写后以指定前缀开头),然后给class字段赋值。但Stata的replace是覆盖式的,一个药物如果匹配多个规则,只会保留最后一次赋值的分类。而你需要的是收集所有匹配的分类,所以我们用R的列表和字符串匹配工具来实现。
第二步:准备R代码实现
首先加载常用的工具包(如果没安装先运行install.packages(c("dplyr", "stringr", "purrr"))):
library(dplyr) library(stringr) library(purrr)
然后把你的Stata分类规则整理成R的列表结构,键是分类名称,值是对应的药物前缀(去掉原代码里的*,因为我们会用开头匹配的逻辑):
# 定义药物分类规则 drug_class_rules <- list( "ACE Inhibitor" = c("CAPTOPRIL", "ENALAPRIL", "ENALAPRILAT", "FOSINOPRIL", "LISINOPRIL", "RAMIPRIL"), "Acne Medication" = c("ADAPALENE", "ADAPALENE/BENZOYL PEROXIDE", "BENZOYL PEROXIDE", "BENZOYL PEROXIDE/CLINDAMYCIN", "ISOTRETINOIN", "ERYTHROMYCIN/TRETINOIN"), "Acne Medication/Acute Promyelocytic Leukemia Medication" = c("TRETINOIN"), "Alpha Agonist" = c("XYLOMETAZOLINE"), "Alpha Blocker" = c("DOXAZOSIN", "PHENOXYBENZAMINE", "PHENTOLAMINE", "PRAZOSIN", "TAMSULOSIN", "TERAZOSIN"), "Alpha/Beta Blocker" = c("CARVEDILOL", "LABETALOL"), "Alpha-1 Agonist" = c("PHENYLEPHRINE", "MIDODRINE"), "Alpha-2 Agonist" = c("CLONIDINE", "DEXMEDETOMIDINE"), "Anaesthetic, general" = c("KETAMINE", "THIOPENTAL"), "Anaesthetic, local" = c("BENZOCAINE", "BUPIVACAINE", "BUPIVACAINE/FENTANYL", "TETRACAINE", "XYLOCAINE"), "Anaesthetic, local/Antiarrythmic" = c("LIDOCAINE"), "Anaesthetic, local/Antiseptic" = c("HEXYLRESORCINOL"), "Anaesthetic, topical" = c("LIDOCAINE/PRILOCAINE", "PROPARACAINE"), "Analgesic" = c("ACETAMINOPHEN", "BELLADONNA & OPIUM SUPPOSITORY") )
接下来处理你的数据框(假设数据框名为drug_df):
# 先把药物名称转成大写,统一匹配规则 drug_df <- drug_df %>% mutate(drug_upper = str_to_upper(drug)) # 编写函数:输入大写药物名,返回所有匹配的分类 get_matching_classes <- function(drug_name, rules) { # 检查每个分类下的药物前缀是否匹配当前药物的开头 matches <- map_lgl(rules, ~any(str_starts(drug_name, .x))) # 返回所有匹配的分类名称 names(rules)[matches] } # 给每一行添加多分类列 drug_df <- drug_df %>% # 生成列表列,每个元素是该药物的所有分类向量 mutate(classes = map(drug_upper, get_matching_classes, rules = drug_class_rules), # 可选:把分类转成逗号分隔的字符串,方便查看 classes_str = map_chr(classes, ~paste(.x, collapse = ", ")))
第三步:验证结果
用你提供的样本数据测试:
- 药物
Amlodipine、Cefprozil、Clobazam不在规则里,所以classes是空向量,classes_str是空字符串。 - 如果有药物是
TRETINOIN,会匹配到Acne Medication/Acute Promyelocytic Leukemia Medication。 - 如果是
ERYTHROMYCIN/TRETINOIN,会匹配到Acne Medication(不会被TRETINOIN*匹配,因为它的开头是ERYTHROMYCIN,和原Stata逻辑一致)。
可选:Base R版本(不用tidyverse)
如果你不想用tidyverse包,用Base R也能实现:
# 转大写 drug_df$drug_upper <- toupper(drug_df$drug) # 生成分类列 drug_df$classes <- lapply(drug_df$drug_upper, function(x) { sapply(names(drug_class_rules), function(c) { any(startsWith(x, drug_class_rules[[c]])) }) %>% which() %>% names() }) # 转成字符串列 drug_df$classes_str <- sapply(drug_df$classes, function(x) paste(x, collapse = ", "))
这样就完美复刻了Stata的匹配逻辑,同时支持一个药物对应多个分类的需求。
内容的提问来源于stack exchange,提问作者user8722680
相关产品推荐
相关产品推荐

