首页 > 解决方案 > 我怎样才能编写这个工作代码来提高性能?

问题描述

我从一个更大的数据集(25K 记录)中设置了这个样本。我注意到我的应用程序的代码在这块上变慢了,我想检查性能改进。

背景:我的财政年度从七月开始,到六月结束。因此,我的记录有一个不同于一个月和一个日历年的财务期间和财务年度。我想添加指示日历年和月的额外列。

FinancialPeriod-FinancialYear : 01 2018 is 7 2017 (Jul 2017),
FinancialPeriod-FinancialYear : 07 2018 is 1 2018 (Jan 2018), etc..

可重现的例子:

dt<-data.table(FinancialPeriod =c(3,4,4,5,1,2,8,8,11,12,2,3,10,1,6), FinancialYear=c(2018), Amount=c(12,14,16,18,12))
dt$Month<-dt$FinancialPeriod + 6
dt$Year<-dt$FinancialYear
t1<-proc.time()
for(row in 1:nrow(dt)){
  if (dt[row,"Month"] > 12){
    dt[row,"Month"]<- dt[row,"Month"] -12
  } 
  else {
    dt[row,"Year"]<- dt[row,"Year"] -1
  }
}
proc.time()-t1
dt

上面的代码有效,但运行缓慢。我想就如何改进提出建议。

标签: rperformancefor-loopdata.tablecoding-efficiency

解决方案


我的建议是使用完整的日期,例如,财务期的开始。所以,我们可以使用 aFinancialDate而不是FinancialPeriod-FinancialYear组合,例如,OP 的例子

FinancialPeriod-FinancialYear : 01 2018

变成

财务日期:2018-01-01

这种方法有几个好处:

  1. 只有一个日期对象来描述周期,而不是两个更易于处理的对象,例如用于聚合。如果需要,可以从日期对象中轻松提取月份和年份。
  2. 我们可以利用通常的日期算术(例如lubridate包的)将 a 转换FinancialDate为 a CalendarDate
  3. 此外,对于日期对象,绘图效果更好。

这是代码:

library(lubridate)
dt[, FinDate := make_date(FinancialYear, FinancialPeriod)]
dt[, CalDate := FinDate %m+% months(6)]   # convert to calendar date by adding offset
dt[, c("CalMonth", "CalYear") := list(month(CalDate), year(CalDate))]
dt
    FinancialPeriod FinancialYear Amount Month Year    FinDate    CalDate CalMonth CalYear
 1:               3          2018     12     9 2018 2018-03-01 2018-09-01        9    2018
 2:               4          2018     14    10 2018 2018-04-01 2018-10-01       10    2018
 3:               4          2018     16    10 2018 2018-04-01 2018-10-01       10    2018
 4:               5          2018     18    11 2018 2018-05-01 2018-11-01       11    2018
 5:               1          2018     12     7 2018 2018-01-01 2018-07-01        7    2018
 6:               2          2018     12     8 2018 2018-02-01 2018-08-01        8    2018
 7:               8          2018     14    14 2018 2018-08-01 2019-02-01        2    2019
 8:               8          2018     16    14 2018 2018-08-01 2019-02-01        2    2019
 9:              11          2018     18    17 2018 2018-11-01 2019-05-01        5    2019
10:              12          2018     12    18 2018 2018-12-01 2019-06-01        6    2019
11:               2          2018     12     8 2018 2018-02-01 2018-08-01        8    2018
12:               3          2018     14     9 2018 2018-03-01 2018-09-01        9    2018
13:              10          2018     16    16 2018 2018-10-01 2019-04-01        4    2019
14:               1          2018     18     7 2018 2018-01-01 2018-07-01        7    2018
15:               6          2018     12    12 2018 2018-06-01 2018-12-01       12    2018

推荐阅读