分组data.frame后的自定义功能

时间:2014-06-09 19:10:26

标签: r dataframe dplyr

给出以下data.frame

d <- rep(c("a", "b"), each=5)
l <- rep(1:5, 2) 
v <- 1:10

df       <- data.frame(d=d, l=l, v=v*v)
df
   d l   v
1  a 1   1
2  a 2   4
3  a 3   9
4  a 4  16
5  a 5  25
6  b 1  36
7  b 2  49
8  b 3  64
9  b 4  81
10 b 5 100

现在我想在l分组之后添加另一列。额外列应包含v_b - v_a

的值
   d l   v    e
1  a 1   1    35 (36-1)
2  a 2   4    45 (49-4)
3  a 3   9    55 (64-9)
4  a 4  16    65 (81-16)
5  a 5  25    75 (100-25)
6  b 1  36    35 (36-1)
7  b 2  49    45 (49-4)
8  b 3  64    55 (64-9)
9  b 4  81    65 (81-16)
10 b 5 100    75 (100-25)

在paranthesis中如何计算价值。

我正在寻找使用dplyr的方法。所以我开始用这样的东西

df %.% 
 group_by(l) %.%
 mutate(e=myCustomFunction)

但是我应该如何定义myCustomFunction?我认为data.frame的分组产生另一个(子)data.frame,它是这个函数的参数。但它不是......

4 个答案:

答案 0 :(得分:13)

我想这是dplyr等同于@ jlhoward的data.table解决方案:

df %>%
  group_by(l) %>%
  mutate(e = v[d == "b"] - v[d == "a"])

OP评论后编辑:

如果您想使用自定义功能,可以采用以下方式:

myfunc <- function(x) {
  with(x, v[d == "b"] - v[d == "a"])
}

test %>%
  group_by(l) %>%
  do(data.frame(. , e = myfunc(.))) %>%
  arrange(d, l)                   # <- just to get it back in the original order

@hadley评论后编辑:

正如hadley在下面评论的那样,在这种情况下将函数定义为

会更好
f <- function(v, d) v[d == "b"] - v[d == "a"]

然后在f

中使用自定义函数mutate
df %>%
  group_by(l) %>%
  mutate(e = f(v, d))  

感谢@hadley的评论。

答案 1 :(得分:4)

使用dplyr

df %.%   
  group_by(l)  %.%
  mutate(e=diff(v))

# d l   v  e
# 1  a 1   1 35
# 2  a 2   4 45
# 3  a 3   9 55
# 4  a 4  16 65
# 5  a 5  25 75
# 6  b 1  36 35
# 7  b 2  49 45
# 8  b 3  64 55
# 9  b 4  81 65
# 10 b 5 100 75

答案 2 :(得分:4)

这是一种使用数据表的方法。

library(data.table)
DT <- as.data.table(df)
DT[,e := diff(v), by=l]

使用diff(...)的这些方法假定您的data frame按照示例进行排序。如果没有,这是一种更可靠的方法来做同样的事情。

DT[, e := .SD[d == "b", v] - .SD[d == "a", v], by=l]

(或)更直接

DT[, e := v[d == "b"] - v[d == "a"], by=l]

但是如果您想访问整个数据子集并将其传递给自定义函数,那么您可以使用.SD。另外,请务必阅读?.SDcols中的?data.table

答案 3 :(得分:1)

如果你想考虑一个非dplyr选项

df$e <- with(df, ave(v, l, FUN=function(x) diff(x)))

会做到这一点。 ave函数可用于计算观察组的值。