преобразование данных тепловой карты покрытия временного блока - PullRequest
0 голосов
/ 15 июня 2019

Я пытаюсь создать тепловую карту, используя очень странную структуру данных.

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

times<-sort(format(seq.POSIXt(as.POSIXct(Sys.Date()),as.POSIXct(Sys.Date()+1),by = "5 min"),"%H%M"))
set.seed(922)
sample.data<-as.data.frame(matrix(NA,nrow = 2000,ncol = 10))
names(sample.data)<-c("INDEX","DAY1","START1","END1","DAY2","START2","END2","DAY3","START3","END3")
for(i in 1:nrow(sample.data)){
  sample.data[i,"INDEX"]<-sample(1:100,1,replace = T)
  sample.data[i,"DAY1"]<-sample(c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"),1,replace = F)
  sample.data[i,"START1"]<-sample(times,1,replace = T)
  sample.data[i,"END1"]<-sample(times,1,replace = T)
  sample.data[i,"DAY2"]<-sample(c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"),1,replace = F)
  sample.data[i,"START2"]<-sample(times,1,replace = T)
  sample.data[i,"END2"]<-sample(times,1,replace = T)
  sample.data[i,"DAY3"]<-sample(c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"),1,replace = F)
  sample.data[i,"START3"]<-sample(times,1,replace = T)
  sample.data[i,"END3"]<-sample(times,1,replace = T)
}

data<-sample.data%>%
  filter(START1<END1 & START2<END2 & START3<END3 & DAY1!=DAY2 & DAY1!=DAY3 & DAY2!=DAY3)

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

Я хочу создать тепловую карту со временем дня, разбитым на 5 минутсегменты по оси Y, а дни недели по оси X.Нужно ли собирать столбцы и группировать по 5 минутных кусков?Я понятия не имею.

Если бы данные были в правильной структуре, я мог бы сгруппировать по дням недели и разным 5-минутным фрагментам, и подсчитать каждый ряд, где в аэропорту была единица наблюдения.Я просто не знаю, как заставить dplyr сказать, что есть человек, работающий без явного вызова, и я не знаю, как это сделать без цикла for.Если мне нужно объяснить, что я делаю лучше, или если у вас есть какие-либо блестящие идеи о том, как получить мои данные в правильной форме, или если я даже думаю об этом правильно, дайте мне знать.Я бился головой о стол, и мне нужно на минуту отойти от проблемы, но если это поможет, должна появиться тепловая карта, если вы выполните следующий код графика:

ggplot(data, aes(x = DAY, y = TIME_CHUNK))+
geom_tile(aes(fill = TOTAL_EMPLOYEES))+
geom_text(aes(label = TOTAL_EMPLOYEES), colour = "white",size = 3)

Спасибо за ваше время ...

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Я думаю, что это должно сделать

clean_colnames <- function(col_inds) {
  data %>% select(INDEX, day = col_inds[1], start = col_inds[2], end = col_inds[3])
}

bind_rows(clean_colnames(2:4), clean_colnames(5:7), clean_colnames(8:10))  %>% 
  gather(key = start_end, value = time, -INDEX, -day) %>% 
  mutate(time = paste0("20190101 ", time) %>% lubridate::ymd_hm()) %>% 
  padr::pad(group = c("INDEX", "day")) %>% 
  count(day, time) %>% 
  mutate(time = paste0(substr(time, 12, 13), substr(time, 15, 16)))
0 голосов
/ 15 июня 2019

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

Сначала я переформирую данные, используя следующую технику: https://stackoverflow.com/a/56605646/6851825

DAY <- grep("DAY", names(data))
START_END <- grep("START|END", names(data))
data_long <- cbind(stack(data, select = DAY), stack(data, select = START_END))
names(data_long) <- c("WEEKDAY", "DAYNUM", "TIME", "STATUS")

Здесь я сделаюеще немного изменить порядок, чтобы упорядочить рабочие дни и преобразовать ВРЕМЯ в десятичное число, а также отследить совокупное число в

library(tidyverse)
data_long_count <- data_long %>%
mutate(WEEKDAY = factor(WEEKDAY, levels = c("Sunday", "Monday", "Tuesday", 
                          "Wednesday", "Thursday", "Friday", "Saturday")),
       TIME_dec = as.numeric(TIME %>% str_sub(end = 2)) +
         as.numeric(TIME %>% str_sub(start = 3))/60,
       STATUS = STATUS %>% str_remove("[0-9]"),
       count_chg = if_else(STATUS == "START", 1, -1)) %>%
arrange(WEEKDAY, TIME_dec) %>%
mutate(employee_count = cumsum(count_chg)) 

[Отсутствует шаг: заполните все минуты без изменений.Для этого собирался использовать пакет padr, но он предпочитает иметь datetime или date.Или может использовать geom_rect, чтобы обойти это.]

Без любой из них, эта тепловая карта является "пятнистой", потому что она имеет полосы, где происходят изменения, а не все минуты между.

ggplot(data_long_count, aes(WEEKDAY, TIME_dec, fill = employee_count)) + geom_tile()
...