Конвертировать ежедневные данные в недельные данные в R - PullRequest
0 голосов
/ 01 марта 2020

У меня ежедневно данные за 7 лет. Я хочу сгруппировать это в еженедельные данные (основанные на фактической дате) и суммировать частоту.

Date Frequency
1   2014-01-01  179
2   2014-01-02  82  
3   2014-01-03  89  
4   2014-01-04  109 
5   2014-01-05  90  
6   2014-01-06  66  
7   2014-01-07  75  
8   2014-01-08  106 
9   2014-01-09  89  
10  2014-01-10  82

Каков наилучший способ достичь этого? Спасибо

Ответы [ 5 ]

5 голосов
/ 01 марта 2020

Все эти решения используют базу R и отличаются только определением и маркировкой недель.

1) cut даты в неделях и затем агрегируются по ним. Недели начинаются в понедельник, но вы можете добавить start.on.monday=FALSE к cut, чтобы начать их в воскресенье, если хотите.

Week <- as.Date(cut(DF$Date, "week"))
aggregate(Frequency ~ Week, DF, sum)
##         Week Frequency
## 1 2013-12-30       549
## 2 2014-01-06       418

2) Если вы предпочитаете определить неделю как 7 дни, начинающиеся с DF $ Date [1], и пометьте их в соответствии с первой датой на этой неделе, затем используйте это. (Добавьте 6 к Week, если предпочитаете последнюю дату недели.)

weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[1] + 7 * weekno
aggregate(Frequency ~ Week, DF, sum)
##         Week Frequency
## 1 2014-01-01       690
## 2 2014-01-08       277

3) или если вы предпочитаете пометить ее первой датой, существующей в DF на этой неделе используйте это. Это и последнее определение недели дают тот же результат, если нет пропущенных дат, как здесь. (Если вам нужна последняя существующая дата недели, а не первая, замените match на findInterval.)

weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[match(weekno, weekno)]
aggregate(Frequency ~ Week, DF, sum)
##         Week Frequency
## 1 2014-01-01       690
## 2 2014-01-08       277

Примечание

Предполагается, что ввод в воспроизводимой форме быть:

Lines <- "Date Frequency
1 2014-01-01 179
2 2014-01-02 82 
3 2014-01-03 89 
4 2014-01-04 109 
5 2014-01-05 90 
6 2014-01-06 66 
7 2014-01-07 75 
8 2014-01-08 106 
9 2014-01-09 89 
10 2014-01-10 82"
DF <- read.table(text = Lines)
DF$Date <- as.Date(DF$Date)
2 голосов
/ 01 марта 2020

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

data.table делает эту работу следующим образом:

library(data.table)
setDT(myDF) # convert to data.table

myDF[ , .(weekly_freq = sum(Frequency)), by = isoweek(Date)]
0 голосов
/ 02 марта 2020

Новый пакет slider от RStudio решает эту проблему напрямую, включая указание начала еженедельных периодов. Предположим, что еженедельные периоды должны были начаться в понедельник, поэтому начало первой недели будет Monday, 2013-12-30. Тогда решение для слайдера будет

library(slider)   
slide_period_dfr(.x = DF, .i=as.Date(DF$Date), 
                 .period = "week", 
                 .f = ~data.frame(week_ending = tail(.x$Date,1),
                                   week_freq = sum(.x$Frequency)),
                 .origin = as.Date("2013-12-30"))

с результатом

 week_ending week_freq
1  2014-01-05       549
2  2014-01-10       418
0 голосов
/ 01 марта 2020

Может быть, вы можете попробовать базовый код R с aggregate + format, то есть

dfout <- aggregate(Frequency ~ yearweek,within(df,yearweek <- format(Date,"%Y,%W")),sum)

таким, что

> dfout
  yearweek Frequency
1  2014,00       549
2  2014,01       418

ДАННЫЕ

df <- structure(list(Date = structure(c(16071, 16072, 16073, 16074, 
16075, 16076, 16077, 16078, 16079, 16080), class = "Date"), Frequency = c(179L, 
82L, 89L, 109L, 90L, 66L, 75L, 106L, 89L, 82L)), row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")
0 голосов
/ 01 марта 2020

Я бы использовал library(lubridate).

df <- read.table(header = TRUE,text = "date Frequency
2014-01-01  179
2014-01-02  82  
2014-01-03  89  
2014-01-04  109 
2014-01-05  90  
2014-01-06  66  
2014-01-07  75  
2014-01-08  106 
2014-01-09  89  
2014-01-10  82")

Вы можете использовать базу R или library(dplyr):

база R: чтобы убедиться, что дата действительно является датой:

df$date <- ymd(df$date)
df$week <- week(df$date)

или короткий:

df$week <- week(ymd(df$date))

или dplyr:

library(dplyr)
df %>% 
  mutate(week = week(ymd(date))) %>% 
  group_by(week)
...