【问题标题】:Add in "empty" rows when joining tables加入表格时添加“空”行
【发布时间】: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 功能也可能会有所帮助,在同一链接的另一个答案中显示。

标签: r dplyr tidyr


【解决方案1】:

使用您发布的非您想要的结果数据:

library(tidyverse)
x <- c("Worker  Week  dpd  fuse ", 
  "person1  1    10    5   ",
  "person1  2     0    5   ",
  "person1  3    10        ",
  "person1  4    10    5   ",
  "person1  6    10    5   ",
  "person2  1    10    5   ",
  "person2  2    50    5   ",
  "person2  3    10        ",
  "person2  4    10    5   ",
  "person2  5    10    5   ",
  "person2  6    10    5   ") %>%
  read_table()


x %>% complete(Worker, Week)

应该给:

# A tibble: 12 x 4
   Worker   Week   dpd  fuse
   <chr>   <dbl> <dbl> <dbl>
 1 person1     1    10     5
 2 person1     2     0     5
 3 person1     3    10    NA
 4 person1     4    10     5
 5 person1     5    NA    NA
 6 person1     6    10     5
 7 person2     1    10     5
 8 person2     2    50     5
 9 person2     3    10    NA
10 person2     4    10     5
11 person2     5    10     5
12 person2     6    10     5

complete() 有填写缺失数据的选项,@aosmith 提供的以上参考链接。用 0 填充 NA 应该不是问题。

【讨论】:

  • 谢谢,我无法让它完全按照您的概述工作,但它引导我找到了解决方案(请参阅原始帖子中的更新)。无论出于何种原因,complete 不尊重我的 group_by() 并且我无法在原始数据上应用 complete(),因为已完成作业的计数取决于原始数据的原样(即,如果我添加不存在的周数)会让他们看起来像是完成了工作,而实际上他们没有完成工作)。
猜你喜欢
  • 2014-04-17
  • 2018-01-07
  • 1970-01-01
  • 2014-04-30
  • 2017-01-30
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多