如何使用动态维度引用跨数据框进行变异?

How to mutate across a dataframe using dynamic dimension references?

假设我们从下面显示的 data 数据帧开始,生成代码就在下面:

> data
   To A  B  C
1   A 1  3  5
2   B 2  4  6
3   C 4  5  7
4 Sum 7 12 18
   
library(dplyr)
data <- 
   data.frame(
     To = c("A","B","C"),
     A = c(1,2,4),
     B = c(3,4,5),
     C = c(5,6,7)
   ) %>% 
   bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(.) else "Sum")))

我已经 运行 下面的代码将数据框中的值更改为百分比(每个单元格计算为其各自列“总和”的百分比):

data %>% mutate(across(-1, ~ ./.[To == "Sum"]))

给出正确的输出:

> data 
   To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000

如何将 mutate(across...))[To == "Sum"] 的除数与对数据帧最后一行的动态(可能是数字)引用交换?在更完整的代码中,它根据用户对 Shiny 的输入动态地和反应性地 expands/contracts 部署在数据框中,并且列 header 名称也会动态更改,因此对“To”的固定引用 header此示例中的名称不是最佳名称。

简单的解释一下也有帮助,这样我就不用一直跑到槽里找答案了。

我们可以使用last 函数来return 列的最后一个值。此外,nth 还有另一个选项,我们可以根据更通用的索引获取列的值,即 nth(., 2) return 是第二个值

library(dplyr)
data %>% 
   mutate(across(-1, ~ ./last(.)))

-输出

 To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000

在 Base R 中你可以这样做:

addmargins(prop.table(as.matrix(data.frame(data, row.names = 1)),2),1)

            A         B         C
A   0.1428571 0.2500000 0.2777778
B   0.2857143 0.3333333 0.3333333
C   0.5714286 0.4166667 0.3888889
Sum 1.0000000 1.0000000 1.0000000

试试这个:这或多或少是 akrun 已经呈现的:

library(dplyr)

data <- 
  data.frame(
    To = c("A","B","C"),
    A = c(1,2,4),
    B = c(3,4,5),
    C = c(5,6,7)
  ) %>% 
  mutate(across(-1, ~ ./sum(.))) %>% 
  bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(.) else "Sum")))
   To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000