【问题标题】:Loop Output Stored as List循环输出存储为列表
【发布时间】:2021-04-23 22:31:02
【问题描述】:

我有广泛的监督数据,其中单个观察由 1 级员工及其部门一直到 8 级组成。我使用带有其他命令的循环来生成所有员工及其下属部门的长格式列表这样我就可以看到各级员工负责哪些部门。可能有比循环更优雅的方法来做到这一点,但它工作正常。样本数据(为简洁起见,通过 3 级):

data <- tibble(LV1_Employee_Name = "Chuck", LV1_Employee_Nbr = "1", LV1_Department = "Tha Boss", LV1_Department_Nbr = "90",
               LV2_Employee_Name = c("Alex", "Alex", "Paul", "Paul", "Jennifer", "Jennifer"), LV2_Employee_Nbr = c("2", "2", "3", "3", "4", "4"), LV2_Department = c("Leadership", "Leadership", "Finance", "Finance", "Philanthropy", "Philanthropy"), LV2_Department_Nbr = c("91", "91", "92", "92",  "93", "93"),
               LV3_Employee_Name = c("Dan", "Wendy", "Sarah", "Monique", "Miguel", "Brandon"), LV3_Employee_Nbr = c("2", "2", "3", "3", "4", "4"), LV3_Department = c("Analytics", "Pop Health", "Acounting", "Investments", "Yacht Aquisitions", "Golf Junkets"), LV3_Department_Nbr = c("94", "95", "96", "97",  "98", "99"))

下面的循环首先产生六个小标题,分别命名为 level1_1、level1_2、level1_3、level2_2、level2_3、level3_3。每个 tibble 包含员工姓名、编号和同一部门级别或以下的部门。然后代码列出并使用ls()bind_rows() 绑定这些小标题的行,然后应用distinct() 命令,我就得到了我需要的东西。

first_department <- 1

data_colnames <- c("Employee", "Employee_Id", "Department", "Department_Number")

for(i in 1:3){
  for(k in first_department:3){
    
    assign(paste0("level", i, "_", k), setNames(distinct(as_tibble(c(data[ ,paste0("LV", i, "_", "Employee_Name")], data[ ,paste0("LV", i, "_", "Employee_Nbr")],
                                                                     data[ ,paste0("LV", k, "_", "Department")],  data[ ,paste0("LV", k, "_", "Department_Nbr")]))), 
                                                data_colnames))
    
  }
  first_department = first_department + 1
}

employees_departments <- distinct(bind_rows(mget(ls(pattern = "^level")))) %>%
  filter(is.na(Department) == FALSE)

rm(list = ls(pattern = "^level"))

我想做的是,让循环本身输出列表,而不是产生六个小标题的初始输出。这将使我免于在输出中出现大量 tibbles,据我所知,这些 tibbles 不是很“R-like”。

【问题讨论】:

    标签: r list loops


    【解决方案1】:

    这是一个修订版本,它将结果存储在循环中的列表中。这将包括一个索引idx,每次循环都会增加。之后,您可以使用此列表中的bind_rows 来获得完整的结果。

    library(tidyverse)
    
    idx <- 1
    first_department <- 1
    data_colnames <- c("Employee", "Employee_Id", "Department", "Department_Number")
    data_lst <- list()
    
    for(i in 1:3){
      for(k in first_department:3){
        data_lst[[idx]] <- setNames(
          distinct(as_tibble(
            c(data[ ,paste0("LV", i, "_", "Employee_Name")], 
              data[ ,paste0("LV", i, "_", "Employee_Nbr")],
              data[ ,paste0("LV", k, "_", "Department")],  
              data[ ,paste0("LV", k, "_", "Department_Nbr")]))),
          data_colnames)
        idx <- idx + 1
      }
      first_department = first_department + 1
    }
    
    distinct(bind_rows(data_lst)) %>%
      filter(!is.na(Department))
    

    输出

       Employee Employee_Id Department        Department_Number
       <chr>    <chr>       <chr>             <chr>            
     1 Chuck    1           Tha Boss          90               
     2 Chuck    1           Leadership        91               
     3 Chuck    1           Finance           92               
     4 Chuck    1           Philanthropy      93               
     5 Chuck    1           Analytics         94               
     6 Chuck    1           Pop Health        95               
     7 Chuck    1           Acounting         96               
     8 Chuck    1           Investments       97               
     9 Chuck    1           Yacht Aquisitions 98               
    10 Chuck    1           Golf Junkets      99               
    11 Alex     2           Leadership        91               
    12 Paul     3           Finance           92               
    13 Jennifer 4           Philanthropy      93               
    14 Alex     2           Analytics         94               
    15 Alex     2           Pop Health        95               
    16 Paul     3           Acounting         96               
    17 Paul     3           Investments       97               
    18 Jennifer 4           Yacht Aquisitions 98               
    19 Jennifer 4           Golf Junkets      99               
    20 Dan      2           Analytics         94               
    21 Wendy    2           Pop Health        95               
    22 Sarah    3           Acounting         96               
    23 Monique  3           Investments       97               
    24 Miguel   4           Yacht Aquisitions 98               
    25 Brandon  4           Golf Junkets      99 
    

    【讨论】:

    • 有趣的解决方案!不幸的是,完整数据的情况是pivot_longer() 步骤创建了一个包含 35,232 个观测值的小标题。当我继续执行fuzzy_left_join() 步骤时,R 会稍微处理命令,然后输出“错误:无法分配大小为 2.6Gb 的向量”我很好奇pivot_longer() 命令在做什么;它如何选择级别编号,知道将此编号放入名为“级别”的新列中,然后为生成的列提供通用名称。当我最初开始这个问题时,我认为我不能使用枢轴。
    • pivot_longer“加长”数据(增加行数,减少列数)...看看data_long 的样子,您会看到每一行包括: (1) 行编号(因为同一行表示与其他部门的关系),(2)级别,(3)员工姓名和ID,以及(4)部门和部门编号。原始数据每行有 3 个名称和 3 个部门,而长版本只有一个名称和部门。每一行。
    • pivot_longer 采用 names_pattern ,它使用正则表达式(正则表达式)来定义键/值应该是什么......在这种情况下,它将数字 \\d+ 分隔在一列中,这是级别,另一个列中的单词\\w+是4个(Employee_Name,Employee_Nbr,Department,Department_Nbr)之一。这是通过解释原始列名来确定的...
    • 请查看编辑版本。我添加了一个类似的方法,但是根据原始数据框的行数进行小连接。这应该给出相同的答案,但更适用于更大的数据。请让我知道这是否有效。如果您的数据量很大,还可以考虑使用data.table 解决方案和非等连接。
    • 数据是 32 个变量(8 个级别)的 4,404 个 obs。 4,613 名员工和 281 个部门。我以前用过pivot_longer,但从来没有使用过使用正则表达式的模式选项,所以很高兴看到它在起作用。在正则表达式中, () 中的值是否表示要拆分为列的值?对这是否可以在没有循环的情况下完成感兴趣,尽管循环确实处理得很快 - 只是我无法将它作为列表输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-28
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多