我有一个数据框df
,我想用R来划分每个单元格的行总和。
set.seed(10);a <- sample(c(1:100), 5)
set.seed(11);b <- sample(c(1:100), 5)
set.seed(12);c <- sample(c(1:100), 5)
df <- as.data.frame(rbind(a,b,c))
>df
> V1 V2 V3 V4 V5
>a 51 31 42 68 9
>b 28 1 51 2 7
>c 7 81 93 27 17
查看类似帖子,我看到通常建议使用scale
或apply
。
我发现简单地使用df/rowSums(df)
对我有用:
V1 V2 V3 V4 V5
a 0.25373134 0.15422886 0.2089552 0.33830846 0.04477612
b 0.31460674 0.01123596 0.5730337 0.02247191 0.07865169
c 0.03111111 0.36000000 0.4133333 0.12000000 0.07555556
要与scale
或apply
达到相同的结果,我需要分别输入
as.data.frame(t(scale(t(df), center = FALSE, scale = rowSums(df))))
和
t(apply(df, 1, function(i) i/sum(i)))
与df/rowSums(df)
相比,这两种方法看起来都有点笨拙。
我的问题是:scale
,apply
和df/rowSums(df)
之间是否存在真正的差异,还是个人偏好问题?也许我没有以最有效的方式使用前两个?
使用df/rowSums(df)
似乎是一个简单而简短的解决方案。它有任何非明显的问题吗?
答案 0 :(得分:2)
您应该使用data.table框架。但我喜欢换位的想法......
require(data.table)
setDT(df)
ma_func <- function(df){
df = t(df)
for (col in names(df)){
set(df, NULL, col, df[[col]] / sum(df[[col]]))
}
df = t(df)
}
在my_func中,我转换data.table,按col执行转换col并将其转置回来。
现在对不同版本进行基准测试:
require(microbenchmark)
microbenchmark(
res1 <- df/rowSums(df),
res2 <- as.data.frame(t(scale(t(df), center = FALSE, scale = rowSums(df)))),
res3 <- t(apply(df, 1, function(i) i/sum(i))),
res4 <- ma_func(df)
)
结果是:
Unit: microseconds
expr min lq mean median uq max neval
res1 <- df/rowSums(df) 641.908 663.4615 745.1004 706.1280 775.920 1148.631 100
res2 <- as.data.frame(t(scale(t(df), center = FALSE, scale = rowSums(df)))) 185.623 201.4580 230.4596 212.4545 237.820 400.863 100
res3 <- t(apply(df, 1, function(i) i/sum(i))) 102.049 111.7255 145.5423 123.8950 140.170 1589.082 100
res4 <- ma_func(df) 51.611 61.1410 116.7342 65.5405 73.897 4825.307 100
正如你所看到的,my_func的中位数比其他任何一个快两倍。
随着更多的列,它会变得更好。