如何通过聚合行在数据框中创建新列?

时间:2017-08-17 23:36:30

标签: r dataframe aggregate

我有一个大的(~20万行)数据帧,其结构如下:

df <-
 data.frame(c(1,1,1,1,1), c('blue','blue','blue','blue','blue'), c('m','m','m','m','m'), c(2016,2016,2016,2016,2016),c(3,4,5,6,7), c(10,20,30,40,50))

colnames(df) <- c('id', 'color', 'size', 'year', 'week','revenue')

假设现在是第7周,我想比较过去4周的收入平均值和本周的收入。我想要做的是在所有标识符匹配时为该平均值创建一个新列。

df_new <-
 data.frame(1, 'blue', 'm', 2016,7,50, 25 )

colnames(df_new) <- c('id', 'color', 'size', 'year', 'week','revenue', 't4ave')

如何有效地完成这项工作?谢谢你的帮助

2 个答案:

答案 0 :(得分:0)

好的问题。 for循环是非常低效的,但是因为你必须检查先前条目的条件,这是我能想到的唯一解决方案(请注意,我也是R的中间人):

for (i in 1:nrow(df))
{
    # condition for all entries to match up
    if ((i > 5) && (df$id[i] == df$id[i-1] == df$id[i-2] == df$id[i-3] == df$id[i-4])
    && (df$color[i] == df$color[i-1] == df$color[i-2] == df$color[i-3] == df$color[i-4])
    && (df$size[i] == df$size[i-1] == df$size[i-2] == df$size[i-3] == df$size[i-4])
    && (df$year[i] == df$year[i-1] == df$year[i-2] == df$year[i-3] == df$year[i-4])
    && (df$week[i] == df$week[i-1] == df$week[i-2] == df$week[i-3] == df$week[i-4]))

    # avg of last 4 entries' revenues
    avg <- mean(df$revenue[i-1] + df$revenue[i-2] + df$revenue[i-3] + df$revenue[i-4])

    # create new variable of difference between this entry and last 4's
    df$diff <- df$revenue[i] - avg
}

这段代码可能会永远存在,但它应该可行。如果这是代码需要运行的一次性事情,那么它应该没问题。否则,希望其他人能够提供建议。

答案 1 :(得分:0)

使用dplyrzoo的解决方案。我们的想法是对相同的变量进行分组,例如idcolorsizeyear。在此之后,使用rollmean来计算收入的滚动均值。使用na.pad = TRUEalign = "right"确保计算涵盖最近几周。最后,使用lag来转换&#34;转移&#34;计算结果符合您的需求。

library(dplyr)
library(zoo)

df2 <- df %>%
  group_by(id, color, size, year) %>%
  mutate(t4ave = rollmean(revenue, 4, na.pad = TRUE, align = "right")) %>%
  mutate(t4ave = lag(t4ave))
df2
# A tibble: 5 x 7
# Groups:   id, color, size, year [1]
     id  color   size  year  week revenue t4ave
  <dbl> <fctr> <fctr> <dbl> <dbl>   <dbl> <dbl>
1     1   blue      m  2016     3      10    NA
2     1   blue      m  2016     4      20    NA
3     1   blue      m  2016     5      30    NA
4     1   blue      m  2016     6      40    NA
5     1   blue      m  2016     7      50    25