举一个例子来看看这个data.table:
foo <- data.table(id = letters[1:5], group = c('a', 'a', 'a', 'b', 'b'), x=1:5, y = (-4):0, z = 2:6)
id group x y z
1: a a 1 -4 2
2: b a 2 -3 3
3: c a 3 -2 4
4: d b 4 -1 5
5: e b 5 0 6
我想按组归一化列向量x,y和z(x/sum(x)
),即按列group
定义的那些组。我还想保留所有其他剩余的列。
我正在尝试这些方面:
foo[, lapply(.SD[, -1], function(x) {x/sum(x)}), by = group]
group x y z
1: a 0.1666667 0.4444444 0.2222222
2: a 0.3333333 0.3333333 0.3333333
3: a 0.5000000 0.2222222 0.4444444
4: b 0.4444444 1.0000000 0.4545455
5: b 0.5555556 0.0000000 0.5454545
但由于id
而删除了列.SD[, -1]
,但是我不知道如何只应用数字列而不删除它...
答案 0 :(得分:3)
我们可以指定.SDcols
并将输出分配回相同的列。
foo[, names(foo)[3:5] := lapply(.SD, function(x) x/sum(x)),
by = group, .SDcols = x:z]
请注意,输出和输入的类型应相同。如果输入为integer
且输出为numeric
则会出现问题。因此,首先将class
更改为numeric
,然后执行作业
nm1 <- names(foo)[3:5]
#or programmatically based on checking whether column is numeric
#nm1 <- foo[, which(unlist(lapply(.SD, is.numeric)))]
foo[, (nm1) := lapply(.SD, as.numeric), .SDcols = nm1
][, (nm1) := lapply(.SD, function(x) x/sum(x)),
by = group, .SDcols = nm1][]
上述tidyverse
方法
library(dplyr)
foo %>%
group_by(group) %>%
mutate_if(is.numeric, funs(./sum(.)))