【发布时间】:2019-10-18 07:04:09
【问题描述】:
我正在使用 for (i in cols) 循环遍历列表 cols = c("x", "y", "z"),但是:
- 使用“:=”创建新列时,无法将“i”用作列名
- 我创建了 mode_func 来获取向量中出现频率最高的字符串,但是当我使用 lapply 时,“i”似乎没有用作列。
有人可以帮我理解 for 循环中“i”的问题和动态吗?非常感谢!
set.seed(10)
dummy = data.table(id = c("11", "11", "11", "22", "22", "22", "33", "33", "33", "33"),
x = sample(c("a", "b", "c"), 10, replace = T),
y = sample(c("a", "b", "c"), 10, replace = T),
z = sample(c("a", "b", "c"), 10, replace = T),
i = sample(3, 10, replace = T),
j = sample(3, 10, replace = T),
k = sample(3, 10, replace = T))
mode_func <- function(x) {
uniqx <- unique(na.omit(x))
uniqx[which.max(tabulate(match(x, uniqx)))]
}
(1) 最频繁
cols = c("x", "y", "z")
for (i in cols){
dummy[, as.character(i) := mode_func(i), by = "id"]
}
# The following works but it's too much coding!
dummy[, x := mode_func(x), by = "id"]
dummy[, y := mode_func(y), by = "id"]
dummy[, z := mode_func(z), by = "id"]
预期的结果如下所示:
id x y z
1: 11 b b c
2: 11 b b c
3: 11 b b c
4: 22 a b b
5: 22 a b b
6: 22 a b b
7: 33 a a c
8: 33 a a c
9: 33 a a c
10: 33 a a c
(2) 我也尝试了平均值,但这对我不起作用:
cols = c("i", "j", "k")
dummy[, (cols) := lapply(.SD, function(x) round(mean(x, na.rm = T))), .SDcols = cols, by = "id"]
【问题讨论】:
-
为了运行你的循环,你可以做
for (i in cols) dummy[, (i) := mode_func(.SD), .SDcols = i, by = id]。关于您第二次尝试中的错误,它只是类型不匹配。您的代码很好,但您试图用双精度组覆盖整数列。所以有一个阶段,当列的一部分仍然是整数(1、2、3)并且它的一部分变成双倍(例如,2.5)并且 R 不能有一个包含两个类的列。您可以通过创建新列来说明这一点,例如,dummy[, paste0(cols, "_mean") := lapply(.SD, mean, na.rm = TRUE), .SDcols = cols, by = id] -
在使用列名作为索引时也应该小心,它会使环境变得混乱。你们都有一个名为
i的列,并且您还在i上运行循环。这会弄乱mget/get等函数。因此,如果您将i替换为a,您也可以使用for (a in cols) dummy[, (a) := mode_func(get(a)), by = id]。您不能只运行mode_func(i)的原因是因为 data.table 在 j 中进行非标准评估,因此它希望列名不被引用 - 例如i而不是"i"。 -
非常感谢您的详细解释和解决方案!祝你有美好的一天,来自巴塞罗那的问候:)
标签: r for-loop data.table