我有这个数据框:
Generacion 1 2 3 4 5 6 NP1 NP2 NP3 NP4 NP5 NP6
1: 1 0 0 0 0 0 0 4 4 4 4 5 5
2: 2 0 0 0 0 0 0 4 4 4 4 4 4
3: 3 0 0 0 0 0 0 5 5 5 5 5 5
4: 4 0 0 0 0 0 0 4 5 5 5 4 4
5: 5 0 0 0 0 0 0 5 4 4 4 4 4
6: 6 0 0 0 0 0 0 5 5 5 5 4 4
我想修改列 1
到 6
,使每列计算右侧列 (NP1
- NP6
) 中该值出现的次数。也就是说,4
列应该计算 4
出现的次数。我希望对每个数字都重复这个过程。这个数字可以取值在 0
到 5
之间。最终结果应该像这样:
head(t2 %>% select(1, 2, 3, 4, 5, 6, 7, NP1, NP2, NP3, NP4, NP5, NP6))
Generacion 1 2 3 4 5 6 NP1 NP2 NP3 NP4 NP5 NP6
1: 1 0 0 0 4 2 0 4 4 4 4 5 5
2: 2 0 0 0 6 0 0 4 4 4 4 4 4
3: 3 0 0 0 0 6 0 5 5 5 5 5 5
4: 4 0 0 0 3 3 0 4 5 5 5 4 4
5: 5 0 0 0 5 1 0 5 4 4 4 4 4
6: 6 0 0 0 2 4 0 5 5 5 5 4 4
我尝试使用包data.table
,我已经执行了以下操作:
t2[NP1 == 4]$`4` <- t2[NP1 == 4]$`4` + 1
但是我遇到了以下错误:
在
[<-.data.table
(* tmp *
, NP1 == 4, value = c(1, 1, 1, 1))中出错: 无法在同一查询中两次分配相同的列(检测到重复项)。
因此我有两个问题:
- 为什么会出现这个错误?
- 是否有更简单、更直观的方法来完成它?
t2[,as.character(1:6):=lapply(1:6, function(n) rowSums(.SD==n)), .SDcols=patterns("^NP")]
更符合data.table
的规范。(尽管基准测试差异很小,但证明使用.SD
和.SDcols
略微比使用.SD[...]
更快。) - r2evansas.character(1:6)
与patterns("^NP")
程序化 同步。我猜更好的方法是在lapply
之前确定两组名称,也许是nms <- gsub("NP", "", grep("^NP", colnames(t2), value=TRUE))
然后t2[, (nms) := lapply(nms, function(n) rowSums(.SD==n)), .SDcols=paste0("NP", nms)]
。 - r2evans