使用mutate_all

时间:2019-01-03 21:28:23

标签: r dplyr mutate

我有一个示例数据框,看起来像这样(我的完整数据框有“ d”加57个元素):

d <- seq(0, 100, 0.5) 
Fe <- runif(201, min = 0, max = 1000) 
Ca <- runif(201, min = 0, max = 1000) 
Zr <- runif(201, min = 0, max = 1000) 
Ti <- runif(201, min = 0, max = 1000) 
Al <- runif(201, min = 0, max = 1000) 
example <- data.frame(d, Fe, Ca, Zr, Ti, Al)
Ratio_Elements <- c("Fe", "Ti", "Zr", "d") #this subset of the 
dataframe is user defined
Detrital_Divisor <- "Zr"

Detrital_Divisor可以根据用户输入进行更改,但始终是“示例”数据框中的一列。我想将所有剩余的列除以Detrital_Divisor列,最好使用管道。现在我有:

Example_Ratio <- example %>%
select (Ratio_Elements) #to subset to the user selected elements
mutate_all(./Detrital_Divisor)

但是我得到了错误:

Error in Ops.data.frame(., Detrital_Divisor) : 
  ‘/’ only defined for equally-sized data frames.

我也尝试过:

Example_Ratio <- example %>%
select (Ratio_Elements)
sweep(., Detrital_Divisor, MARGIN = 1, '/')

基于在此论坛上提出的类似问题,但我无法使其正常工作。我收到错误

    `Error in Ops.data.frame(x, aperm(array(STATS, dims[perm]), order(perm)),  : 
  list of length 206340 not meaningful.`

我知道这个问题有些重复,但是我发现的其他答案在我的情况下不起作用。我的整个数据框包含57个元素,因此编写代码以单独划分每一列会很长。

预先感谢您的任何建议。

2 个答案:

答案 0 :(得分:4)

可能是这样的:

library(tidyverse)

d <- seq(0, 100, 0.5) 
Fe <- runif(201, min = 0, max = 1000) 
Ca <- runif(201, min = 0, max = 1000) 
Zr <- runif(201, min = 0, max = 1000) 
Ti <- runif(201, min = 0, max = 1000) 
Al <- runif(201, min = 0, max = 1000) 
example <- data.frame(d, Fe, Ca, Zr, Ti, Al)
Ratio_Elements <- c("Fe", "Ti", "Zr", "d") #this subset of the 

Example_Ratio <- example %>%
  mutate_at(vars(-Zr), funs(. / Zr)) %>%
  select(Ratio_Elements)

我知道您说过您想看到一个mutate_all解决方案,但是我想您不想将Zr本身分开吗?

在这种情况下,mutate_at会更有用,否则,您可以执行mutate_all(funs(. / Zr))

如果要保留提到的向量:

Detrital_Divisor <- as.symbol("Zr")

Example_Ratio <- example %>%
  mutate_at(vars(- !! Detrital_Divisor), funs(. / !! Detrital_Divisor)) %>%
  select(Ratio_Elements)

答案 1 :(得分:1)

通过@ arg0naut91更新答案(dplyr 1.0.0)

Example_Ratio <- example %>% 
  mutate(across(everything()), . / Zr) %>% 
  select(Ratio_Elements)