使用dplyr将函数应用于表的每一行?
在使用使用dplyr将函数应用于表的每一行?,r,plyr,dplyr,R,Plyr,Dplyr,在使用plyr时,我经常发现使用adply对必须应用于每一行的标量函数很有用 e、 g 现在我使用的是dplyr更多,我想知道是否有一种整洁/自然的方法可以做到这一点?因为这不是我想要的: library(dplyr) head( mutate(iris, Max.Len= max(Sepal.Length,Petal.Length)) ) Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len 1
plyr
时,我经常发现使用adply
对必须应用于每一行的标量函数很有用
e、 g
现在我使用的是dplyr
更多,我想知道是否有一种整洁/自然的方法可以做到这一点?因为这不是我想要的:
library(dplyr)
head(
mutate(iris, Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 7.9
2 4.9 3.0 1.4 0.2 setosa 7.9
3 4.7 3.2 1.3 0.2 setosa 7.9
4 4.6 3.1 1.5 0.2 setosa 7.9
5 5.0 3.6 1.4 0.2 setosa 7.9
6 5.4 3.9 1.7 0.4 setosa 7.9
像这样的
iris$Max.Len <- pmax(iris$Sepal.Length, iris$Petal.Length)
iris$Max.Len您需要按行分组:
iris %>% group_by(1:n()) %>% mutate(Max.Len= max(Sepal.Length,Petal.Length))
这就是1
在adply
中所做的,惯用的方法是创建一个适当的矢量化函数
library(dplyr)
# use base R pmax (vectorized in C)
iris %>% mutate(max.len = pmax(Sepal.Length, Petal.Length))
# use vectorize to create your own function
# for example, a horribly inefficient get first non-Na value function
# a version that is not vectorized
coalesce <- function(a,b) {r <- c(a[1],b[1]); r[!is.na(r)][1]}
# a vectorized version
Coalesce <- Vectorize(coalesce, vectorize.args = c('a','b'))
# some example data
df <- data.frame(a = c(1:5,NA,7:10), b = c(1:3,NA,NA,6,NA,10:8))
df %>% mutate(ab =Coalesce(a,b))
Called from: ..f(.d[[i]], ...)
Browse[1]> this_row
# A tibble: 1 × 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<dbl> <dbl> <dbl> <dbl> <fctr>
1 5.1 3.5 1.4 0.2 setosa
Browse[1]> Q
R
提供适用于此处的pmax
,但它也提供Vectorize
作为mapply
的包装,允许您创建任意函数的矢量化任意版本
library(dplyr)
# use base R pmax (vectorized in C)
iris %>% mutate(max.len = pmax(Sepal.Length, Petal.Length))
# use vectorize to create your own function
# for example, a horribly inefficient get first non-Na value function
# a version that is not vectorized
coalesce <- function(a,b) {r <- c(a[1],b[1]); r[!is.na(r)][1]}
# a vectorized version
Coalesce <- Vectorize(coalesce, vectorize.args = c('a','b'))
# some example data
df <- data.frame(a = c(1:5,NA,7:10), b = c(1:3,NA,NA,6,NA,10:8))
df %>% mutate(ab =Coalesce(a,b))
库(dplyr)
#使用基本R pmax(用C矢量化)
虹膜%>%突变(最大长度=pmax(萼片长度,花瓣长度))
#使用矢量化创建您自己的函数
#例如,一个效率极低的get first非Na值函数
#未矢量化的版本
联合扩展BrodieG的答案
如果函数返回多行,则必须使用do()
而不是mutate()
。然后使用dplyr
包中的rbind\u all()
将其组合在一起
在dplyr
版本dplyr\u 0.1.2
中,在group\u by()
子句中使用1:n()。希望很快
测试性能,
library(plyr) # plyr_1.8.4.9000
library(dplyr) # dplyr_0.8.0.9000
library(purrr) # purrr_0.2.99.9000
library(microbenchmark)
d1_count <- 1000
d2_count <- 10
d1 <- data.frame(a=runif(d1_count))
do_fn <- function(row){data.frame(a=row$a, b=runif(d2_count))}
do_fn2 <- function(a){data.frame(a=a, b=runif(d2_count))}
op <- microbenchmark(
plyr_version = plyr::adply(d1, 1, do_fn),
dplyr_version = d1 %>%
dplyr::group_by(1:nrow(d1)) %>%
dplyr::do(do_fn(.)) %>%
dplyr::bind_rows(),
purrr_version = d1 %>% purrr::pmap_dfr(do_fn2),
times=50)
这表明新的purrr
版本是自dplyr 0.2(我认为)rowwise()
实现以来最快的版本,因此这个问题的答案是:
iris %>%
rowwise() %>%
mutate(Max.Len= max(Sepal.Length,Petal.Length))
非rowwise
备选方案
五年后(!)这个答案仍然获得了大量的流量。自从它被给出以来,rowwise
越来越不被推荐,尽管很多人似乎觉得它很直观。帮自己一个忙,仔细阅读詹妮·布莱恩的材料,以便更好地把握这个话题
我发现的最直接的方法是基于哈德利的一个例子,使用pmap
:
iris %>%
mutate(Max.Len= purrr::pmap_dbl(list(Sepal.Length, Petal.Length), max))
使用这种方法,您可以为pmap
中的函数(.f
)提供任意数量的参数
pmap
是一种很好的概念方法,因为它反映了这样一个事实,即当您执行行操作时,实际上是在使用向量列表(数据帧中的列)中的元组。更新2017-08-03
写完这篇文章后,哈德利又换了一些东西。以前在purrr中的功能现在在中,描述如下:
purrlyr包含一些位于purrr和dplyr交叉点的函数。它们已从purrr中移除,以使包装更轻,因为它们已被tidyverse中的其他解决方案所取代
因此,您需要安装并加载该软件包才能使下面的代码正常工作
原职
Hadley经常改变我们应该使用什么的想法,但我认为我们应该切换到purrr中的函数来获得按行功能。至少,它们提供了与plyr中的adply
相同的功能和界面
有两个相关函数,按行
和调用行
。我的理解是,当您想要循环行并将结果添加到data.frame时,您可以使用by_row
invoke_rows
用于循环data.frame的行并将每个列作为参数传递给函数。我们将只使用第一个
例子
这让我们可以看到内部结构(这样我们就可以看到我们正在做什么),这与使用adply
进行操作是一样的
Called from: ..f(.d[[i]], ...)
Browse[1]> this_row
# A tibble: 1 × 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<dbl> <dbl> <dbl> <dbl> <fctr>
1 5.1 3.5 1.4 0.2 setosa
Browse[1]> Q
给出:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <dbl [1]>
2 4.9 3.0 1.4 0.2 setosa <dbl [1]>
3 4.7 3.2 1.3 0.2 setosa <dbl [1]>
4 4.6 3.1 1.5 0.2 setosa <dbl [1]>
5 5.0 3.6 1.4 0.2 setosa <dbl [1]>
6 5.4 3.9 1.7 0.4 setosa <dbl [1]>
7 4.6 3.4 1.4 0.3 setosa <dbl [1]>
8 5.0 3.4 1.5 0.2 setosa <dbl [1]>
9 4.4 2.9 1.4 0.2 setosa <dbl [1]>
10 4.9 3.1 1.5 0.1 setosa <dbl [1]>
# ... with 140 more rows
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <data.frame [1 × 2]>
2 4.9 3.0 1.4 0.2 setosa <data.frame [1 × 2]>
3 4.7 3.2 1.3 0.2 setosa <data.frame [1 × 2]>
4 4.6 3.1 1.5 0.2 setosa <data.frame [1 × 2]>
5 5.0 3.6 1.4 0.2 setosa <data.frame [1 × 2]>
6 5.4 3.9 1.7 0.4 setosa <data.frame [1 × 2]>
7 4.6 3.4 1.4 0.3 setosa <data.frame [1 × 2]>
8 5.0 3.4 1.5 0.2 setosa <data.frame [1 × 2]>
9 4.4 2.9 1.4 0.2 setosa <data.frame [1 × 2]>
10 4.9 3.1 1.5 0.1 setosa <data.frame [1 × 2]>
# ... with 140 more rows
给出:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <dbl [1]>
2 4.9 3.0 1.4 0.2 setosa <dbl [1]>
3 4.7 3.2 1.3 0.2 setosa <dbl [1]>
4 4.6 3.1 1.5 0.2 setosa <dbl [1]>
5 5.0 3.6 1.4 0.2 setosa <dbl [1]>
6 5.4 3.9 1.7 0.4 setosa <dbl [1]>
7 4.6 3.4 1.4 0.3 setosa <dbl [1]>
8 5.0 3.4 1.5 0.2 setosa <dbl [1]>
9 4.4 2.9 1.4 0.2 setosa <dbl [1]>
10 4.9 3.1 1.5 0.1 setosa <dbl [1]>
# ... with 140 more rows
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <data.frame [1 × 2]>
2 4.9 3.0 1.4 0.2 setosa <data.frame [1 × 2]>
3 4.7 3.2 1.3 0.2 setosa <data.frame [1 × 2]>
4 4.6 3.1 1.5 0.2 setosa <data.frame [1 × 2]>
5 5.0 3.6 1.4 0.2 setosa <data.frame [1 × 2]>
6 5.4 3.9 1.7 0.4 setosa <data.frame [1 × 2]>
7 4.6 3.4 1.4 0.3 setosa <data.frame [1 × 2]>
8 5.0 3.4 1.5 0.2 setosa <data.frame [1 × 2]>
9 4.4 2.9 1.4 0.2 setosa <data.frame [1 × 2]>
10 4.9 3.1 1.5 0.1 setosa <data.frame [1 × 2]>
# ... with 140 more rows
两者都产生:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <dbl>
1 5.1 3.5 1.4 0.2 setosa 2.550
2 4.9 3.0 1.4 0.2 setosa 2.375
3 4.7 3.2 1.3 0.2 setosa 2.350
4 4.6 3.1 1.5 0.2 setosa 2.350
5 5.0 3.6 1.4 0.2 setosa 2.550
6 5.4 3.9 1.7 0.4 setosa 2.850
7 4.6 3.4 1.4 0.3 setosa 2.425
8 5.0 3.4 1.5 0.2 setosa 2.525
9 4.4 2.9 1.4 0.2 setosa 2.225
10 4.9 3.1 1.5 0.1 setosa 2.400
# ... with 140 more rows
两者都给出:
# A tibble: 150 × 8
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .row new_col_mean new_col_median
<dbl> <dbl> <dbl> <dbl> <fctr> <int> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 1 2.550 2.45
2 4.9 3.0 1.4 0.2 setosa 2 2.375 2.20
3 4.7 3.2 1.3 0.2 setosa 3 2.350 2.25
4 4.6 3.1 1.5 0.2 setosa 4 2.350 2.30
5 5.0 3.6 1.4 0.2 setosa 5 2.550 2.50
6 5.4 3.9 1.7 0.4 setosa 6 2.850 2.80
7 4.6 3.4 1.4 0.3 setosa 7 2.425 2.40
8 5.0 3.4 1.5 0.2 setosa 8 2.525 2.45
9 4.4 2.9 1.4 0.2 setosa 9 2.225 2.15
10 4.9 3.1 1.5 0.1 setosa 10 2.400 2.30
# ... with 140 more rows
分别产生:
# A tibble: 32 × 3
mpg cyl .out
<dbl> <dbl> <list>
1 21.0 6 <int [5]>
2 21.0 6 <int [5]>
3 22.8 4 <int [5]>
4 21.4 6 <int [5]>
5 18.7 8 <int [5]>
6 18.1 6 <int [5]>
7 14.3 8 <int [5]>
8 24.4 4 <int [5]>
9 22.8 4 <int [5]>
10 19.2 6 <int [5]>
# ... with 22 more rows
# A tibble: 160 × 4
mpg cyl .row .out
<dbl> <dbl> <int> <int>
1 21 6 1 1
2 21 6 1 2
3 21 6 1 3
4 21 6 1 4
5 21 6 1 5
6 21 6 2 1
7 21 6 2 2
8 21 6 2 3
9 21 6 2 4
10 21 6 2 5
# ... with 150 more rows
# A tibble: 32 × 7
mpg cyl .out1 .out2 .out3 .out4 .out5
<dbl> <dbl> <int> <int> <int> <int> <int>
1 21.0 6 1 2 3 4 5
2 21.0 6 1 2 3 4 5
3 22.8 4 1 2 3 4 5
4 21.4 6 1 2 3 4 5
5 18.7 8 1 2 3 4 5
6 18.1 6 1 2 3 4 5
7 14.3 8 1 2 3 4 5
8 24.4 4 1 2 3 4 5
9 22.8 4 1 2 3 4 5
10 19.2 6 1 2 3 4 5
# ... with 22 more rows
#一个tible:32×3
mpg共青团出局
1 21.0 6
2 21.0 6
3 22.8 4
4 21.4 6
5 18.7 8
6 18.1 6
7 14.3 8
8 24.4 4
9 22.8 4
10 19.2 6
# ... 还有22排
#一个tibble:160×4
mpg气缸,世界其他地区,完毕
1 21 6 1 1
2 21 6 1 2
3 21 6 1 3
4 21 6 1 4
5 21 6 1 5
6 21 6 2 1
7 21 6 2 2
8 21 6 2 3
9 21 6 2 4
10 21 6 2 5
# ... 还有150行
#一个tibble:32×7
mpg气缸输出1.输出2.输出3.输出4.输出5
1 21.0 6 1 2 3 4 5
2 21.0 6 1 2 3 4 5
3 22.8 4 1 2 3 4 5
4 21.4 6 1 2 3 4 5
5 18.7 8 1 2 3 4 5
6 18.1 6 1 2 3 4 5
7 14.3 8 1 2 3 4 5
8 24.4 4 1 2 3 4 5
9 22.8 4 1 2 3 4 5
10 19.2 6 1 2 3 4 5
# ... 还有22排
所以,底线是。如果您想使用adply(.margins=1,…)
功能,除了@alexwhan提供的精彩答案外,您还可以使用按行,请记住您需要使用解组()
以避免副作用。这是因为rowwise()
是一个分组操作
iris %>%
rowwise() %>%
mutate(Max.Len = max(Sepal.Length, Petal.Length))
将为您提供:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1
2 4.9 3 1.4 0.2 setosa 4.9
3 4.7 3.2 1.3 0.2 setosa 4.7
4 4.6 3.1 1.5 0.2 setosa 4.6
5 5 3.6 1.4 0.2 setosa 5
6 5.4 3.9 1.7 0.4 setosa 5.4
7 4.6 3.4 1.4 0.3 setosa 4.6
8 5 3.4 1.5 0.2 setosa 5
9 4.4 2.9 1.4 0.2 setosa 4.4
10 4.9 3.1 1.5 0.1 setosa 4.9
这将产生:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len Lead.Max.Len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1 NA
2 4.9 3 1.4 0.2 setosa 4.9 NA
3 4.7 3.2 1.3 0.2 setosa 4.7 NA
4 4.6 3.1 1.5 0.2 setosa 4.6 NA
5 5 3.6 1.4 0.2 setosa 5 NA
6 5.4 3.9 1.7 0.4 setosa 5.4 NA
7 4.6 3.4 1.4 0.3 setosa 4.6 NA
8 5 3.4 1.5 0.2 setosa 5 NA
9 4.4 2.9 1.4 0.2 setosa 4.4 NA
10 4.9 3.1 1.5 0.1 setosa 4.9 NA
这将产生所需的输出:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len lead.max.len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1 4.9
2 4.9 3 1.4 0.2 setosa 4.9 4.7
3 4.7 3.2 1.3 0.2 setosa 4.7 4.6
4 4.6 3.1 1.5 0.2 setosa 4.6 5
5 5 3.6 1.4 0.2 setosa 5 5.4
6 5.4 3.9 1.7 0.4 setosa 5.4 4.6
7 4.6 3.4 1.4 0.3 setosa 4.6 5
8 5 3.4 1.5 0.2 setosa 5 4.4
9 4.4 2.9 1.4 0.2 setosa 4.4 4.9
10 4.9 3.1 1.5 0.1 setosa 4.9 5.4
萼片。长度萼片。宽度花瓣。长度花瓣。宽度品种最大长度铅最大长度
1 5.1 3.5 1.4 0.2 setosa 5.1 4.9
2 4.9 3 1.4 0.2 setosa 4.9 4.7
3 4.7 3.2 1.3 0.2 setosa 4.7 4.6
4.6 3.1 1.5 0.2 setosa 4.6 5
5 5 3
# A tibble: 32 × 3
mpg cyl .out
<dbl> <dbl> <list>
1 21.0 6 <int [5]>
2 21.0 6 <int [5]>
3 22.8 4 <int [5]>
4 21.4 6 <int [5]>
5 18.7 8 <int [5]>
6 18.1 6 <int [5]>
7 14.3 8 <int [5]>
8 24.4 4 <int [5]>
9 22.8 4 <int [5]>
10 19.2 6 <int [5]>
# ... with 22 more rows
# A tibble: 160 × 4
mpg cyl .row .out
<dbl> <dbl> <int> <int>
1 21 6 1 1
2 21 6 1 2
3 21 6 1 3
4 21 6 1 4
5 21 6 1 5
6 21 6 2 1
7 21 6 2 2
8 21 6 2 3
9 21 6 2 4
10 21 6 2 5
# ... with 150 more rows
# A tibble: 32 × 7
mpg cyl .out1 .out2 .out3 .out4 .out5
<dbl> <dbl> <int> <int> <int> <int> <int>
1 21.0 6 1 2 3 4 5
2 21.0 6 1 2 3 4 5
3 22.8 4 1 2 3 4 5
4 21.4 6 1 2 3 4 5
5 18.7 8 1 2 3 4 5
6 18.1 6 1 2 3 4 5
7 14.3 8 1 2 3 4 5
8 24.4 4 1 2 3 4 5
9 22.8 4 1 2 3 4 5
10 19.2 6 1 2 3 4 5
# ... with 22 more rows
iris %>%
rowwise() %>%
mutate(Max.Len = max(Sepal.Length, Petal.Length))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1
2 4.9 3 1.4 0.2 setosa 4.9
3 4.7 3.2 1.3 0.2 setosa 4.7
4 4.6 3.1 1.5 0.2 setosa 4.6
5 5 3.6 1.4 0.2 setosa 5
6 5.4 3.9 1.7 0.4 setosa 5.4
7 4.6 3.4 1.4 0.3 setosa 4.6
8 5 3.4 1.5 0.2 setosa 5
9 4.4 2.9 1.4 0.2 setosa 4.4
10 4.9 3.1 1.5 0.1 setosa 4.9
iris %>%
rowwise() %>%
mutate(Max.Len = max(Sepal.Length, Petal.Length)) %>%
mutate(Lead.Max.Len = lead(Max.Len))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len Lead.Max.Len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1 NA
2 4.9 3 1.4 0.2 setosa 4.9 NA
3 4.7 3.2 1.3 0.2 setosa 4.7 NA
4 4.6 3.1 1.5 0.2 setosa 4.6 NA
5 5 3.6 1.4 0.2 setosa 5 NA
6 5.4 3.9 1.7 0.4 setosa 5.4 NA
7 4.6 3.4 1.4 0.3 setosa 4.6 NA
8 5 3.4 1.5 0.2 setosa 5 NA
9 4.4 2.9 1.4 0.2 setosa 4.4 NA
10 4.9 3.1 1.5 0.1 setosa 4.9 NA
iris %>%
rowwise() %>%
mutate(Max.Len = max(Sepal.Length, Petal.Length)) %>%
ungroup() %>%
mutate(Lead.Max.Len = lead(Max.Len))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len lead.max.len
<dbl> <dbl> <dbl> <dbl> <fct> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 5.1 4.9
2 4.9 3 1.4 0.2 setosa 4.9 4.7
3 4.7 3.2 1.3 0.2 setosa 4.7 4.6
4 4.6 3.1 1.5 0.2 setosa 4.6 5
5 5 3.6 1.4 0.2 setosa 5 5.4
6 5.4 3.9 1.7 0.4 setosa 5.4 4.6
7 4.6 3.4 1.4 0.3 setosa 4.6 5
8 5 3.4 1.5 0.2 setosa 5 4.4
9 4.4 2.9 1.4 0.2 setosa 4.4 4.9
10 4.9 3.1 1.5 0.1 setosa 4.9 5.4