2010-10-05 58 views
2

我有一个因式分解的时间序列,看起来像这样:计算月

df <- data.frame(a=c("11-JUL-2004", "11-JUL-2005", "11-JUL-2006", 
        "11-JUL-2007", "11-JUL-2008"), 
       b=c("11-JUN-1999", "11-JUN-2000", "11-JUN-2001", 
        "11-JUN-2002", "11-JUN-2003")) 

首先,我想将其转换为一种格式,原产于R.其次,我想计算两列之间的月数。

更新:

基本上我试图重新我做什么在SPSS,在R.

在SPSS我想:

  1. 转换字符串到日期格式DD-MMM -YYYY
  2. COMPUTE。 RND((a-b)/60/60/24/30.416)

30.416是365/12的简称我不太关心月边缘情况,因此舍入操作。

+1

这个问题的正确答案将完全取决于你如何定义“一个月的差异”。这是30天吗?它是否从一个月到另一个月过渡,无论这两个日期之间有多少天?还有别的吗? – 2010-10-05 17:44:02

+0

30.416一般是我在SPSS中使用的。 – 2010-10-05 17:55:18

+0

你想要日期之间的实际月数? – hadley 2010-10-05 18:41:34

回答

4
df <- data.frame(c("11-JUL-2004","11-JUL-2005","11-JUL-2006","11-JUL-2007","11-JUL-2008"), 
       c("11-JUN-1999","11-JUN-2000","11-JUN-2001","11-JUN-2002","11-JUN-2003")) 
names(df) <- c("X1","X2") 
df <- within(df, X1 <- as.Date(X1, format = "%d-%b-%Y")) 
df <- within(df, X2 <- as.Date(X2, format = "%d-%b-%Y")) 

然后difftime()将给予周的区别:

> with(df, difftime(X1, X2, units = "weeks")) 
Time differences in weeks 
[1] 265.2857 265.1429 265.1429 265.1429 265.2857 

或者,如果我们使用布兰登的近似值:

> with(df, difftime(X1, X2)/30.416) 
Time differences in days 
[1] 61.05339 61.02052 61.02052 61.02052 61.05339 

最近我可以lubridate得到(由为突出德克)是(使用上面的df

> m <- with(df, as.period(subtract_dates(X1, X2))) 
> m 
[1] 5 years and 1 month 5 years and 1 month 5 years and 1 month 5 years and 1 month 5 years and 1 month 
> str(m) 
Classes ‘period’ and 'data.frame': 5 obs. of 6 variables: 
$ year : int 5 5 5 5 5 
$ month : int 1 1 1 1 1 
$ day : num 0 0 0 0 0 
$ hour : int 0 0 0 0 0 
$ minute: int 0 0 0 0 0 
$ second: num 0 0 0 0 0 
+2

好吧,随意驾驶的人们在没有留下评论的情况下反复投票,正在开始与本网站联系。至少有正派的态度来评论评论的错误,所以我们有机会学习。 – 2010-10-05 19:26:24

+0

我为一个人看到这个答案没有错。你可以补充说,月数可以计算为m $ year * 12 + m $ month。 ;-) – 2010-10-05 22:33:22

+0

+1从我,绝对没有downvote。 – 2010-10-05 23:01:26

2
> Data <- data.frame(
+ V1=c("11-JUL-2004","11-JUL-2005","11-JUL-2006","11-JUL-2007","11-JUL-2008"), 
+ V2=c("11-JUN-1999","11-JUN-2000","11-JUN-2001","11-JUN-2002","11-JUN-2003")) 
> Data[,1] <- as.Date(Data[,1],"%d-%b-%Y") 
> Data[,2] <- as.Date(Data[,2],"%d-%b-%Y") 
> # Assuming 30 days per month 
> (Data[,1]-Data[,2])/30 
Time differences in days 
[1] 61.90000 61.86667 61.86667 61.86667 61.90000 
> # Assuming 30.416 days per month 
> (Data[,1]-Data[,2])/30.416 
Time differences in days 
[1] 61.05339 61.02052 61.02052 61.02052 61.05339 
> # Assuming month crosses 
> require(zoo) 
> Data[,1] <- as.yearmon(Data[,1]) 
> Data[,2] <- as.yearmon(Data[,2]) 
> (Data[,1]-Data[,2])*12 
[1] 61 61 61 61 61 
+0

动物园看起来更干净的输出和输入。我必须检查一个。 – 2010-10-05 18:04:43

+0

@Brandon:是的,如果你只是处理月度数据,动物园的'yearmon'类非常方便。请注意,您不需要首先将'Date'转换为'yearmon'(例如,在您的初始data.frame上:'Data [,1] < - as.yearmon(Data [,1],“%d- %B-%Y“)')。 – 2010-10-05 18:10:01

+0

是的,'动物园'真是太棒了。但请放心,在引擎盖下它使用基本的R类型作为* ordered索引*。这一切都回到理解'POSIXct'等 - 除非你切换到像lubridate。 – 2010-10-05 18:35:53

3

乔希通过点上就什么难度一个月可能意味着。 lubridate包有一些答案。

在基础R方面,我们虽然可以回答这个问题了几个星期:

> df[,"pa"] <- as.POSIXct(strptime(as.character(df$a), 
+       format="%d-%B-%Y", tz="GMT")) 
> df[,"pb"] <- as.POSIXct(strptime(as.character(df$b), 
+       format="%d-%B-%Y",tz="GMT")) 
> df[,"weeks"] <- difftime(df$pa, df$pb, unit="weeks") 
> df[,"months"] <- difftime(df$pa, df$pb, unit="days")/30.416 
> df 
      a   b   pa   pb  weeks  months 
1 11-JUL-2004 11-JUN-1999 2004-07-11 1999-06-11 265.29 weeks 61.053 days 
2 11-JUL-2005 11-JUN-2000 2005-07-11 2000-06-11 265.14 weeks 61.021 days 
3 11-JUL-2006 11-JUN-2001 2006-07-11 2001-06-11 265.14 weeks 61.021 days 
4 11-JUL-2007 11-JUN-2002 2007-07-11 2002-06-11 265.14 weeks 61.021 days 
5 11-JUL-2008 11-JUN-2003 2008-07-11 2003-06-11 265.29 weeks 61.053 days 
> 

这将使用改变data.frame按我的编辑,使我们有正确的列名。如果你投掷as.numeric()difftime()你也可以得到数字。

2

下面的数字1似乎最接近你要求的,但2和3是你可能想要根据你的目的考虑的选择。如果您想考虑几个月的小数,也可以尝试不舍入数字1和3。

# first convert columns of df to "Date" class 
df[] <- lapply(df, as.Date, "%d-%b-%Y") 

# 1. difference in days divided by 365.25/12 
with(df, round((as.numeric(a) - as.numeric(b))/(365.25/12))) 

# 2. convert to 1st of month & then take diff in mos 
library(zoo) 
with(df, 12 * (as.yearmon(a) - as.yearmon(b))) 

# 3. business style difference in months. See: ?"mondate-class" 
library(mondate) 
with(df, round(as.numeric(mondate(a) - mondate(b)))) 
3

布兰登,

您可以与lubridate包做到这一点。

> library(lubridate) 

通知R这些是日期。使用dmy()解析器函数是因为日期被写为Day,Month,Year(即,dmy)。

> df <- transform(df, a = dmy(a), b = dmy(b)) 

计算差异为一个周期。这会给你全年,月,日等的数量。

> diff <- as.period(df$a - df$b) 

使用数学将结果转换为几个月。

> 12* diff$year + diff$month 

这些都是相隔61个月。这会将它铺设到最近的月份。如果你想圆基于天数,你可以做这样的事情

> 12* diff$year + diff$month + round(diff$day/30) 

我在努力使这些步骤更容易/更直观的lubridate的下一个版本。