0

我有一个包含一些日期字段的大约 200,000 行的 data.frame。我需要在数据框中添加一个新列,该列将具有与给定日期对应的会计年度值。一个财政年度跨越 2 年的部分时间。就我而言,是四月到三月。2010 年 3 月 1 日的日期将属于 2009-10 财年,而 2010 年 7 月 1 日将属于 2010-11 财年。我编写了一个标量函数来进行这种转换。以下是这些函数的代码:

convMonthYearToFY = function(m, y){
  yn = y+1
  yp = y-1

  if (m < 4){
    fy = sprintf("%d-%02d", yp, y%%100)
  } else {
    fy = sprintf("%d-%02d", y, yn%%100)
  }
  return(fy)
}

convDateToFY = function(dt){
  y = 1900+as.POSIXlt(dt)$year
  m = 1+as.POSIXlt(dt)$mon
  return(convMonthYearToFY(m, y))
}

我正在使用 ddply/transform 创建新列

new_df = ddply(df, 1, transform, fy=convDateToFY(somedate))

我看到以下行为。由于 df 有 200,000 行,因此非常慢。其次它会发出以下警告消息

38: In if (m < 4) { ... :
  the condition has length > 1 and only the first element will be used
39: In if (m < 4) { ... :
  the condition has length > 1 and only the first element will be used
40: In if (m < 4) { ... :
  the condition has length > 1 and only the first element will be used
41: In if (m < 4) { ... :
  the condition has length > 1 and only the first element will be used

我尝试使用 mutate ,它也给了我很多如上所述的警告信息。这些警告很烦人,因为我看不出哪里出了问题。

在没有任何警告的情况下,我可以实现这种转变的最好和最快的方法是什么?对于示例数据,下面是两行的数据框以及 ddply 和 mutate 的行为:

df = data.frame(somedate = as.Date(c("2010-01-01", "2010-07-01"), "%Y-%m-%d"))

> ddply(df, 1, transform, fy=convDateToFY(somedate))
    somedate      fy
1 2010-01-01 2009-10
2 2010-07-01 2010-11

这里的输出是正确的...

mutate(df, fy=convDateToFY(somedate)) somedate fy 1 2010-01-01 2009-10 2 2010-07-01 2009-10 警告消息:在 if (m < 4) { :条件的长度 > 1 和只使用第一个元素

在变异的情况下,输出是错误的。

简而言之,我试图在 ddply/transform 和 mutate 中使用用户定义的函数来处理大型数据集,但没有成功。请帮忙。

问候

ķ

4

1 回答 1

0

未测试

mydata$yn<- mydata$y+1
mydata$yp<- mydata$y-1
mydata$fy<-with(mydata,ifelse (m < 4), sprintf("%d-%02d", yp, y%%100),sprintf("%d-%02d", y, yn%%100))
于 2013-08-31T17:36:12.347 回答