【问题标题】:how to transform marginal data (reporting line data) using R如何使用 R 转换边际数据(报告线数据)
【发布时间】:2021-03-30 06:28:51
【问题描述】:

我有以下数据:

Name Line Manager
A1 B1
A2 B1
A3 B2
B1 C1
B2 C1
A4 C1

我想将数据转换为以下两种方式。转型后,我可以找到一个直线经理内的所有成员,包括不直接向他/她汇报的成员。注意,实际情况下可能有3个以上的层次结构。

我猜这可能与网络分析有关,但不太确定。使用包 dplyr 的数据操作是一种方法。但是,我只是想知道是否有一种简单的方法可以通过某些 R 包中的内置函数来做到这一点?

(1)

Name Line Manager
A1 B1
A2 B1
A3 B2
A1 C1
A2 C1
A3 C1
A4 C1
B1 C1
B2 C1

(2)

Name LM_Level1 LM_Level2
A1 B1 C1
A2 B1 C1
A3 B2 C1
A4 C1
B1 C1
B2 C1

【问题讨论】:

    标签: r dplyr igraph network-analysis


    【解决方案1】:

    设置数据:

    dat <- tibble::tribble(~Name ,   ~Line.Manager,
    "A1" , "B1",
    "A2" , "B1",
    "A3" , "B2",
    "A1" , "C1",
    "A2" , "C1",
    "A3" , "C1",
    "A4" , "C1",
    "B1" , "C1",
    "B2" , "C1")
    
    # Reshaping to wide
    dat <- tidyr::pivot_wider(dat, names_from = Line.Manager, values_from = Line.Manager)
    # Moving values to the left - stolen from here: https://stackoverflow.com/a/26651706/5221626
    dat[] <- t(apply(dat, 1, function(x) c(x[!is.na(x)], x[is.na(x)])))
    # Removing empty columns
    dat <- janitor::remove_empty(dat, "cols")
    # Renaming column names.
    names(dat)[2:ncol(dat)] <- paste0("LM_Level", seq_len(ncol(dat) - 1))
    dat
    
    # A tibble: 6 x 3
      Name  LM_Level1 LM_Level2
      <chr> <chr>     <chr>    
    1 A1    B1        C1       
    2 A2    B1        C1       
    3 A3    B2        C1       
    4 A4    C1        NA       
    5 B1    C1        NA       
    6 B2    C1        NA 
    

    我觉得第二步有点尴尬,但我想不出更好的方法。

    【讨论】:

    • 感谢您的回复。我稍后会试一试。我正在考虑使用一些递归方法。
    【解决方案2】:

    对于(2)(此处标记为step_1),您可以加入df 本身;用line_managername 连接join。

    对于 (1)(标记为 step_2),只需按 name 分组并旋转更长的时间。

    输出(2):

    library(tidyverse)
    
    step_1 <- 
      df %>%
        left_join(df, by = c("line_manager" = "name"), suffix = c("", "_lvl2")) %>%
        replace_na(list(line_manager_lvl2 = ""))
    
      name line_manager line_manager_lvl2
    1   A1           B1                C1
    2   A2           B1                C1
    3   A3           B2                C1
    4   B1           C1                  
    5   B2           C1                  
    6   A4           C1                  
    

    输出(1):

    step_2 <- 
      step_1 %>%
        group_by(name) %>%
        pivot_longer(-name, names_to = 'tmp', values_to = 'line_manager') %>%
        select(-tmp) %>%
        filter(line_manager != "")
    
      name  line_manager
      <chr> <chr>       
    1 A1    B1          
    2 A1    C1          
    3 A2    B1          
    4 A2    C1          
    5 A3    B2          
    6 A3    C1          
    7 B1    C1          
    8 B2    C1          
    9 A4    C1     
    

    数据:

    df <- read.table(text = "Name   Line Manager
    A1  B1
    A2  B1
    A3  B2
    B1  C1
    B2  C1
    A4  C1", 
                     sep = "\t", 
                     header = TRUE, 
                     stringsAsFactors = FALSE) %>%
      mutate(across(everything(), str_replace, " ", "")) %>%
      janitor::clean_names()
    

    注意:我知道将 OP 的 (2)、step_1 和 (1) 称为 step_2 有点奇怪,但 step_ 索引更像是此转换中操作的逻辑顺序。

    【讨论】:

    • 感谢您的回复。我稍后会试一试。我正在考虑使用一些递归方法。
    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    相关资源
    最近更新 更多