Заполните пропущенный год в упорядоченном списке дат

Я собрал некоторые данные временных рядов из Интернета, и временная метка, которую я получил, выглядит так, как показано ниже.

24 Jun 
21 Mar
20 Jan 
10 Dec
20 Jun 
20 Jan
10 Dec 
...

Интересно то, что в данных отсутствует год, однако все записи упорядочены, и вы можете вывести год из записи и заполнить недостающие данные. Таким образом, данные после вменения должны быть такими:

24 Jun 2014
21 Mar 2014
20 Jan 2014
10 Dec 2013 
20 Jun 2013
20 Jan 2013
10 Dec 2012
...

Прежде чем засунуть рукава и начать писать цикл for с логикой nested... есть ли простой способ, который может работать в R "из коробки" для вменения пропущенного года.

Большое спасибо за любое предложение!


person B.Mr.W.    schedule 02.09.2014    source источник


Ответы (2)


Вот одна идея

## Make data easily reproducible
df <- data.frame(day=c(24, 21, 20, 10, 20, 20, 10),
                 month = c("Jun", "Mar", "Jan", "Dec", "Jun", "Jan", "Dec"))


## Convert each month-day combo to its corresponding "julian date"
datestring <- paste("2012", match(df[[2]], month.abb), df[[1]], sep = "-")
date <- strptime(datestring, format = "%Y-%m-%d") 
julian <- as.integer(strftime(date, format = "%j"))

## Transitions between years occur wherever julian date increases between
## two observations
df$year <- 2014 - cumsum(diff(c(julian[1], julian))>0)

## Check that it worked
df
#   day month year
# 1  24   Jun 2014
# 2  21   Mar 2014
# 3  20   Jan 2014
# 4  10   Dec 2013
# 5  20   Jun 2013
# 6  20   Jan 2013
# 7  10   Dec 2012
person Josh O'Brien    schedule 02.09.2014
comment
если за один день нет повторяющихся записей... возможно, можно изменить cumsum(diff(c(julian[1], julian))>0) на большее или равное нулю. В любом случае, большое спасибо за вашу помощь. - person B.Mr.W.; 03.09.2014
comment
Вы можете пропустить шаги datestring и date и сразу перейти к julian с помощью julian <- julian(ISOdate(2012, match(df[[2]], month.abb), df[[1]])). Все остальное должно работать так же. - person MrFlick; 03.09.2014
comment
@MrFlick - спасибо за эти замечательные предложения. - person Josh O'Brien; 03.09.2014

ОП просил заполнить годы в убывающем порядке, начиная с 2014 года.

Вот альтернативный подход, который работает без преобразования даты и поддельных дат. Кроме того, этот подход можно изменить для работы с финансовыми годами, которые начинаются не в январе, а в другом месяце.

# create sample dataset
df <- data.frame(
  day = c(24L, 21L, 20L, 10L, 20L, 20L, 21L, 10L, 30L, 10L, 10L, 7L),
  month = c("Jun", "Mar", "Jan", "Dec", "Jun", "Jan", "Jan", "Dec", "Jan", 
            "Jan", "Jan", "Jun"))

df$year <- 2014 - cumsum(c(0L, diff(100L*as.integer(
  factor(df$month, levels = month.abb)) + df$day) > 0))
df
   day month year
1   24   Jun 2014
2   21   Mar 2014
3   20   Jan 2014
4   10   Dec 2013
5   20   Jun 2013
6   20   Jan 2013
7   21   Jan 2012
8   10   Dec 2011
9   30   Jan 2011
10  10   Jan 2011
11  10   Jan 2011
12   7   Jun 2010

Завершение финансового года

Предположим, компания решила начать свой финансовый год 1 февраля. Таким образом, январь приходится на другой финансовый год, чем февраль или март того же календарного года.

Чтобы обрабатывать финансовые годы, нам нужно только соответствующим образом перетасовать уровни факторов:

df$fy <- 2014 - cumsum(c(0L, diff(100L*as.integer(
  factor(df$month, levels = month.abb[c(2:12, 1)])) + df$day) > 0))
df
   day month year   fy
1   24   Jun 2014 2014
2   21   Mar 2014 2014
3   20   Jan 2014 2013
4   10   Dec 2013 2013
5   20   Jun 2013 2013
6   20   Jan 2013 2012
7   21   Jan 2012 2011
8   10   Dec 2011 2011
9   30   Jan 2011 2010
10  10   Jan 2011 2010
11  10   Jan 2011 2010
12   7   Jun 2010 2010
person Uwe    schedule 22.01.2018