根据命名列表更新 dt 列
Posted
技术标签:
【中文标题】根据命名列表更新 dt 列【英文标题】:Update dt columns based on named list 【发布时间】:2022-01-19 02:15:07 【问题描述】:假设,我有以下my_dt
数据表:
neutrons | spectrum | geography |
---|---|---|
2.30 | -1.2 | KIEL |
2.54 | -1.6 | KIEL |
2.56 | -0.9 | JUNG |
2.31 | -0.3 | ANT |
我还有以下命名列表 (my_list
):
> my_list
$particles
[1] "neutrons"
$station
[1] NA
$energy
[1] "spectrum"
$area
[1] "geography"
$gamma
[1] NA
此列表的值对应于我的数据集中的列名称(如果它们存在,如果它们不存在 - NA
)。
根据我的数据集和此列表,我需要检查 my_dt
中存在哪些列并重命名它们(基于 my_list
名称),对于 NA
值 - 我需要创建填充有 NA
s 的列。
所以,我想获取以下数据集:
>final_dt
particles | station | energy | area | gamma |
---|---|---|---|---|
2.30 | NA | -1.2 | KIEL | NA |
2.54 | NA | -1.6 | KIEL | NA |
2.56 | NA | -0.9 | JUNG | NA |
2.31 | NA | -0.3 | ANT | NA |
我尝试使用 apply 系列函数来实现这一点,但目前我无法获得我想要的。 所以,如果有任何帮助,我将不胜感激!
【问题讨论】:
【参考方案1】:data.table 使用lapply
library(data.table)
setDT(my_dt)
setDT(my_list)
final_dt <- setnames( my_list[, lapply( .SD, function(x)
if( x %in% colnames(my_dt)) my_dt[,x,with=F] else NA ) ],
names(my_list) )
final_dt
particles station energy area gamma
1: 2.30 NA -1.2 KIEL NA
2: 2.54 NA -1.6 KIEL NA
3: 2.56 NA -0.9 JUNG NA
4: 2.31 NA -0.3 ANT NA
base R 使用sapply
setDF(my_dt)
setDF(my_list)
data.frame( sapply( my_list, function(x) if(!is.na(x)) my_dt[,x] else NA ) )
particles station energy area gamma
1 2.30 NA -1.2 KIEL NA
2 2.54 NA -1.6 KIEL NA
3 2.56 NA -0.9 JUNG NA
4 2.31 NA -0.3 ANT NA
数据
my_dt <- structure(list(neutrons = c(2.3, 2.54, 2.56, 2.31), spectrum = c(-1.2,
-1.6, -0.9, -0.3), geography = c("KIEL", "KIEL", "JUNG", "ANT"
)), class = "data.frame", row.names = c(NA, -4L))
my_list <- list(particles = "neutrons", station = NA, energy = "spectrum",
area = "geography", gamma = NA)
【讨论】:
谢谢你,安德烈!将此解决方案应用于我的数据并收到错误:Error in
[.data.table(xxx, , x) : j (the 2nd argument inside [...]) is a single symbol but column name 'x' is not found.
@Hilary 这是base R
解决方案。使用setDF(my_dt)
和setDF(my_list)
。如果你想要一个纯粹的data.table
解决方案,你应该将标签datatable
更改为data.table
。小但重要的区别:)
非常感谢,我更改了标签!您对如何将您的解决方案转换为纯data.table
解决方案有任何想法吗?
@Hilary 查看编辑。希望这对你有用!【参考方案2】:
这可能无法满足您的需求,但由于我单独提出了这个想法,因此我会分享以防万一。您可以使用setnames
重命名基于my_list
的列。之后,添加缺少的列名,其值为NA
。最后,如果需要,您可以使用setcolorder
根据您的列表重新排序。
library(data.table)
my_vec <- unlist(my_list)
setnames(my_dt, names(my_vec[match(names(my_dt), my_vec)]))
my_dt[, (setdiff(names(my_vec), names(my_dt))) := NA]
setcolorder(my_dt, names(my_vec))
my_dt
输出
particles station energy area gamma
1: 2.30 NA -1.2 KIEL NA
2: 2.54 NA -1.6 KIEL NA
3: 2.56 NA -0.9 JUNG NA
4: 2.31 NA -0.3 ANT NA
【讨论】:
【参考方案3】:我写了一个简单的代码来为你完成这项工作:
l = list(c = 'cc', a = 'aa', b = NA) # replace this with your my_list
dt = data.frame(aa = 1:3, cc = 2:4) # replace this with my_dt
dtl = data.frame(l)
names(dt) = names(l)[na.omit(match(l, names(dt)))]
m = merge(dt, dtl[!is.element(names(dtl), names(dt))])
【讨论】:
谢谢你,马蒂亚!但我需要纯data.table
解决方案..
@Hilary,您确实应该在问题中指定该约束,以我阅读的方式假设它是不安全的。
我确信有一种方法可以将 data.table 转换为 data.frame(如果需要,还可以返回),例如使用 as.data.frame(my_dt)
l = my_list # replace this with your my_list
dt = as.data.frame(my_dt) # replace this with my_dt
dtl = data.frame(l)
names(dt) = names(l)[na.omit(match(l, names(dt)))]
m = merge(dt, dtl[!is.element(names(dtl), names(dt))])
以上是关于根据命名列表更新 dt 列的主要内容,如果未能解决你的问题,请参考以下文章
根据另一个 data.table 中的值更新 data.table