将数据框转换为比例

时间:2017-11-20 14:49:46

标签: r

我有一个数据框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

查看类似帖子,我看到通常建议使用scaleapply。 我发现简单地使用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

要与scaleapply达到相同的结果,我需要分别输入

as.data.frame(t(scale(t(df), center = FALSE, scale = rowSums(df))))

t(apply(df, 1, function(i) i/sum(i)))

df/rowSums(df)相比,这两种方法看起来都有点笨拙。

我的问题是:scaleapplydf/rowSums(df)之间是否存在真正的差异,还是个人偏好问题?也许我没有以最有效的方式使用前两个?

使用df/rowSums(df)似乎是一个简单而简短的解决方案。它有任何非明显的问题吗?

1 个答案:

答案 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的中位数比其他任何一个快两倍。

随着更多的列,它会变得更好。