【发布时间】:2020-04-20 02:40:00
【问题描述】:
我正在开发一个在 R 中监控工人生产力的应用程序。对于每个工人,我都有他们完成的工作,我想看看他们一年中每周完成了多少工作(所以第 1 到 52 周)。问题是某些工人在某些周内没有任何工作记录(例如,工人 1 可能工作了第 1 到 48 周,但不是第 49 到 52 周)。
源数据是每个工作顶部的表格,其中观察是工人,格式如下:
UniqueID Date mapper
10000001 3/3/2015 person1
从这里开始,我将日期分解为年、月、日字段,然后使用lubridate 来获取周数。这适用于每个源数据文件(其中有 10 个)。
然后我按用户和周对每个表进行分组,并计算每个工人完成的工作数量,请参见此处的代码:
library(tidyverse)
library(readxl)
library(rlang)
library(pryr)
library(lubridate)
library(extrafont)
loadfonts(device = "win")
current_week <- week(Sys.Date())
feature_sheets <- excel_sheets("./typesMerged.xlsx")
list_sheets <- lapply(feature_sheets, function(x) read_excel(path = "./typesMerged.xlsx",col_types = c("numeric", "date", "text"), sheet = x))
users = list('person1', 'person2', 'person3', 'person4', 'person5', 'person6')
createTibble <- function(i, yr, wk){
is_missing <- missing(wk)
list_sheets[[i]]%>%
filter(LASTUSER %in% users ) %>%
mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
month = as.numeric(format(DATEMODIFI, format = "%m")),
week = week(DATEMODIFI),
day = as.numeric(format(DATEMODIFI, format = "%d")))%>%
select(-DATEMODIFI) %>%
filter(year == yr) %>%
filter(if(is_missing) TRUE else week == wk)
}
tableNames <- c('dpd', 'fuse', 'ohprimary', 'ohsecondary', 'poles', 'pv', 'switch','transformers', 'ugprimary', 'ugsecondary' )
features <- vector('list', length(tableNames))
for (feature in seq_along(features)){
features[[feature]] <- createTibble(i = feature, yr = 2019)
}
# use for iteratively creating tibbles/df if needed
# for (feature in seq_along(features)){
# assign(features[feature], value = createTibble(feature))
# }
countFeatures <- function(x){
x %>%
group_by(LASTUSER, week) %>%
summarize(n = n())
}
featureCountTibbles <-map(.x = features,.f = countFeatures)
featureCountsByUser <- featureCountTibbles %>% reduce(full_join, by = c("LASTUSER", "week")) %>%
rename(mapper = LASTUSER) %>%
rename(dpd = n.x) %>%
rename(fuse = n.y) %>%
rename(ohprimary = n.x.x) %>%
rename(ohsecondary = n.y.y) %>%
rename(poles = n.x.x.x) %>%
rename(pv = n.y.y.y) %>%
rename(switch = n.x.x.x.x) %>%
rename(transformers = n.y.y.y.y) %>%
rename(ugprimary = n.x.x.x.x.x) %>%
rename(ugsecondary = n.y.y.y.y.y) %>%
replace_na(replace = list(dpd = 0, fuse = 0, ohprimary = 0, ohsecondary = 0, poles = 0, pv = 0, switch = 0, transformers = 0, ugprimary = 0, ugsecondary = 0))
这导致一个看起来像这样的表,这里的问题是 person1 在第 5 周没有工作,所以他没有一行:
mapper week dpd fuse etc.
person1 1 10 50 ...
person1 2 0 50 ...
person1 3 10 0 ...
person1 4 10 50 ...
person1 6 10 50 ...
person2 1 10 50 ...
person2 2 50 50 ...
person2 3 10 0 ...
person2 4 10 50 ...
person2 5 10 50 ***
person2 6 10 50 ...
这就是我希望它在几周没有工作的地方看到的样子:
mapper week dpd fuse etc.
person1 1 10 50 ...
person1 2 0 50 ...
person1 3 10 0 ...
person1 4 10 50 ...
person1 5 0 0 ***
person1 6 10 50 ...
person2 1 10 50 ...
person2 2 50 50 ...
person2 3 10 0 ...
person2 4 10 50 ...
person2 5 10 50 ...
person2 6 10 50 ...
如何才能添加这些空行?这听起来很简单,但我真的想不出在 R 中做这件事的方法(对它来说还是有点新的)。如果这是 SQL,我会在开始时添加一个新字段 week,用 1 - 52 填充它(这将添加我需要的所有行),然后使用我在几周内拥有的实际数据更新表。
已实施的解决方案:
featureCountsByUser <- featureCountTibbles %>% reduce(full_join, by = c("LASTUSER", "week")) %>%
rename(mapper = LASTUSER) %>%
rename(dpd = n.x) %>%
rename(fuse = n.y) %>%
rename(ohprimary = n.x.x) %>%
rename(ohsecondary = n.y.y) %>%
rename(poles = n.x.x.x) %>%
rename(pv = n.y.y.y) %>%
rename(switch = n.x.x.x.x) %>%
rename(transformers = n.y.y.y.y) %>%
rename(ugprimary = n.x.x.x.x.x) %>%
rename(ugsecondary = n.y.y.y.y.y) %>%
ungroup() %>%
complete(mapper,week) %>%
group_by(mapper,week) %>%
replace_na(replace = list(dpd = 0, fuse = 0, ohprimary = 0, ohsecondary = 0, poles = 0, pv = 0, switch = 0, transformers = 0, ugprimary = 0, ugsecondary = 0))
complete() 是答案;但与文档相反,它不尊重我的分组,并且由于我计算完成工作的方式的性质,我无法在原始数据上complete(),所以这是我的工作。谢谢大家!
【问题讨论】:
-
创建一个包含我需要的所有列和空白行的小标题,然后将此脚本的结果输入其中?
-
听起来你可能想要
tidyr::complete()。你可以看到一个使用它的例子here。如果在某个时候进行分组,新的.drop = FALSE功能也可能会有所帮助,在同一链接的另一个答案中显示。