[英]using mutate_at from dplyr
我有一个包含 5 列的数据框,我想生成 4 个额外的列,给出最后 4 列和第一列之间的差异。 我尝试了以下方法,但这不起作用:
library(tidyverse)
df <- as.tibble(data.frame(A = c(1,2), B = c(3,4), C = c(4,5), D = c(2,3), E = c(4,5)))
r_diff <- function(x,y){
z = y - x
return(z)
}
vars_to_process <- c("B","C","D","E")
df %>% mutate_at(.cols=vars_to_process, .funs =r_diff(.,df[,1])) %>% head()
谢谢仁格
这是最简单的方法。
df %>%
mutate_at(.vars = vars(B:E),
.funs = list(~ . - A))
.vars
参数允许您以与在select()
指定列相同的方式指定列,前提是您将该规范放在函数vars()
。
.funs
参数接受在调用list()
定义的匿名函数。 并且您可以在定义此匿名函数时引用数据框中的列(在本例中为A
)(请参阅此 Stackoverflow 问题)。
此外,随着 dplyr 1.0.0 的发布,您现在可以简单地执行以下操作:
df %>%
mutate(across(B:E, ~ . - A))
这是使用基本 R 代码的更快解决方案。 策略转换为矩阵,从所需的列中减去第一列,重新构建为数据框。 请注意,这只是返回修改后的列-如果没有在列vars_to_process
他们将不会出现在输出中,但你没有任何那些在你测试集,所以我会假设它们不存在。
所以,尽可能在函数中写东西:
bsr = function(df,vars_to_process){
m = as.matrix(df)
data.frame(
A = m[, 1],
m[, 1] - m[, vars_to_process])}
制作一些测试数据:
> df = data.frame(matrix(runif(5*1000), ncol=5))
> names(df)=LETTERS[1:5]
> dft = as.tibble(df)
> head(dft)
# A tibble: 6 x 5
A B C D E
<dbl> <dbl> <dbl> <dbl> <dbl>
1 0.2609174 0.07857624 0.2727817 0.8498004 0.3403234
2 0.3644744 0.95810657 0.8183856 0.2958133 0.4752349
3 0.6042914 0.98793218 0.7547003 0.9596591 0.5354045
4 0.4000441 0.61403331 0.9018804 0.3838347 0.3266855
5 0.6767012 0.11984219 0.9181570 0.5988404 0.6058629
与tidyverse版本对比:
akr = function(df,vars_to_process){
df %>% mutate_at(vars_to_process, funs(r_diff(.,df[[1]])))
}
检查bsr
和akr
是否同意:
> head(bsr(dft, vars_to_process))
A B C D E
1 0.2609174 0.1823412 -0.01186432 -0.58888295 -0.07940594
2 0.3644744 -0.5936322 -0.45391119 0.06866108 -0.11076050
3 0.6042914 -0.3836408 -0.15040892 -0.35536765 0.06888696
4 0.4000441 -0.2139892 -0.50183635 0.01620939 0.07335861
> head(akr(dft, vars_to_process))
# A tibble: 6 x 5
A B C D E
<dbl> <dbl> <dbl> <dbl> <dbl>
1 0.2609174 0.1823412 -0.01186432 -0.58888295 -0.07940594
2 0.3644744 -0.5936322 -0.45391119 0.06866108 -0.11076050
3 0.6042914 -0.3836408 -0.15040892 -0.35536765 0.06888696
4 0.4000441 -0.2139892 -0.50183635 0.01620939 0.07335861
好的,除了akr
返回一个akr
但 nm。 基准:
> microbenchmark(bsr(dft, vars_to_process),akr(dft, vars_to_process))
Unit: microseconds
expr min lq mean median uq
bsr(dft, vars_to_process) 362.117 388.7215 488.9309 446.123 521.776
akr(dft, vars_to_process) 8070.391 8365.4230 9853.5239 8673.692 9335.613
Base R 版本的速度提高了 26 倍。 我还认为,从另一组列中减去一列比应用 mutator 函数更整洁,但只要您将所做的事情包装在一个函数中,那么胆量有多混乱都没有关系。
我们需要用[[
对列进行子集化,因为[
仍然是一个data.frame
df %>%
mutate_at(vars_to_process, funs(r_diff(.,df[[1]])))
# A tibble: 2 x 5
# A B C D E
# <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1 -2 -3 -1 -3
#2 2 -2 -3 -1 -3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.