2010-10-05 122 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的下一個版本。