2010-10-05 3 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. Во-вторых, я хотел бы вычислить количество месяцев между двумя столбцами.

Update:

По существу я пытаюсь воссоздать то, что я делаю в SPSS, в R.

В SPSS я бы:

  1. Преобразование строки в формат даты DD-MMM -YYYY
  2. COMPUTE. RND ((a-b) /60/60/24/30.416)

30.416 не подходит для 365/12. Меня не волнует о крайних случаях месяца, следовательно, операция округления.

+1

Правильный ответ на этот вопрос будет полностью зависеть от того, как вы определяете «разницу в один месяц». Это 30 дней? Переходит ли он с одного месяца на другой, независимо от количества дней между двумя датами? Что-то другое? –

+0

30.416, как правило, используется в SPSS. –

+0

Вы хотите настоящее количество месяцев между датами? – hadley

ответ

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 (как было подчеркнуто Dirk) (с использованием вышеуказанного df)

+2

OK, случайные пропущенные голоса от людей, не выходя из комментариев, начинаются с этого сайта. По крайней мере, порядочность сказать, что не так с комментарием, поэтому у нас есть шанс учиться. –

+0

Я не вижу ничего плохого в этом ответе. Можно добавить, что количество месяцев может быть рассчитано как m $ year * 12 + m $ month. ;-) –

+0

+1 От меня, безусловно, нет нисходящего. –

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

зоопарк выглядит как чистый выход И вход. Я должен проверить это. –

+0

@Brandon: да, класс 'yearmon' зоопарка очень удобен, если вы просто работаете с месячными данными. Обратите внимание, что вам не нужно сначала конвертировать в 'Date', чтобы использовать' yearmon' (например, на вашем исходном data.frame: 'Data [, 1] <- as.yearmon (данные [, 1],"% d- % b-% Y ")'). –

+0

Да, «зоопарк» замечательный. Но будьте уверены, что под капотом он использует базовые типы R для * упорядоченного индекса *. Все это возвращается к пониманию 'POSIXct' и др. - если вы не переключитесь на нечто вроде lubridate. –

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

Brandon,

Вы можете сделать это с пакетом lubridate.

> library(lubridate) 

Сообщите, что это даты. Используйте функцию парсера dmy(), потому что даты записываются в день, месяц, год (т. Е. 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.

Смежные вопросы