2012-03-26 1 views
6

Я имею годовую почасовые данные в кадре данных в R:Агрегирования, реструктуризации данных часовых временных рядов в 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. все понедельники, все вторники и т.д. года

Я попытался использовать «разрезать» без результата и после поиска в Интернете подумал, что «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 

EDIT: Дополнительные операции, основанные на время Я хотел бы выполнить на те же набор данных 1. Выполнение час за часом усреднения для всех точек данных, т.е. среднего значения всех значений в первый час каждого дня в году. Выходной сигнал будет «почасовым профилем» всего года (24 момента времени). 2. Выполняйте то же самое для каждой недели и каждого месяца, т.е. получаете 52 и 12 часовых профилей соответственно 3. Сделайте сезонные средние значения, например, за июнь до Сентябрь

+0

Это чисто связанный с программированием R вопрос, без статистического содержания. Мы переносим такие вопросы в stackoverflow, так как здесь у нас больше программистов. – mpiktas

+0

Предлагаю добавить несколько строк вашего data.frame здесь с dput. Я думаю, что достаточно только столбца даты. – mpiktas

+0

@mpiktas: я добавил образец из своего фрейма данных. обратите внимание, что я создал дату и время, используя _timeSequence_ – avg

ответ

6

Конвертировать дату в формат, который понимает 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) 
+0

Все вышеописанное, за исключением # 2b. Я подозреваю, что это может иметь какое-то отношение к моим данным, оно начинается с 1 апреля 2010 года и длится до 31 марта 2011 года - 2 календарных года. – avg

+0

Я запустил команду: wkd <- subset (week (newdf $ datetime), mday (newdf $ datetime) == 1) all.firstweeks.newdf <- subset (newdf, week (datetime)% in% wkd) «datetime» здесь: datetime <- timeSequence (from = "2010-04-01 00:00", to = "2011-03- 31 23:00 ", by =" hour ") вот фрагмент выхода: – avg

+0

вывод: 'all.firstweeks.newdf [1: 240,]' Дата Время..HRs. Hour.of.Year Wind.MW MSEDCL.Demand 1 2010-04-01 1 1 375 13293 2 2010-04-01 2 2 492 13140 3 2010-04-01 3 3 483 12806 . ... ... .. . ... ... .. . ... ... .. 168 2010-04-07 24 168 77 14447 673 2010-04-29 1 673 397 13468 674 2010-04-29 2 674 495 13426 – avg

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

Теперь subset кадр данных с использованием соответствующей их комбинации. Шаг 2. получает ответ на вашу задачу 3. Шаги 3. и 4. поставили задачу 1. Задача 2 может потребовать строку или две из R. Или просто выберите строки, соответствующие, скажем, всем понедельникам в месяц и позвоните по номеру unique или его alter-ego 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') 
+0

Спасибо за результаты. Я смог использовать эти функции, но был зациклен на построении кода для анализа моих данных. Я пытаюсь решить @Bryan Goodrich .. – avg

+0

На самом деле я написал это, я думаю, что мне нравится «lubridate' вещь немного лучше в других ответах. Вспомните код здесь как введение в команду 'subset' :-) – conjugateprior

3

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

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

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

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

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)}) 

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

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

+0

спасибо за подробный ответ, это помогает, так как я не очень владею R. Я сделал то, что вы предложили, со следующим результатом: 'alt. allfirstdays.newdf <- sapply (unique (month (datetime)), function (month) {getFirstDay (datetime, month)}) – avg

+0

Ошибка в Math.data.frame (штук [, 1: 5]): non- числовая переменная в кадре данных: месяц «datetime» здесь: 'datetime <- timeSequence (from = "2010-04-01 00:00", to = "2011-03-31 23:00", by = "hour") ' Что такое «месяц» здесь, функция в _lubridate_ или новая переменная? Я попытался сделать _months (datetime) _ с тем же результатом – avg

+0

Мой подход работает с объектами класса Date, а не lubridate (никогда не использовал его раньше). Точка использования Date - в отличие от, скажем, _chron _-- - заключается в том, что компонент времени не имеет значения. Если ваши данные «2010-04-01», то as.Date («2010-04-01») хранит его правильно. Если вместо этого у вас было «01/04/2010», вам нужно было бы как. Date («01/04/2010», format = «% d /% m /% Y»). Подробности см. На страницах справки. Если ваши данные включают время, вам придется отключить эту часть. Хотя strsplit может работать, он достаточно однородный, чтобы просто подстрока («2010-04-01 00:00», 1, 10) и as.Date. –

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