Агрегирование, реструктуризация часовых временных рядов данных в R - PullRequest
6 голосов
/ 26 марта 2012

У меня есть почасовые данные за год в кадре данных в R:

> str(df.MHwind_load)   # compactly displays structure of data frame
'data.frame':   8760 obs. of  6 variables:
 $ Date         : Factor w/ 365 levels "2010-04-01","2010-04-02",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Time..HRs.   : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Hour.of.Year : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Wind.MW      : int  375 492 483 476 486 512 421 396 456 453 ...
 $ MSEDCL.Demand: int  13293 13140 12806 12891 13113 13802 14186 14104 14117 14462 ...
 $ Net.Load     : int  12918 12648 12323 12415 12627 13290 13765 13708 13661 14009 ...

Сохраняя почасовую структуру, я хотел бы знать, как извлечь

  1. определенный месяц / группа месяцев
  2. первый день / первая неделя и т. Д. Каждого месяца
  3. все понедельники, все вторники и т. Д. Года

Я пытался использовать «cut» безрезультатно, и, посмотрев в Интернете, подумал, что «lubridate» мог бы это сделать, но не нашел подходящих примеров. Я был бы очень признателен за помощь в этом вопросе.

Редактировать: образец данных во фрейме данных ниже:

  Date Hour.of.Year  Wind.MW  datetime
1  2010-04-01  1  375  2010-04-01  00:00:00
2  2010-04-01  2  492  2010-04-01  01:00:00
3  2010-04-01  3  483  2010-04-01  02:00:00
4  2010-04-01  4  476  2010-04-01  03:00:00
5  2010-04-01  5  486  2010-04-01  04:00:00
6  2010-04-01  6  512  2010-04-01  05:00:00
7  2010-04-01  7  421  2010-04-01  06:00:00
8  2010-04-01  8  396  2010-04-01  07:00:00
9  2010-04-01  9  456  2010-04-01  08:00:00
10  2010-04-01  10  453  2010-04-01  09:00:00
..  ..  ...  ..........  ........
8758  2011-03-31  8758  302  2011-03-31  21:00:00
8759  2011-03-31  8759  378  2011-03-31  22:00:00
8760  2011-03-31  8760  356  2011-03-31  23:00:00

РЕДАКТИРОВАТЬ: Дополнительные основанные на времени операции, которые я хотел бы выполнить с тем же набором данных 1. Выполните почасовое усреднение для всех точек данных, т. Е. Усредните все значения в первый час каждого дня в году. Результатом будет «почасовой профиль» всего года (24 временных точки) 2. Выполните то же самое для каждой недели и каждого месяца, то есть получите 52 и 12 часовых профилей соответственно 3. Делать сезонные средние, например, с июня по сентябрь

Ответы [ 3 ]

6 голосов
/ 26 марта 2012
  1. Первый переход к представлению Date: as.Date(df.MHwind_load$Date)
  2. Затем вызовите weekdays для вектора даты, чтобы получить новый коэффициент, помеченный днем ​​недели
  3. Затем вызовите months для вектора даты, чтобы получить новый множитель с названием месяца
  4. При необходимости создайте переменную years (см. Ниже).

Теперь subset фрейм данных, используя соответствующую их комбинацию. Шаг 2. получает ответ на вашу задачу 3. Шаги 3. и 4. Приведите вас к задаче 1. Для задачи 2 может потребоваться строка или две из R. Или просто выберите строки, соответствующие, скажем, всем понедельникам в месяце и позвоните unique или его альтер-эго duplicated по результатам.

Чтобы ты пошел ...

newdf <- df.MHwind_load ## build an augmented data set
newdf$d <- as.Date(newdf$Date)
newdf$month <- months(newdf$d)
newdf$day <- weekdays(newdf$d)

## for some reason R has no years function.  Here's one
years <- function(x){ format(as.Date(x), format = "%Y") }

newdf$year <- years(newdf$d)

# get observations from January to March of every year
subset(newdf, month %*% in c('January', 'February', 'March'))

# get all Monday observations
subset(newdf, day == 'Monday')

# get all Mondays in 1999
subset(newdf, day == 'Monday' & year == '1999')

# slightly fancier: _first_ Monday of each month
# get the first weeks
first.week.of.month <- !duplicated(cbind(newdf$month, newdf$day)) 
# now pull out the mondays
subset(newdf, first.monday.of.month & day=='Monday')
6 голосов
/ 26 марта 2012

Преобразуйте дату в формат, понятный lubridate, и затем используйте функции month, mday, wday соответственно.

Предположим, у вас есть data.frame со временем, сохраненным в столбце Date, тогда ответ на ваши вопросы будет:

 ###dummy data.frame
 df <- data.frame(Date=c("2012-01-01","2012-02-15","2012-03-01","2012-04-01"),a=1:4) 
 ##1. Select rows for particular month
 subset(df,month(Date)==1)

 ##2a. Select the first day of each month
 subset(df,mday(Date)==1)

 ##2b. Select the first week of each month
 ##get the week numbers which have the first day of the month
 wkd <- subset(week(df$Date),mday(df$Date)==1)
 ##select the weeks with particular numbers
 subset(df,week(Date) %in% wkd)     

 ##3. Select all mondays 
 subset(df,wday(Date)==1)
3 голосов
/ 26 марта 2012

Поскольку вы не спрашиваете о временной (почасовой) части ваших данных, лучше всего сохранять эти данные как объект Date.В противном случае вас может заинтересовать chron , который также имеет некоторые удобные функции, как вы увидите ниже.

Что касается ответа Conjugate Prior, вы должны сохранить свои данные даты как датуобъект.Поскольку ваши данные уже следуют формату по умолчанию ('гггг-мм-дд'), вы можете просто позвонить как.В противном случае вам придется указать формат строки.Я также хотел бы использовать as.character для вашего фактора, чтобы убедиться, что вы не получите ошибки в строке.Я знаю, что по этой причине у меня возникли проблемы с факторами (возможно, исправлено в текущей версии).

df.MHwind_load <- transform(df.MHwind_load, Date = as.Date(as.character(Date)))

Теперь вы бы неплохо создали функции-обертки, которые извлекают нужную вам информацию.Вы можете использовать transform , как я делал выше, чтобы просто добавить те столбцы, которые представляют месяцы, дни, годы и т. Д., И затем логически поднастроить их.В качестве альтернативы, вы можете сделать что-то вроде этого:

getMonth <- function(x, mo) {  # This function assumes w/in single year vector
  isMonth <- month(x) %in% mo  # Boolean of matching months
  return(x[which(isMonth)]     # Return vector of matching months
}  # end function

Или в краткой форме

getMonth <- function(x, mo) x[month(x) %in% mo]

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

Более сложным процессом является ваша потребность, скажем, в первый день месяца.Это не совсем сложно, хотя.Ниже приведена функция, которая будет возвращать все эти значения, но довольно просто просто установить подмножество отсортированного вектора значений для данного месяца и взять его первый.

getFirstDay <- function(x, mo) {
  isMonth <- months(x) %in% mo
  x <- sort(x[isMonth])  # Look at only those in the desired month.
                         # Sort them by date. We only want the first day.
  nFirsts <- rle(as.numeric(x))$len[1]  # Returns length of 1st days
  return(x[seq(nFirsts)])
}  # end function

Более простой альтернативой будет

getFirstDayOnly <- function(x, mo) {sort(x[months(x) %in% mo])[1]}

Я не создавал прототипы, так как вы не предоставили никаких образцов данных, но это тот тип подхода, который может помочь вам получить желаемую информацию.Это зависит от вас, чтобы выяснить, как включить их в свой рабочий процесс.Например, предположим, что вы хотите получить первый день для каждого месяца данного года (при условии, что мы рассматриваем только один год; вы можете создать обертки или предварительно обработать вектор до одного года).

# Return a vector of first days for each month
df <- transform(df, date = as.Date(as.character(date)))
sapply(unique(months(df$date)),  # Iterate through months in Dates
       function(month) {getFirstDayOnly(df$date, month)})

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...