Даты и дни недели не соответствуют вашему набору данных, поэтому сначала я создам несколько игрушечных дат и значений:
set.seed(123)
df <- data.frame(date = as.Date("2018-10-26") - 14:0,
val = sample(1:4, 15, replace = TRUE))
Создать будни:
df$day <- format(df$date, "%a")
Получить индексы суббот и воскресений:
ix <- df$day %in% c("Sat", "Sun")
Добавьте 2 к датам, соответствующим субботам, и 1 к «датам воскресенья»:
df$date[ix] <- df$date[ix] + (7 - as.integer(format(df$date[ix], "%u")) + 1)
Изменить день недели для субботы и воскресенья на понедельник
df$day[ix] <- "Mon"
Используйте by
для вычисления среднего значения «val» по дате. Результатом by
является список, поэтому нам нужно связать элементы списка по строке (do.call(rbind...
).
do.call(rbind,
by(df, df$date, function(x){
data.frame(date = x$date[1], day = x$day[1], val = mean(x$val))
}))
# date day val
# 2018-10-12 2018-10-12 Fri 4.000000
# 2018-10-15 2018-10-15 Mon 1.333333
# 2018-10-16 2018-10-16 Tue 4.000000
# 2018-10-17 2018-10-17 Wed 4.000000
# 2018-10-18 2018-10-18 Thu 3.000000
# 2018-10-19 2018-10-19 Fri 3.000000
# 2018-10-22 2018-10-22 Mon 3.333333
# 2018-10-23 2018-10-23 Tue 3.000000
# 2018-10-24 2018-10-24 Wed 3.000000
# 2018-10-25 2018-10-25 Thu 2.000000
# 2018-10-26 2018-10-26 Fri 1.000000
Чуть более компактно, используя data.table
:
library(data.table)
# convert data frame to data.table
d <- as.data.table(df)
# or setDT(df)
# create weekday
d[ , day := format(date, "%a")]
# update dates and days for Saturdays and Sundays
d[day %in% c("Sat", "Sun"), `:=`(
date = date + (7 - as.integer(format(date, "%u")) + 1),
day = "Mon")]
# For each date, select first weekday and calculate mean 'val'
d[ , .(day = day[1], val = mean(val)), by = date]
# date day val
# 1: 2018-10-12 Fri 4.000000
# 2: 2018-10-15 Mon 1.333333
# 3: 2018-10-16 Tue 4.000000
# 4: 2018-10-17 Wed 4.000000
# 5: 2018-10-18 Thu 3.000000
# 6: 2018-10-19 Fri 3.000000
# 7: 2018-10-22 Mon 3.333333
# 8: 2018-10-23 Tue 3.000000
# 9: 2018-10-24 Wed 3.000000
# 10: 2018-10-25 Thu 2.000000
# 11: 2018-10-26 Fri 1.000000