【问题标题】:How can I avoid having to loop through and search through this data frame?我怎样才能避免遍历和搜索这个数据框?
【发布时间】:2014-08-04 23:32:42
【问题描述】:

我有一个 100 万行的数据框,其中包含 2003-2010 年各个账户的每月用水量数据 (HCF):

> head(LeakyAccts)
      ACCOUNT     Date HCF
1    10114488 Oct 2010  25
2    10114488 Sep 2007  24
3    10114488 Nov 2006  11
4    10114488 Jun 2008  18
5    10114488 Aug 2003   6
6    10114488 Jan 2008  30

日期为yearmon。我想知道每个帐户与上一年同月相比每个月使用了多少。所以对于每一行,我想找出那个月的使用量(Date)和上一年同月的使用量(Date - 1)之间的差异。换句话说,我想要这个:

for(i in 1:nrow(LeakyAccts)) {
  row <- which((LeakyAccts$ACCOUNT == LeakyAccts[i,]$UB_ACCT_NBR) & (LeakyAccts$Date == (LeakyAccts[i,]$Date - 1)))

  if (length(row) == 1) {   # no previous year for 2003
     LeakyAccts[i,]$Difference <- LeakyAccts[i,]$HCF - LeakyAccts[row,]$HCF
  }
}

不用说,这个循环需要几个小时才能运行,而且看起来非常不像 R。如何避免使用丑陋的 for 循环并加快计算速度?有没有办法使用apply 函数或data.table 来做到这一点?

【问题讨论】:

    标签: r loops search dataframe


    【解决方案1】:

    我已经稍微重新配置了您的数据以给出一个完整的示例:

    library(zoo)
    dat <- structure(list(ACCOUNT = c(10114488L, 10114488L, 10114488L, 20114488L, 20114488L, 20114488L), ate = structure(c(2010.75, 2009.75, 2008.75, 2008, 2007, 2006), class = "yearmon"), HCF = c(25L, 24L, 11L, 18L, 6L, 30L)), .Names = c("ACCOUNT", "Date", "HCF"), row.names = c("1", "2", "3", "4", "5", "6"), class = "data.frame")
    

    看起来像:

       ACCOUNT     Date HCF
    1 10114488 Oct 2010  25
    2 10114488 Oct 2009  24
    3 10114488 Oct 2008  11
    4 20114488 Jan 2008  18
    5 20114488 Jan 2007   6
    6 20114488 Jan 2006  30
    

    由于yearmon 本质上只是一个numeric 值,其中1 的差异是一年的差异,因此您可以获得一年前的匹配差异,例如:

    dat$HCF - dat$HCF[match(dat$Date-1,dat$Date)]
    #[1]   1  13  NA  12 -24  NA
    

    ...您也可以在每个组中应用,例如:

    do.call(c,by(dat,dat$ACCOUNT,function(x) x$HCF - x$HCF[match(x$Date-1,x$Date)]))
    #101144881 101144882 101144883 201144881 201144882 201144883 
    #        1        13        NA        12       -24        NA 
    

    或使用data.table 喜欢:

    library(data.table)
    dat <- as.data.table(dat)
    dat[, Difference := HCF - HCF[match(Date-1,Date)], by=ACCOUNT]
    dat
    
    #    ACCOUNT     Date HCF Difference
    #1: 10114488 Oct 2010  25          1
    #2: 10114488 Oct 2009  24         13
    #3: 10114488 Oct 2008  11         NA
    #4: 20114488 Jan 2008  18         12
    #5: 20114488 Jan 2007   6        -24
    #6: 20114488 Jan 2006  30         NA
    

    【讨论】:

    • 谢谢!将match 与数据表一起使用似乎是一种非常优雅的方式。
    猜你喜欢
    • 2022-08-13
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多