【问题标题】:R: Simplifying For Loops -- Goat Farms in New ZealandR:简化 For 循环——新西兰的山羊农场
【发布时间】:2018-03-14 18:30:32
【问题描述】:

我正在处理相当大的数据集,其中我使用一个 for 循环来调用函数,其中函数有 2 个嵌套的 for 循环。它非常慢,我需要看看是否有一种使用向量的方法,而不是循环观察和变量。我的第一个数据集包含 10,000 多条新西兰境内山羊销售和转让的记录。我的“主要”数据集包含每个农场中每种山羊的季度数据。即,有 300 种山羊和约 15,000 个农场。这个“主要”数据框被保存为面板数据框。鉴于农场收购 - 我需要将购买农场的山羊数据添加到购买农场数据中。这是我之前使用的程序的结构:

goat_full_takeover<-function(farm1,farm2,takeover_date){
for(loop over dates(i)){
for(loop over goat types(j)){
   farm[farm(1)date(i)goat(j)] = farm[farm(1)date(i)goat(j)] + 
                                 farm[farm(2)date(i)goat(j)]
   farm[farm(2)date(i)goat(j)] = NA
}
}
}

goat_partial_takeover<-function(farm1,farm2,takeover_date){
for(loop over dates(i) up to takeover_date){
for(loop over goat types(j)){
   goat_scale = #goats[takeover_date + 1] / #goats[takeover_date] 

   farm[farm(1)date(i)goat(j)] = farm[farm(1)date(i)goat(j)] + goat_scale *
                                  (farm[farm(2)date(i)goat(j)])
   farm[farm(2)date(i)goat(j)] = (1-goat_scale)*farm[farm(2)date(i)goat(j)]
}
}
}

for(every goat farm purchased){
if(takeover == type1){
  goat_full_takeover
}
if(takeover == type2){
  goat_partial_takeover
}
}

所以我循环了超过 10,000 只山羊的销售,然后我循环了 300 种山羊的多达 100 个季度日期。有没有办法可以以不同的方式格式化它,以便我只需要循环购买?理想情况下,我可以从函数中删除嵌套的 for 循环,以便该函数仅将 farm2 的值堆叠在 farm1 上

       goat1   goat2   goat3
farm1 Q1     5       5       5 
farm1 Q2     6       6       6
farm1 Q3     7       7       7 
farm1 Q4     8       8       8 
farm2 Q1     9       9       9 
farm2 Q2    10      10       10
farm2 Q3    11      11       11  
farm2 Q4    12      12       12

农场 1 购买农场 2 >>

      goat1   goat2   goat3
farm1 Q1     14      14      14 
farm1 Q2     16      16      16
farm1 Q3     18      18      18 
farm1 Q4     20      20      20 
farm2 Q1     na      na      na
farm2 Q2     na      na      na
farm2 Q3     na      na      na  
farm2 Q4     na      na      na

我的问题纯粹是想出一种更快的方法来做到这一点。目前,由于山羊的数量,这需要将近一周的时间才能运行。我需要找到一种简化的方法来解决这个问题,以便我可以将它用于新西兰以外的其他国家。提前感谢您的任何帮助,非常感谢。如果有什么不清楚的,请告诉我!

【问题讨论】:

  • 您可能希望给出一个可重现的示例:stackoverflow.com/questions/5963269/… 如果没有具体的供人们测试的东西,就很难评估性能。现在,您的示例看起来都是伪代码,如何将其扩展到大 n 并不明显。
  • aggregate(.~farm+quarter,transform(dat,farm=sub("farm2","farm1",farm)),sum) 其中farm 是第一列,quarter 是第二列
  • 有趣的问题,我有一些想法,但没有可编译的代码和示例数据,我们只能叹息继续前进。

标签: r performance for-loop


【解决方案1】:
dat=read.table(text=" farm quarter     goat1   goat2   goat3
farm1 Q1     5       5       5 
               farm1 Q2     6       6       6
               farm1 Q3     7       7       7 
               farm1 Q4     8       8       8 
               farm2 Q1     9       9       9 
               farm2 Q2    10      10       10
               farm2 Q3    11      11       11  
               farm2 Q4    12      12       12
               farm3 Q1    13     13       13
               farm3 Q2    13     13       13
               farm3 Q3    13     13       13
               farm3 Q4    13     13       13

               ",stringsAsFactors=F,h=T)


takeover=function(dat,buyer,seller){
   pattern=paste(seller,collapse="|")
   A=aggregate(.~farm+quarter,dat[grepl(pattern,dat$farm),],`is.na<-`)
   x=rbind(transform(dat,farm=sub(pattern,buyer,farm)),A)
   aggregate(.~quarter+farm,x,sum,na.action = function(x)x)
 }
takeover(dat,"farm2","farm1")#farm2 takes over farm1
   quarter  farm goat1 goat2 goat3
1       Q1 farm1    NA    NA    NA
2       Q2 farm1    NA    NA    NA
3       Q3 farm1    NA    NA    NA
4       Q4 farm1    NA    NA    NA
5       Q1 farm2    14    14    14
6       Q2 farm2    16    16    16
7       Q3 farm2    18    18    18
8       Q4 farm2    20    20    20
9       Q1 farm3    13    13    13
10      Q2 farm3    13    13    13
11      Q3 farm3    13    13    13
12      Q4 farm3    13    13    13

takeover(dat,"farm1","farm3")#farm1 takes over farm3
   quarter  farm goat1 goat2 goat3
1       Q1 farm1    18    18    18
2       Q2 farm1    19    19    19
3       Q3 farm1    20    20    20
4       Q4 farm1    21    21    21
5       Q1 farm2     9     9     9
6       Q2 farm2    10    10    10
7       Q3 farm2    11    11    11
8       Q4 farm2    12    12    12
9       Q1 farm3    NA    NA    NA
10      Q2 farm3    NA    NA    NA
11      Q3 farm3    NA    NA    NA
12      Q4 farm3    NA    NA    NA

takeover(dat,"farm3",c("farm2","farm1"))#farm3 takes over farm1 and farm2. The order doesnt matter
   quarter  farm goat1 goat2 goat3
1       Q1 farm1    NA    NA    NA
2       Q2 farm1    NA    NA    NA
3       Q3 farm1    NA    NA    NA
4       Q4 farm1    NA    NA    NA
5       Q1 farm2    NA    NA    NA
6       Q2 farm2    NA    NA    NA
7       Q3 farm2    NA    NA    NA
8       Q4 farm2    NA    NA    NA
9       Q1 farm3    27    27    27
10      Q2 farm3    29    29    29
11      Q3 farm3    31    31    31
12      Q4 farm3    33    33    33

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2016-03-06
    • 1970-01-01
    相关资源
    最近更新 更多