Совокупный диапазон дней недели (вычисление среднего значения) и присвоение результата определенному дню недели. - PullRequest
0 голосов
/ 26 октября 2018

У меня есть data.frame, который содержит даты, дни недели и некоторые значения.Вот типичное подмножество моих данных:

Date          Weekday     Value
01/01/2010    Friday      0.5
01/03/2010    Sunday      0.4
01/04/2010    Monday      0.2
01/05/2010    Tuesday     0.6
01/06/2010    Wednesday   0.7
01/07/2010    Thursday    0.6
01/08/2010    Friday      0.6
01/09/2018    Saturday    0.2
01/10/2018    Sunday      0.7
01/11/2018    Monday      0.3
01/12/2018    Tuesday     0.5
01/13/2018    Wednesday   0.4

Я хочу свернуть строки для определенных диапазонов будних дней - последовательных суббот, воскресений и понедельников.То есть я хочу рассчитать среднее значение для каждого набора сб-вс-понедельник.Затем результат должен быть назначен на «строку понедельника», которая следует за каждыми выходными.

Желаемый результат:

Date          Weekday     Value
01/01/2010    Friday      0.5
01/04/2010    Monday      0.3 # <- mean Value Sun-Mon Jan 3-4      
01/05/2010    Tuesday     0.6
01/06/2010    Wednesday   0.7
01/07/2010    Thursday    0.6
01/08/2010    Friday      0.6
01/11/2018    Monday      0.4 # <- mean Value Sat-Mon Jan 9-11 
01/12/2018    Tuesday     0.5
01/13/2018    Wednesday   0.4

Я пытался сделать это с помощью присоединения и затем повторного поднабора, ноЯ всегда получаю среднее значение за все по субботам, воскресеньям и понедельникам.Это также портит мою структуру данных.

Спасибо за любые полезные советы или решения.Я очень ценю это!

Ответы [ 3 ]

0 голосов
/ 26 октября 2018

Пример данных (в зависимости от того, что вы предоставили)

# example dataset
df = read.table(text = "
Date          Weekday     Value
01/01/2010    Monday      0.5
01/02/2010    Tuesday     0.3
01/03/2010    Wednesday   0.2
01/04/2010    Thursday    0.6
01/05/2010    Friday      0.7
01/06/2010    Saturday    0.9
01/07/2010    Sunday      0.7
01/08/2010    Monday      0.2
01/01/2018    Monday      0.6
01/02/2018    Tuesday     0.2
01/03/2018    Wednesday   0.7
01/04/2018    Thursday    0.3
01/05/2018    Friday      0.5
01/06/2018    Saturday    0.3
01/07/2018    Sunday      0.8
01/08/2018    Monday      0.1
", header=T, stringsAsFactors=F)

Решение (с использованием dplyr)

library(dplyr)

# specify days of interest
days_of_interest = c("Saturday","Sunday","Monday")

df %>%
  group_by(Weekday) %>%                                 # for each day               
  mutate(Value = ifelse(Weekday %in% days_of_interest,  # if that day is one of the days of interest
                        mean(Value),                    # use the mean value of those days
                        Value)) %>%                     # otherwise keep the initial value
  ungroup()                                             # forget the grouping

Выход

# # A tibble: 16 x 3
#   Date       Weekday   Value
#   <chr>      <chr>     <dbl>
# 1 01/01/2010 Monday     0.35
# 2 01/02/2010 Tuesday    0.3 
# 3 01/03/2010 Wednesday  0.2 
# 4 01/04/2010 Thursday   0.6 
# 5 01/05/2010 Friday     0.7 
# 6 01/06/2010 Saturday   0.6 
# 7 01/07/2010 Sunday     0.75
# 8 01/08/2010 Monday     0.35
# 9 01/01/2018 Monday     0.35
#10 01/02/2018 Tuesday    0.2 
#11 01/03/2018 Wednesday  0.7 
#12 01/04/2018 Thursday   0.3 
#13 01/05/2018 Friday     0.5 
#14 01/06/2018 Saturday   0.6 
#15 01/07/2018 Sunday     0.75
#16 01/08/2018 Monday     0.35
0 голосов
/ 26 октября 2018

Даты и дни недели не соответствуют вашему набору данных, поэтому сначала я создам несколько игрушечных дат и значений:

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
0 голосов
/ 26 октября 2018

Я думаю, это зависит от того, как выглядят ваши фактические данные, вот моя попытка.

data = read.table(text = "Date          Weekday     Value
                          01/01/2010    Monday      0.5
                          01/02/2010    Tuesday     0.3
                          01/03/2010    Wednesday   0.2
                          01/04/2010    Thursday    0.6
                          01/05/2010    Friday      0.7
                          01/06/2010    Saturday    0.9
                          01/07/2010    Sunday      0.7
                          01/08/2010    Monday      0.2
                          01/02/2010    Tuesday     0.3
                          01/03/2010    Wednesday   0.2
                          01/04/2010    Thursday    0.6
                          01/05/2010    Friday      0.7
                          01/06/2010    Saturday    0.9
                          01/07/2010    Sunday      0.7
                          01/01/2018    Monday      0.6
                          01/02/2018    Tuesday     0.2
                          01/03/2018    Wednesday   0.7
                          01/04/2018    Thursday    0.3
                          01/05/2018    Friday      0.5
                          01/06/2018    Saturday    0.3
                          01/07/2018    Sunday      0.8
                          01/01/2010    Monday      0.5", header = T)
# find where the saturdays are
sat_row = which(data$Weekday == "Saturday")
# get the mean of sat - mon
new_mean = sapply(sat_row, function(index) mean(data[index:(index + 2),]$Value))
# remove saturday and sunday
data2 = subset(data, !(Weekday == "Sunday" | Weekday == "Saturday"))
# put new mean in
data2[which(data2$Weekday == "Monday"),][-1,]$Value = new_mean

Вероятно, требуется некоторая настройка в зависимости от набора данных.

...