使用R从创建新列的行中提取数据

时间:2019-08-16 16:08:07

标签: r dplyr stringr

我有一个看起来像这样的数据集: enter image description here

数据集的代码:

sample <- structure(list(`Employee ID` = c(200, 201, 202, 203, 204, 205
), `Leader1 Name` = c("CH", "CH", "CH", "CH", "CH", "CH"), `Leader1 Level` = c("Founder", 
"Founder", "Founder", "Founder", "Founder", "Founder"), `Leader2 Name` = c("HF", 
"SR", "HF", "HF", "AK", "UT"), `Leader2 Level` = c("CEO", "VP", 
"CEO", "CEO", "Exec", "Exec"), `Leader3 Name` = c("KK", NA, "NA", 
NA, "TR", NA), `Leader3 Level` = c("VP", NA, "VP", NA, "VP", 
NA), `Leader4 Name` = c("EQ", NA, "YY", NA, NA, NA), `Leader4 Level` = c("Director", 
NA, "VP", NA, NA, NA)), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

我希望获得每位员工在每个层次结构中的领导者姓名。所以我期望的输出是这样的: enter image description here

我的处理方法是使用定界符将所有领导者的姓名和级别连接起来,然后去除每个级别

sample$AllLevels <- paste(sample$`Leader1 Name`, sample$`Leader1 Level`, 
                          sample$`Leader2 Name`, sample$`Leader2 Level`, 
                          sample$`Leader3 Name`, sample$`Leader3 Level`, 
                          sample$`Leader4 Name`, sample$`Leader4 Level`, 
                          sep = "~~")


sample$DirectorLevel <- unlist(lapply(strsplit(sample$AllLevels, "Director", fixed = TRUE), '[', 1))
sample$VPLevel <- unlist(lapply(strsplit(sample$DirectorLevel, "VP", fixed = TRUE), '[', 1))
sample$ExecLevel <- unlist(lapply(strsplit(sample$VPLevel, "Exec", fixed = TRUE), '[', 1))
sample$CEOLevel <- unlist(lapply(strsplit(sample$ExecLevel, "CEO", fixed = TRUE), '[', 1))
sample$FounderLevel <- unlist(lapply(strsplit(sample$CEOLevel, "Founder", fixed = TRUE), '[', 1))

sample$Director <- unlist(lapply(strsplit(sample$DirectorLevel, "~~", fixed = TRUE), tail, 1))
sample$VP <- unlist(lapply(strsplit(sample$VPLevel, "~~", fixed = TRUE), tail, 1))
sample$Exec <- unlist(lapply(strsplit(sample$ExecLevel, "~~", fixed = TRUE), tail, 1))
sample$CEO <- unlist(lapply(strsplit(sample$CEOLevel, "~~", fixed = TRUE), tail, 1))
sample$Founder <- unlist(lapply(strsplit(sample$FounderLevel, "~~", fixed = TRUE), tail, 1))


sample <- sample[,c(1, 16:20)]

这是我得到的输出。 enter image description here

这种方法的问题是,如果在特定级别之间没有领导者,那么我将接替下一个领导者,而不是NA。有关员工ID 200,请参见第1行。在执行级别中也重复了VP“ KK”。其他行也有相同的问题。

是否有更好的方法来获得所需的结果?

1 个答案:

答案 0 :(得分:1)

这是tidyverse的一个选项(pivot_longer来自tidyr的开发者-安装here的信息),我们将数据重塑为“长”格式(pivot_longer,然后spread将其预处理后恢复为“宽”格式

library(dplyr)
library(tidyr)#  ‘0.8.3.9000’
library(stringr)
lvls <- c("Director", "VP", "Exec", "CEO", "Founder")
sample %>%
  rename_at(-1, ~ str_replace(., "(\\S+) (\\S+)", '\\2_\\1')) %>% 
  pivot_longer(-`Employee ID`, names_to = c(".value", "group"), names_sep = '_') %>% 
  na.omit %>%
  select(-group) %>%
  group_by(`Employee ID`,
     Level = factor(Level, 
              levels = lvls))%>% 
  mutate(rn = row_number()) %>% 
  spread(Level, Name) %>% 
  select(-rn)
# A tibble: 7 x 6
# Groups:   Employee ID [6]
#  `Employee ID` Director VP    Exec  CEO   Founder
#          <dbl> <chr>    <chr> <chr> <chr> <chr>  
#1           200 EQ       KK    <NA>  HF    CH     
#2           201 <NA>     SR    <NA>  <NA>  CH     
#3           202 <NA>     NA    <NA>  HF    CH     
#4           202 <NA>     YY    <NA>  <NA>  <NA>   
#5           203 <NA>     <NA>  <NA>  HF    CH     
#6           204 <NA>     TR    AK    <NA>  CH     
#7           205 <NA>     <NA>  UT    <NA>  CH     

注意:修正了操作输出中提到的重复步骤


或使用melt/dcast中的data.table

library(data.table)
dcast(melt(setDT(sample), measure = patterns("Level", "Name"),
  na.rm = TRUE)[, value1 := factor(value1, 
        levels = lvls)],
    `Employee ID` + rowid(`Employee ID`, value1) ~ value1,
          value.name = 'value2')[, `Employee ID_1`  := NULL][]
#.   Employee ID Director   VP Exec  CEO Founder
#1:         200       EQ   KK <NA>   HF      CH
#2:         201     <NA>   SR <NA> <NA>      CH
#3:         202     <NA>   NA <NA>   HF      CH
#4:         202     <NA>   YY <NA> <NA>    <NA>
#5:         203     <NA> <NA> <NA>   HF      CH
#6:         204     <NA>   TR   AK <NA>      CH
#7:         205     <NA> <NA>   UT <NA>      CH