将每列总和除以矩阵的总和

Dan*_*nby 4 r dplyr

如果我有一个数据框:

d = data.frame(sample=c("a2","a3"),a=c(1,5),b=c(4,5),c=c(6,4))
d
    sample a b c
1     a2 1 4 6
2     a3 5 5 4
Run Code Online (Sandbox Code Playgroud)

我如何使用 dplyr 将每列的总和除以整个数据帧的总和,所以我最终得到一个如下所示的数据帧:

     a b c
1    6/25 9/25 10/25
Run Code Online (Sandbox Code Playgroud)

我试着做

d <- d %>%
mutate_if(is.numeric, funs(colSums(d)/sum(d)))
Run Code Online (Sandbox Code Playgroud)

但不断返回错误。

提前致谢!

G. *_*eck 6

除了 2a 和 2b,在这些替代方案中的每一个中,如果可以假设我们知道只有第一列是非数字的,我们可以用 d[-1] 替换管道的前两个组件。

1) Base R使用 base R,我们得到了一个直接的解决方案:

d |> Filter(f = is.numeric) |> colSums() |> prop.table()
##    a    b    c 
## 0.24 0.36 0.40 
Run Code Online (Sandbox Code Playgroud)

2) dplyr与 dplyr:

library(dplyr)

d %>%
  select(where(is.numeric)) %>%
  summarize(across(.fn = sum) / sum(.))
##      a    b   c
## 1 0.24 0.36 0.4
Run Code Online (Sandbox Code Playgroud)

2a)

d %>%
  summarize(across(where(is.numeric), sum)) %>%
  { . / sum(.) }
Run Code Online (Sandbox Code Playgroud)

2b)诸如 *_if 函数之类的作用域函数如今已被 cross 取代,但它们仍然可用,因此如果您无论如何都想使用它们,请尝试使用与问题中的代码相近的方法:

d %>%
  summarize_if(is.numeric, sum) %>%
  { . / sum(.) }
Run Code Online (Sandbox Code Playgroud)

3)collapse 用collapse 包,得到数值变量(nv),对每一列求和(fsum),然后取比例。当我在此数据上对其进行基准测试时,它的运行速度比 (1) 快 3 倍,比 (2) 快 100 倍以上,比 (4) 快 300 倍。

library(collapse)
d |> nv() |> fsum() |> fsum(TRA = "/")
##    a    b    c 
## 0.24 0.36 0.40 
Run Code Online (Sandbox Code Playgroud)

4) dplyr/tidyr使用 tidyr 和 dplyr 我们可以转换为长格式,处理并转换回来。

library(dplyr)
library(tidyr)
d %>%
  select(where(is.numeric)) %>%
  pivot_longer(everything()) %>%
  group_by(name) %>%
  summarize(value = sum(value) / sum(.$value), .groups = "drop") %>%
  pivot_wider
## # A tibble: 1 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1  0.24  0.36   0.4
Run Code Online (Sandbox Code Playgroud)