【问题标题】:How to get sum of values every 8 days by date in data frame in R如何在R中的数据框中按日期每8天获取值的总和
【发布时间】:2013-01-07 06:24:51
【问题描述】:

我不需要经常在 R 中处理日期,但我想这相当容易。我有如下几年的每日数据,其中包含一些值,我想在每 8 天期间获取相关值的总和。最好的方法是什么?

您能提供的任何帮助将不胜感激!

 str(temp)
'data.frame':648 obs. of  2 variables:
 $ Date : Factor w/ 648 levels "2001-03-24","2001-03-25",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ conv2: num  -3.93 -6.44 -5.48 -6.09 -7.46 ...

head(temp)
Date              amount
24/03/2001  -3.927020472
25/03/2001  -6.4427004
26/03/2001  -5.477592528
27/03/2001  -6.09462162
28/03/2001  -7.45666902
29/03/2001  -6.731540928
30/03/2001  -6.855206184
31/03/2001  -6.807210228
1/04/2001   -5.40278802

我尝试使用聚合函数,但由于某些原因它不起作用并且聚合方式错误:

z <- aggregate(amount ~ Date, timeSequence(from =as.Date("2001-03-24"),to =as.Date("2001-03-29"), by="day"),data=temp,FUN=sum)

【问题讨论】:

  • 请用户XXXXXX。首先,您在一个数据框上为我们提供 str,其中包含名为“Date”和“conv2”的列,然后显示一个不同的对象。什么给了?

标签: r aggregate time-series


【解决方案1】:

我更喜欢使用包xts 进行此类操作。

  1. 我读取了您的数据,作为动物园对象。查看格式选项的灵活性。

    library(xts)
    ts.dat <- read.zoo(text ='Date              amount
    24/03/2001  -3.927020472
    25/03/2001  -6.4427004
    26/03/2001  -5.477592528
    27/03/2001  -6.09462162
    28/03/2001  -7.45666902
    29/03/2001  -6.731540928
    30/03/2001  -6.855206184
    31/03/2001  -6.807210228
    1/04/2001   -5.40278802',header=TRUE,format = '%d/%m/%Y')
    
  2. 然后我提取给定时期的索引

    ep <- endpoints(ts.dat,'days',k=8)
    
  3. 最后我将我的函数应用于每个索引处的时间序列。

    period.apply(x=ts.dat,ep,FUN=sum )
    2001-03-29 2001-04-01 
    -36.13014  -19.06520 
    

【讨论】:

    【解决方案2】:

    在您的aggregate() 命令中使用cut()

    一些示例数据:

    set.seed(1)
    mydf <- data.frame(
        DATE = seq(as.Date("2000/1/1"), by="day", length.out = 365),
        VALS = runif(365, -5, 5))
    

    现在,聚合。有关详细信息,请参阅?cut.Date。您可以使用cut 指定您希望在每个组中的天数:

    output <- aggregate(VALS ~ cut(DATE, "8 days"), mydf, sum)
    list(head(output), tail(output))
    # [[1]]
    #   cut(DATE, "8 days")      VALS
    # 1          2000-01-01  8.242384
    # 2          2000-01-09 -5.879011
    # 3          2000-01-17  7.910816
    # 4          2000-01-25 -6.592012
    # 5          2000-02-02  2.127678
    # 6          2000-02-10  6.236126
    # 
    # [[2]]
    #    cut(DATE, "8 days")       VALS
    # 41          2000-11-16 17.8199285
    # 42          2000-11-24 -0.3772209
    # 43          2000-12-02  2.4406024
    # 44          2000-12-10 -7.6894484
    # 45          2000-12-18  7.5528077
    # 46          2000-12-26 -3.5631950
    

    【讨论】:

      【解决方案3】:

      滚动应用。 zoo 包有一个滚动应用功能,它也可以进行非滚动聚合。首先使用read.zootemp 数据框转换为动物园,如下所示:

      library(zoo)
      zz <- read.zoo(temp)
      

      然后它只是:

      rollapply(zz, 8, sum, by = 8)
      

      如果您想要滚动总数,请删除 by = 8

      (请注意,您问题中temp 的两个版本不一样。它们具有不同的列标题,并且日期列的格式不同。我在这里假设str(temp) 输出版本。对于@987654328 @ 版本一必须向 read.zoo 添加一个 format = "%d/%m/%Y" 参数。)

      聚合。这是一个不使用任何外部包的解决方案。它基于原始数据框使用aggregate

      ix <- 8 * ((1:nrow(temp) - 1) %/% 8 + 1)
      aggregate(temp[2], list(period = temp[ix, 1]), sum)
      

      请注意,ix 看起来像这样:

      > ix
      [1]  8  8  8  8  8  8  8  8 16
      

      因此它将前 8 行的索引、后 8 行的索引分组,依此类推。

      【讨论】:

        【解决方案4】:

        这些不是日期分类变量。 (没有自尊的程序会显示这样的日期,更不用说这些被标记为因素的事实。)[我后来注意到这些不是同一个对象。]此外,timeSequence 函数(至少在timeDate 包)也不返回 Date 类向量。因此,您期望两个不同的非 Date 对象以合理的方式对齐会有一种“正确的方式”是错误的。具有讽刺意味的是,仅仅使用 temp$Date 列就可以了:

        > z <- aggregate(amount ~ Date, data=temp , FUN=sum)
        > z
                Date    amount
        1  1/04/2001 -5.402788
        2 24/03/2001 -3.927020
        3 25/03/2001 -6.442700
        4 26/03/2001 -5.477593
        5 27/03/2001 -6.094622
        6 28/03/2001 -7.456669
        7 29/03/2001 -6.731541
        8 30/03/2001 -6.855206
        9 31/03/2001 -6.807210
        

        但要每隔 8 天获得它,请使用 cut.Date:

        > z <- aggregate(temp$amount , 
                         list(Dts = cut(as.Date(temp$Date, format="%d/%m/%Y"), 
                         breaks="8 day")), FUN=sum)
        > z
                 Dts          x
        1 2001-03-24 -49.792561
        2 2001-04-01  -5.402788
        

        【讨论】:

          【解决方案5】:

          一种更简洁的方法扩展到@G。格洛腾迪克方法。 注意:不考虑日期是连续还是不连续,总和是根据固定宽度计算的。


          代码

            interval = 8 # your desired date interval. 2 days, 3 days or whatevea 
            enddate = interval-1 # this sets the enddate
            nrows = nrow(z)
            z <- aggregate(.~V1,data = df,sum) # aggregate sum of all duplicate dates
            z$V1 <- as.Date(z$V1)
            data.frame ( Start.date = (z[seq(1, nrows, interval),1]),
                         End.date =  z[seq(1, nrows, interval)+enddate,1],
                         Total.sum = rollapply(z$V2, interval, sum, by = interval, partial = TRUE))
          

          输出

             Start.date   End.date   Total.sum
          1  2000-01-01 2000-01-08   9.1395926
          2  2000-01-09 2000-01-16  15.0343960
          3  2000-01-17 2000-01-24   4.0974712
          4  2000-01-25 2000-02-01   4.1102645
          5  2000-02-02 2000-02-09 -11.5816277
          

          数据

            df <- data.frame(
            V1 = seq(as.Date("2000/1/1"), by="day", length.out = 365),
            V2 = runif(365, -5, 5))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-04
            • 2018-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多