19

我有一个 R 数据框,例如:

df <- data.frame(period=rep(1:4,2), 
                 farm=c(rep('A',4),rep('B',4)), 
                 cumVol=c(1,5,15,31,10,12,16,24),
                 other = 1:8);

  period farm cumVol other
1      1    A      1     1
2      2    A      5     2
3      3    A     15     3
4      4    A     31     4
5      1    B     10     5
6      2    B     12     6
7      3    B     16     7
8      4    B     24     8

忽略“其他”列,如何找到每个农场在每个时期的 cumVol 变化?我想要一个这样的数据框(可选择保留 cumVol 列):

  period farm volume other
1      1    A      0     1
2      2    A      4     2
3      3    A     10     3
4      4    A     16     4
5      1    B      0     5
6      2    B      2     6
7      3    B      4     7
8      4    B      8     8

在实践中,可能有许多类似“农场”的列,以及许多类似“其他”(即忽略)的列。我希望能够使用变量指定所有列名。

我正在使用 dplyr 包。

4

4 回答 4

46

在 dplyr 中:

require(dplyr)
df %>%
  group_by(farm) %>%
  mutate(volume = cumVol - lag(cumVol, default = cumVol[1]))

Source: local data frame [8 x 5]
Groups: farm

  period farm cumVol other volume
1      1    A      1     1      0
2      2    A      5     2      4
3      3    A     15     3     10
4      4    A     31     4     16
5      1    B     10     5      0
6      2    B     12     6      2
7      3    B     16     7      4
8      4    B     24     8      8

也许所需的输出实际上应该如下所示?

df %>%
  group_by(farm) %>%
  mutate(volume = cumVol - lag(cumVol, default = 0))

  period farm cumVol other volume
1      1    A      1     1      1
2      2    A      5     2      4
3      3    A     15     3     10
4      4    A     31     4     16
5      1    B     10     5     10
6      2    B     12     6      2
7      3    B     16     7      4
8      4    B     24     8      8

编辑:跟进您的评论,我认为您正在寻找安排()。如果不是这样,最好开始一个新问题。

df1 <- data.frame(period=rep(1:4,4), farm=rep(c(rep('A',4),rep('B',4)),2), crop=(c(rep('apple',8), rep('pear',8))), cumCropVol=c(1,5,15,31,10,12,16,24,11,15,25,31,20,22,26,34), other = rep(1:8,2) ); 
df1 %>% 
  arrange(desc(period), desc(farm)) %>%
  group_by(period, farm) %>% 
  summarise(cumVol=sum(cumCropVol))

编辑:跟进#2

df1 <- data.frame(period=rep(1:4,4), farm=rep(c(rep('A',4),rep('B',4)),2), crop=(c(rep('apple',8), rep('pear',8))), cumCropVol=c(1,5,15,31,10,12,16,24,11,15,25,31,20,22,26,34), other = rep(1:8,2) ); 
df <- df1 %>% 
  arrange(desc(period), desc(farm)) %>% 
  group_by(period, farm) %>% 
  summarise(cumVol=sum(cumCropVol))

ungroup(df) %>% 
  arrange(farm) %>%
  group_by(farm) %>% 
  mutate(volume = cumVol - lag(cumVol, default = 0))

Source: local data frame [8 x 4]
Groups: farm

  period farm cumVol volume
1      1    A     12     12
2      2    A     20      8
3      3    A     40     20
4      4    A     62     22
5      1    B     30     30
6      2    B     34      4
7      3    B     42      8
8      4    B     58     16
于 2014-02-10T01:37:22.403 回答
12

在 dplyr - 所以你不必更换 NA

library(dplyr)
df %>%
 group_by(farm)%>%
 mutate(volume = c(0,diff(cumVol)))


   period farm cumVol other volume
1      1    A      1     1      0
2      2    A      5     2      4
3      3    A     15     3     10
4      4    A     31     4     16
5      1    B     10     5      0
6      2    B     12     6      2
7      3    B     16     7      4
8      4    B     24     8      8
于 2014-02-10T02:12:10.123 回答
3

在原始数据集中创建一个新列是一种选择吗?

这是一个使用data.table操作符的选项:=

require("data.table")
DT <- data.table(df)
DT[, volume := c(0,diff(cumVol)), by="farm"]

或者

diff_2 <- function(x) c(0,diff(x))
DT[, volume := diff_2(cumVol), by="farm"]

输出:

# > DT
#    period farm cumVol other volume
# 1:      1    A      1     1      0
# 2:      2    A      5     2      4
# 3:      3    A     15     3     10
# 4:      4    A     31     4     16
# 5:      1    B     10     5      0
# 6:      2    B     12     6      2
# 7:      3    B     16     7      4
# 8:      4    B     24     8      8
于 2014-02-10T02:51:54.663 回答
3

tapplytransform

> transform(df, volumen=unlist(tapply(cumVol, farm, function(x) c(0, diff(x)))))
   period farm cumVol other volumen
A1      1    A      1     1       0
A2      2    A      5     2       4
A3      3    A     15     3      10
A4      4    A     31     4      16
B1      1    B     10     5       0
B2      2    B     12     6       2
B3      3    B     16     7       4
B4      4    B     24     8       8

ave是更好的选择,见@thelatemail 的评论

with(df, ave(cumVol,farm,FUN=function(x) c(0,diff(x))) )
于 2014-02-10T00:50:30.077 回答