【问题标题】:Split and Diff function in RR中的Split和Diff函数
【发布时间】:2013-11-08 21:29:50
【问题描述】:

我有一个名为 data 的数据框。我正在使用名为 KEY 的属性使用 split 函数拆分数据。

data <- split(data, data$KEY);   

通过 KEY 拆分数据框后,我们得到的是各个公司的数据。数据框数据包含宇宙中所有公司的数据。拆分后,每个单独的拆分都有两列,年份和销售额。对于每个拆分,我必须计算每年对应的增量销售额。例如,如果我们有 2002 - 10、2003 - 12、2004 - 15、2005 - 20 的数据。我有兴趣获得的数据是 2003-2、2004 -3、2005 - 5,对于每个拆分。 我编写了一个名为 mod_sale 的函数来执行上述工作:

data[with(data, order(year)),];
sale_data <- diff(data$SALE);
data <- data[-1,];
data$SALE <- sale_data;
return(data)

目前,我正在使用 for 循环:

for(key in names(data)){
a <- try(mod_sale(data[[key]]))
if(class(a) == "try-error") next;
mod_data <- rbind(mod_data,a)};

我认为有某种方法,我可以使用 sapply(也可能是 plyr)。有人可以帮我改进这个 R 代码吗?不知道 sapply 代码会怎样。

sapply(data, mod_sale)

任何帮助将不胜感激。谢谢。

编辑:

这是一个数据示例:

a <- data.frame();
key <- c(1,1,1,1,2,2,2,2,2,3,3,3);
sales <- c(12,12,15,8,3,6,3,9,9,12,3,7);
year <- c(2002,2003,2004,2005,2001,2002,2003,2004,2005,2003,2004,2005);
ovar <- runif(12,5.0,7.5);
a <- data.frame(key,sales,year,ovar)

在生成的 data.frame 中,我期望的是增量销售而不是实际销售。显然,我们会为 3 个 key 丢失 3 个数据点;每个起始年一个,因为我们正在考虑差异。因此,结果 data.frame 中将少三行,其中包含 key、diff(sales)、year 和 ovar 列。

【问题讨论】:

  • 如果您不提供最低限度的工作示例(包括数据),将很难为您提供帮助。
  • 代码改进类型的东西在我们可以看到的可重现示例中效果更好
  • 这是对您前两个问题的改进,但仍然很难提供帮助,因为我们没有 data 可以单独使用。

标签: r


【解决方案1】:

这就是我会做的:

a$diffsales <- ave( a$sales, a$key, FUN=function(x) c(NA, diff(x) ) )
a
   key sales year     ovar diffsales
1    1    12 2002 6.845177        NA
2    1    12 2003 6.328153         0
3    1    15 2004 6.872669         3
4    1     8 2005 6.098920        -7
5    2     3 2001 7.154824        NA
6    2     6 2002 6.110810         3
7    2     3 2003 5.906624        -3
8    2     9 2004 5.214369         6
9    2     9 2005 5.818218         0
10   3    12 2003 5.354354        NA
11   3     3 2004 6.728992        -9
12   3     7 2005 7.412213         4

【讨论】:

    【解决方案2】:

    感谢您尝试展示您的尝试。谢谢。

    以后尽量提供一个小例子,像这样:

    df <- data.frame(year = 2001:2010,
                     sale = sample(20,10))
    
    df <- rbind(df,df,df)
    df$key <- rep(letters[1:3],each = 10)
    

    这使您的数据看起来更清晰,并且让试图回答的人非常轻松。您为我们做的越简单,您得到的答案就越快+更好。

    我建议在拆分前进行排序:

    #Sort first (already sorted, but you get the idea)
    df <- df[order(df$key,df$year),]
    df_split <- split(df,df$key)
    

    您实际上并不想使用sapply。 (试试看。)你只需要lapply

    out <- lapply(df_split,function(x) {x$sale_diff <- c(NA,diff(x$sale)); x[-1,]})
    

    你会再次使用:

    do.call(rbind,out)
    

    你说得对,plyrdata.table 也可以这样做。我会把这些例子留给其他人。

    【讨论】:

      【解决方案3】:

      使用data.table:

      library(data.table)
      dt = data.table(a)
      
      dt[, sale_diff := c(NA, diff(sales)), by = key]
      dt
      #    key sales year     ovar sale_diff
      # 1:   1    12 2002 7.416857        NA
      # 2:   1    12 2003 5.625818         0
      # 3:   1    15 2004 5.018934         3
      # 4:   1     8 2005 6.671986        -7
      # 5:   2     3 2001 6.242739        NA
      # 6:   2     6 2002 6.297763         3
      # 7:   2     3 2003 6.482124        -3
      # 8:   2     9 2004 6.724256         6
      # 9:   2     9 2005 5.071265         0
      #10:   3    12 2003 6.136681        NA
      #11:   3     3 2004 6.974392        -9
      #12:   3     7 2005 6.517553         4
      

      【讨论】: