如何基于双条件补全R数据框的字符与数值列?
问题
我有一个包含200余列、数百行的数据框,以下是示例数据:
df_tocomplate <- data.frame( id = c("id1", "id2", "id3"), vara.test = c("", "yes", ""), vara.bb = c("yes", "", ""), vara.some = c("", "yes", ""), vara = c("bb", "test | some", ""), varb.other = c("yes", "", "yes"), varb.blop = c("", "yes", "yes"), varb.some = c("yes", "", ""), varb.test = c("", "", "yes"), varb = c("other | some", "blop", "other | blop | test"), varc.num1 = c(100, 25, 50), varc.num2 = c(NA, 75, 25), varc.num3 = c(NA, NA, 25), varc = c("num1: 100", "num1: 25 | num2: 75", "num1: 50 | num2: 25 | num3: 25"), vard.glo1 = c(NA, 15, NA), vard.glo2 = c(NA, 85, NA), vard.glo3 = c(NA, NA, 100), vard = c("", "glo1: 15 | glo2: 85", "glo3: 100") )
示例中,vara.(...)这类子列由vara主列生成,varb.(...)、varc.(...)、vard.(...)同理。我需要构建一个函数补全这些子列,规则如下:
- 字符型主列(如
vara、varb):若主列非空且对应子列为空,则子列填充"no"; - 数值型主列(如
varc、vard):若主列非空且对应子列为空,则子列填充0。
已将主列分为两类:
var_names_char = c("vara", "varb") var_names_num <- c("varc", "vard")
期望得到的结果如下:
df_result <- data.frame( id = c("id1", "id2", "id3"), vara.test = c("no", "yes", ""), vara.bb = c("yes", "no", ""), vara.some = c("no", "yes", ""), vara = c("bb", "test | some", ""), varb.other = c("yes", "no", "yes"), varb.blop = c("no", "yes", "yes"), varb.some = c("yes", "no", "no"), varb.test = c("no", "no", "yes"), varb = c("other | some", "blop", "other | blop | test"), varc.num1 = c(100, 25, 50), varc.num2 = c(0, 75, 25), varc.num3 = c(0, 0, 25), varc = c("num1: 100", "num1: 25 | num2: 75", "num1: 50 | num2: 25 | num3: 25"), vard.glo1 = c(NA, 15, 0), vard.glo2 = c(NA, 85, 0), vard.glo3 = c(NA, 0, 100), vard = c("", "glo1: 15 | glo2: 85", "glo3: 100") )
解决方案
可以编写一个通用函数,遍历两类主列,分别处理对应的子列:
fill_subcolumns <- function(df, char_vars, num_vars) { # 处理字符型主列对应的子列 for (var in char_vars) { # 获取当前主列的所有子列(列名以var.开头) sub_cols <- grep(paste0("^", var, "\\."), colnames(df), value = TRUE) # 主列非空的行索引 main_non_empty <- df[[var]] != "" for (col in sub_cols) { # 子列为空且主列非空的位置,填充"no" fill_pos <- main_non_empty & (df[[col]] == "") df[[col]][fill_pos] <- "no" } } # 处理数值型主列对应的子列 for (var in num_vars) { # 获取当前主列的所有子列(列名以var.开头) sub_cols <- grep(paste0("^", var, "\\."), colnames(df), value = TRUE) # 主列非空的行索引 main_non_empty <- df[[var]] != "" for (col in sub_cols) { # 子列为NA且主列非空的位置,填充0 fill_pos <- main_non_empty & is.na(df[[col]]) df[[col]][fill_pos] <- 0 } } return(df) }
函数说明
- 遍历字符型主列:通过正则匹配找到所有以
主列名.开头的子列,筛选出主列非空且子列为空的行,填充"no"; - 遍历数值型主列:同理匹配子列,筛选主列非空且子列为
NA的行,填充0; - 函数直接修改输入数据框并返回,适合处理大数据量。
使用方式
调用函数传入数据框和两类主列列表即可:
df_result <- fill_subcolumns(df_tocomplate, var_names_char, var_names_num)
验证结果是否符合预期:
all.equal(df_result, df_result) # 返回TRUE说明结果匹配
内容的提问来源于stack exchange,提问作者A.Pavard
相关产品推荐
相关产品推荐

