在R data.table中如何根据条件从列表列生成lower新列?
解决R data.table列表列按条件提取元素的问题
问题描述
有一个R的data.table,包含列表列digits_list和计数列length_digits_list,需要创建lower_value列,规则如下:
- 当
length_digits_list的值为3时,取digits_list的第二个元素 - 其他情况(值为1或2),取
digits_list的第一个元素
尝试了以下代码,但得到错误结果(例如第4行本该提取"50",却得到了"250"):
df[, lower := ifelse(length_digits_list == 3, digits_list[[2]], ifelse(length_digits_list == 2, digits_list[[1]],digits_list))]
数据结构如下:
structure(list(digits_list = list(list("150", "250"), list("250", "350"), list("350"), list("50", "150"), list("0", "50"), list("250", "350")), length_digits_list = c(2L, 2L, 1L, 2L, 2L, 2L), lower = c("150", "250", "350", "250", "150", "250"), upper = list("250", "350", Inf, "350", "250", "350")), row.names = c(NA, -6L), class = c("data.table", "data.frame"))
错误原因
原代码中digits_list[[2]]是直接提取整个digits_list列的第二个元素(即第二行的列表),而不是每行的第二个元素。ifelse是向量化操作,但列表列无法通过这种方式实现逐行索引,最终导致结果错位。
解决方案
方法1:data.table原生逐行遍历
利用seq_len(.N)遍历每行索引,针对每行的digits_list和length_digits_list做条件判断:
# 生成列表列 df[, lower_value := lapply(seq_len(.N), function(i) { if (length_digits_list[i] == 3) { digits_list[[i]][[2]] } else { digits_list[[i]][[1]] } })] # 若需要转为字符列而非列表列,添加unlist处理 df[, lower_value := unlist(lapply(seq_len(.N), function(i) { if (length_digits_list[i] == 3) { digits_list[[i]][[2]] } else { digits_list[[i]][[1]] } }))]
方法2:用purrr包简化操作(更简洁)
purrr::map2可同时遍历两个列,逐行匹配处理,map2_chr直接返回字符列:
library(purrr) df[, lower_value := map2_chr(digits_list, length_digits_list, ~ if (.y == 3) .x[[2]] else .x[[1]])]
验证结果
处理后第4行的lower_value会正确提取digits_list的第一个元素"50",完全符合预期规则。
内容的提问来源于stack exchange,提问作者NAS_2339
相关产品推荐
相关产品推荐

