如何使用 dplyr 生成基于行数据的新列?
How do I use dplyr to generate a new column based on rowwise data?
我想向基于逐行计算的数据框添加一个新列。假设我有这样一个数据框:
x <-as.data.frame(matrix(1:10, 5, 2))
V1 V2
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
如果我想做一些按行操作来生成一个新列,我可以使用 rowwise() 和 do() 来完成。例如:
y <- rowwise(x) %>% do (foo = .$V1 * .$V2)
我什至可以将其附加到现有数据框中:
y <- rowwise(x) %>% bind_cols(do (., foo = .$V1 * .$V2))
这一切都有效,但结果并不是我想要的。 y$foo 中的值是列表,而不是数字。
V1 V2 foo
1 1 6 6
2 2 7 14
3 3 8 24
4 4 9 36
5 5 10 50
看起来不错,但事实并非如此。
class(y$foo)
[1] "list"
那么,两个问题:
- 有没有办法让结果变成数字而不是列表?
- 有没有更好的方法来解决这个问题?
更新:
这更接近我正在尝试做的事情。鉴于此功能:
pts <- 11:20
z <- function(x1, x2) {
min(x1*x2*pts)
}
这没有产生我期望的结果:
y <- x %>% mutate(foo = z(V1, V2))
V1 V2 foo
1 1 6 66
2 2 7 66
3 3 8 66
4 4 9 66
5 5 10 66
同时这样做:
y <-rowwise(x) %>% bind_cols( do (., data.frame(foo = z(.$V1, .$V2))))
V1 V2 foo
1 1 6 66
2 2 7 154
3 3 8 264
4 4 9 396
5 5 10 550
为什么?有没有更好的方法?
x <-as.data.frame(matrix(1:10, 5, 2))
foo <- apply(x , 1 , function(x){
prod(x)
})
#[1] 6 14 24 36 50
class(foo)
#[1] "numeric"
df_final <- cbind(x , foo)
你应该 return 在你的 do
语句中 data.frame
:
y <- rowwise(x) %>% bind_cols(do(., data.frame(foo = .$V1 * .$V2)))
y
## V1 V2 foo
## 1 1 6 6
## 2 2 7 14
## 3 3 8 24
## 4 4 9 36
## 5 5 10 50
y$foo
## [1] 6 14 24 36 50
在您更新的问题中,您在带有 mutate
语句的链中缺少 rowwise
,但是在带有 do
语句的链中有 rowwise
.只需添加 rowwise
即可得到相同的结果。
x %>% rowwise %>% mutate(foo = z(V1, V2))
## Source: local data frame [5 x 3]
## Groups: <by row>
##
## V1 V2 foo
## 1 1 6 66
## 2 2 7 154
## 3 3 8 264
## 4 4 9 396
## 5 5 10 550
我通常不相信 R 等矢量化语言中的行式运算。在您的情况下,您可以通过简单的矩阵乘法来解决问题。
您可以定义 z
如下
z <- function(x1, x2) {
do.call(pmin, as.data.frame(tcrossprod(x1 * x2, pts)))
}
一个简单的 mutate
就可以了
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550
您还可以使用 matrixStats::rowMins
函数(完全矢量化)
来提高性能
library(matrixStats)
z <- function(x1, x2) {
rowMins(tcrossprod(x1 * x2, pts))
}
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550
我想向基于逐行计算的数据框添加一个新列。假设我有这样一个数据框:
x <-as.data.frame(matrix(1:10, 5, 2))
V1 V2
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
如果我想做一些按行操作来生成一个新列,我可以使用 rowwise() 和 do() 来完成。例如:
y <- rowwise(x) %>% do (foo = .$V1 * .$V2)
我什至可以将其附加到现有数据框中:
y <- rowwise(x) %>% bind_cols(do (., foo = .$V1 * .$V2))
这一切都有效,但结果并不是我想要的。 y$foo 中的值是列表,而不是数字。
V1 V2 foo
1 1 6 6
2 2 7 14
3 3 8 24
4 4 9 36
5 5 10 50
看起来不错,但事实并非如此。
class(y$foo)
[1] "list"
那么,两个问题:
- 有没有办法让结果变成数字而不是列表?
- 有没有更好的方法来解决这个问题?
更新:
这更接近我正在尝试做的事情。鉴于此功能:
pts <- 11:20
z <- function(x1, x2) {
min(x1*x2*pts)
}
这没有产生我期望的结果:
y <- x %>% mutate(foo = z(V1, V2))
V1 V2 foo
1 1 6 66
2 2 7 66
3 3 8 66
4 4 9 66
5 5 10 66
同时这样做:
y <-rowwise(x) %>% bind_cols( do (., data.frame(foo = z(.$V1, .$V2))))
V1 V2 foo
1 1 6 66
2 2 7 154
3 3 8 264
4 4 9 396
5 5 10 550
为什么?有没有更好的方法?
x <-as.data.frame(matrix(1:10, 5, 2))
foo <- apply(x , 1 , function(x){
prod(x)
})
#[1] 6 14 24 36 50
class(foo)
#[1] "numeric"
df_final <- cbind(x , foo)
你应该 return 在你的 do
语句中 data.frame
:
y <- rowwise(x) %>% bind_cols(do(., data.frame(foo = .$V1 * .$V2)))
y
## V1 V2 foo
## 1 1 6 6
## 2 2 7 14
## 3 3 8 24
## 4 4 9 36
## 5 5 10 50
y$foo
## [1] 6 14 24 36 50
在您更新的问题中,您在带有 mutate
语句的链中缺少 rowwise
,但是在带有 do
语句的链中有 rowwise
.只需添加 rowwise
即可得到相同的结果。
x %>% rowwise %>% mutate(foo = z(V1, V2))
## Source: local data frame [5 x 3]
## Groups: <by row>
##
## V1 V2 foo
## 1 1 6 66
## 2 2 7 154
## 3 3 8 264
## 4 4 9 396
## 5 5 10 550
我通常不相信 R 等矢量化语言中的行式运算。在您的情况下,您可以通过简单的矩阵乘法来解决问题。
您可以定义 z
如下
z <- function(x1, x2) {
do.call(pmin, as.data.frame(tcrossprod(x1 * x2, pts)))
}
一个简单的 mutate
就可以了
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550
您还可以使用 matrixStats::rowMins
函数(完全矢量化)
library(matrixStats)
z <- function(x1, x2) {
rowMins(tcrossprod(x1 * x2, pts))
}
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550