Разбиение данных по временным интервалам в R

У меня есть некоторые данные наблюдений по часам. Я пытаюсь подмножить эти данные по дневным или даже недельным интервалам. Я не знаю, как выполнить эту задачу в R.

Образец данных ниже.

date                                 obs
2011-10-24 01:00:00                  12
2011-10-24 02:00:00                  4
2011-10-24 19:00:00                  18
2011-10-24 20:00:00                  7
2011-10-24 21:00:00                  4
2011-10-24 22:00:00                  2
2011-10-25 00:00:00                  4
2011-10-25 01:00:00                  2
2011-10-25 02:00:00                  2
2011-10-25 15:00:00                  12
2011-10-25 18:00:00                  2
2011-10-25 19:00:00                  3
2011-10-25 21:00:00                  2
2011-10-25 23:00:00                  9
2011-10-26 00:00:00                  13
2011-10-26 01:00:00                  11

person notrockstar    schedule 06.07.2012    source источник
comment
Можете ли вы привести пример того, что вы пытаетесь сделать? Подмножество дневных или недельных интервалов можно интерпретировать несколькими способами.   -  person Joshua Ulrich    schedule 07.07.2012
comment
Я пытаюсь получить подмножество данных (не совокупность) на основе временных ограничений.   -  person notrockstar    schedule 07.07.2012
comment
Да, я понимаю, что вы пытаетесь получить подмножество, но хотите ли вы подмножество по календарной неделе, неделе с определенного момента времени и т. д.?   -  person Joshua Ulrich    schedule 07.07.2012
comment
Извините, я должен быть более ясным. Мне нужен раздел по календарной неделе.   -  person notrockstar    schedule 07.07.2012


Ответы (2)


Сначала я ввел данные с несколькими пробелами, замененными вкладками.

dat$date <- as.POSIXct(dat$date, format="%Y-%m-%d %H:%M:%S")
split(dat , as.POSIXlt(dat$date)$yday)
# Notice these are not the same functions
#---------------------
$`296`
                 date obs
1 2011-10-24 01:00:00  12
2 2011-10-24 02:00:00   4
3 2011-10-24 19:00:00  18
4 2011-10-24 20:00:00   7
5 2011-10-24 21:00:00   4
6 2011-10-24 22:00:00   2

$`297`
                  date obs
7  2011-10-25 00:00:00   4
8  2011-10-25 01:00:00   2
9  2011-10-25 02:00:00   2
10 2011-10-25 15:00:00  12
11 2011-10-25 18:00:00   2
12 2011-10-25 19:00:00   3
13 2011-10-25 21:00:00   2
14 2011-10-25 23:00:00   9

$`298`
                  date obs
15 2011-10-26 00:00:00  13
16 2011-10-26 01:00:00  11

Класс POSIXlt плохо работает внутри фреймов данных, но может быть очень удобен для создания групп на основе времени. Это структура списка с такими индексами: 'yday', 'wday', 'year', 'mon', 'mday', 'hour', 'min', 'sec' и 'isdt'. Функция cut.POSIXt добавляет деления на другие естественные границы; Например.

?cut.POSIXt
  split(dat , cut(dat$date, "week") )

Если вы хотите суммировать в пределах даты:

tapply(dat$obs, as.POSIXlt(dat$date)$yday, sum)
#-------
296 297 298 
 47  36  24 
person IRTFM    schedule 06.07.2012
comment
Спасибо, @DWin. Как бы вы сделали это еженедельно? - person notrockstar; 07.07.2012
comment
Любые решения для фреймов данных? - person notrockstar; 07.07.2012
comment
На первый вопрос используйте cut(dat$date, breaks=week). Ко второму вопросу....а? .... это кадр данных. - person IRTFM; 07.07.2012
comment
мой второй вопрос касался предложения о том, что POSIX не работает внутри фреймов данных. - person notrockstar; 07.07.2012
comment
Я только советовал не использовать POSIXlt в качестве класса для содержимого фреймов данных. Вы, безусловно, можете использовать от POSIXct до POSIXlt в качестве стратегии вывода. Это действительно то, для чего это нужно. - person IRTFM; 07.07.2012
comment
Спасибо. Я смог разделить его в фрейме данных, как вы посоветовали. Как я могу теперь извлечь каждое подмножество в отдельный фрейм данных? - person notrockstar; 07.07.2012
comment
Вы можете индексировать списки либо по числовой позиции, либо по имени. Трюк с индексацией их по имени заключается в использовании кавычек: «298», а не необработанных чисел. Предполагая, что вы присвоили результат «segdat», эти вызовы дадут одинаковые результаты: segdat[['298']] и segdat[[3]] - person IRTFM; 07.07.2012

Я бы использовал класс временных рядов, такой как xts

dat <- read.table(text="2011-10-24 01:00:00                  12
2011-10-24 02:00:00                  4
2011-10-24 19:00:00                  18
2011-10-24 20:00:00                  7
2011-10-24 21:00:00                  4
2011-10-24 22:00:00                  2
2011-10-25 00:00:00                  4
2011-10-25 01:00:00                  2
2011-10-25 02:00:00                  2
2011-10-25 15:00:00                  12
2011-10-25 18:00:00                  2
2011-10-25 19:00:00                  3
2011-10-25 21:00:00                  2
2011-10-25 23:00:00                  9
2011-10-26 00:00:00                  13
2011-10-26 01:00:00                  11", header=FALSE, stringsAsFactors=FALSE)

xobj <- xts(dat[, 3], as.POSIXct(paste(dat[, 1], dat[, 2])))

Подмножество xts очень интуитивно понятно. Для всех данных на "2011-10-25" сделайте это

xobj["2011-10-25"]
#                    [,1]
#2011-10-25 00:00:00    4
#2011-10-25 01:00:00    2
#2011-10-25 02:00:00    2
#2011-10-25 15:00:00   12
#2011-10-25 18:00:00    2
#2011-10-25 19:00:00    3
#2011-10-25 21:00:00    2
#2011-10-25 23:00:00    9

Вы также можете разделить временные промежутки, подобные этому (все данные между 24.10.2011 и 25.10.2011 включительно).

xobj["2011-10-24/2011-10-25"]

Или, если вам нужны все данные за октябрь 2011 г.,

xobj["2011-10"]

Если вы хотите получить все данные за любой день с 19:00 до 20:00,

xobj['T19:00:00/T20:00:00']
#                    [,1]
#2011-10-24 19:00:00   18
#2011-10-24 20:00:00    7
#2011-10-25 19:00:00    3

Вы можете использовать функцию endpoints, чтобы найти строки, которые являются последними строками периода времени («часы», «дни», «недели» и т. д.).

endpoints(xobj, "days")
[1]  0  6 14 16    

Или вы можете преобразовать в более низкую частоту

to.weekly(xobj)
#           xobj.Open xobj.High xobj.Low xobj.Close
#2011-10-26        12        18        2         11
to.daily(xobj)
#           xobj.Open xobj.High xobj.Low xobj.Close
#2011-10-25        12        18        2          2
#2011-10-26         4        12        2          9
#2011-10-26        13        13       11         11

Обратите внимание, что в приведенном выше примере создаются столбцы для Open, High, Low и Close. Если вам нужны данные только на конечных точках, вы можете использовать OHLC=FALSE

to.daily(xobj, OHLC=FALSE)
#           [,1]
#2011-10-25    2
#2011-10-26    9
#2011-10-26   11

Дополнительные базовые поднастройки и многое другое можно найти на странице http://www.quantmod.com/examples/.

Как упоминает @JoshuaUlrich в комментариях, split.xts НЕВЕРОЯТНО полезен.

Вы можете разделить по дням (или неделям, или месяцам и т. д.), применить функцию, а затем рекомбинировать

split(xobj, 'days') #create a list where each element is the data for a different day
#[[1]]
#                    [,1]
#2011-10-24 01:00:00   12
#2011-10-24 02:00:00    4
#2011-10-24 19:00:00   18
#2011-10-24 20:00:00    7
#2011-10-24 21:00:00    4
#2011-10-24 22:00:00    2
#
#[[2]]
#                    [,1]
#2011-10-25 00:00:00    4
#2011-10-25 01:00:00    2
#2011-10-25 02:00:00    2
#2011-10-25 15:00:00   12
#2011-10-25 18:00:00    2
#2011-10-25 19:00:00    3
#2011-10-25 21:00:00    2
#2011-10-25 23:00:00    9
#
#[[3]]
#                    [,1]
#2011-10-26 00:00:00   13
#2011-10-26 01:00:00   11

Предположим, вам нужно только первое значение каждого дня. split по дням, lapply функция first и rbind обратно вместе.

do.call(rbind, lapply(split(xobj, 'days'), first))
#                    [,1]
#2011-10-24 01:00:00   12
#2011-10-25 00:00:00    4
#2011-10-26 00:00:00   13
person GSee    schedule 06.07.2012
comment
Не забудьте split.xts: split(xobj, "days"). - person Joshua Ulrich; 07.07.2012
comment
@GSee, спасибо! По какой-то причине запуск: xobj <- xts(dat[, 3], as.POSIXct(paste(dat[, 1], dat[, 2]))) выдает ошибку: order.by requires an appropriate time-based object. Любой совет? - person notrockstar; 07.07.2012
comment
Первым аргументом функции xts должны быть данные, а вторым аргументом должен быть индекс времени. Если вы скопируете и вставите весь первый блок кода в мой ответ, он должен работать (и работает для меня), потому что первые 2 столбца — это дата и время, а 3-й столбец — это данные. Виньетки в пакетах zoo и xts помогут вам понять, как превратить ваши данные в xts. Или, если вы предоставите dput ваших данных, я обновлю свой ответ для ваших конкретных данных. - person GSee; 07.07.2012