【问题标题】:Using one data frame to sum a range of data from another data frame in R使用一个数据帧对来自 R 中另一个数据帧的一系列数据求和
【发布时间】:2013-03-25 21:03:11
【问题描述】:

我正在从 SAS 迁移到 R。我需要帮助来弄清楚如何汇总日期范围内的天气数据。在 SAS 中,我采用日期范围,使用数据步骤为范围内的每个日期(startdateenddatedate)创建记录,与天气合并然后汇总(VAR hdd cdd; CLASS =startdate enddate sum=) 对日期范围的值求和。

R 代码:

startdate <- c(100,103,107)
enddate <- c(105,104,110)
billperiods <-data.frame(startdate,enddate);

得到:

> billperiods
startdate enddate
1       100     105
2       103     104
3       107     110

R 代码:

weatherdate <- c(100:103,105:110)
hdd <- c(0,0,4,5,0,0,3,1,9,0)
cdd <- c(4,1,0,0,5,6,0,0,0,10)
weather <- data.frame(weatherdate,hdd,cdd)

得到:

> weather
   weatherdate hdd cdd
1          100   0   4
2          101   0   1
3          102   4   0
4          103   5   0
5          105   0   5
6          106   0   6
7          107   3   0
8          108   1   0
9          109   9   0
10         110   0  10

注意:weatherdate = 104 丢失。我可能一天都没有天气。

我不知道怎么去:

> billweather
  startdate enddate sumhdd sumcdd
1       100     105      9     10
2       103     104      5      0
3       107     110     13     10

其中sumhddhdd 在天气data.frame 中从startdateenddate 的总和。

有什么想法吗?

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    这是使用IRangesdata.table 的方法。看起来,对于这个问题,这个答案似乎有点矫枉过正。但总的来说,我发现使用IRanges 处理区间很方便,它们可能多么简单。

    # load packages
    require(IRanges)
    require(data.table)
    
    # convert data.frames to data.tables
    dt1 <- data.table(billperiods)
    dt2 <- data.table(weather)
    
    # construct Ranges to get overlaps
    ir1 <- IRanges(dt1$startdate, dt1$enddate)
    ir2 <- IRanges(dt2$weatherdate, width=1) # start = end
    
    # find Overlaps
    olaps <- findOverlaps(ir1, ir2)
    
    # Hits of length 10
    # queryLength: 3
    # subjectLength: 10
    #    queryHits subjectHits 
    #     <integer>   <integer> 
    #  1          1           1 
    #  2          1           2 
    #  3          1           3 
    #  4          1           4 
    #  5          1           5 
    #  6          2           4 
    #  7          3           7 
    #  8          3           8 
    #  9          3           9 
    #  10         3          10 
    
    # get billweather (final output)
    billweather <- cbind(dt1[queryHits(olaps)], 
                    dt2[subjectHits(olaps), 
                    list(hdd, cdd)])[, list(sumhdd = sum(hdd), 
                    sumcdd = sum(cdd)), 
                    by=list(startdate, enddate)]
    
    #    startdate enddate sumhdd sumcdd
    # 1:       100     105      9     10
    # 2:       103     104      5      0
    # 3:       107     110     13     10
    

    最后一行的代码分解: 首先我使用queryHitssubjectHitscbind 构造一个中间的data.table,然后我按startdate, enddate 分组并得到hddcdd 的总和。如下图所示,单独查看该行更容易理解。

    # split for easier understanding
    billweather <- cbind(dt1[queryHits(olaps)], 
                dt2[subjectHits(olaps), 
                list(hdd, cdd)])
    billweather <- billweather[, list(sumhdd = sum(hdd), 
                sumcdd = sum(cdd)), 
                by=list(startdate, enddate)]
    

    【讨论】:

      【解决方案2】:
       cbind(billperiods, t(sapply(apply(billperiods, 1, function(x) 
           weather[weather$weatherdate >= x[1] & 
                   weather$weatherdate <= x[2], c("hdd", "cdd")]), colSums)))
      
        startdate enddate hdd cdd
      1       100     105   9  10
      2       103     104   5   0
      3       107     110  13  10
      

      【讨论】:

      • 感谢您的快速回复!我对更大的数据框(12,356 行)进行了尝试,耗时 6.75 秒,结果很好!
      【解决方案3】:
      billweather <- cbind(billperiods, 
                       t(apply(billperiods, 1, function(x) { 
                         colSums(weather[weather[, 1] %in% c(x[1]:x[2]), 2:3])
                     })))
      

      【讨论】:

      • 感谢您的快速回复!我对更大的数据框(12,356 行)进行了尝试,耗时 7.89 秒,结果很好!我很惊讶人们的反应如此之快。这是我第一次在这里提问。
      猜你喜欢
      • 2021-12-25
      • 2019-04-02
      • 1970-01-01
      • 2013-06-14
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多