通过成对的列收集数据

时间:2019-02-13 19:05:25

标签: r dataframe dplyr

我在塑造dataframe时遇到麻烦。 这是一个示例:

id  institution name1         id1   name2           id2
1   usp         Miles Davis   123   Arturo Sandoval 111
2   unb         Chet Baker    321   Clifford Brown  121
3   usp         Wayne Shorter 222   Hermeto Pascoal 322
4   Puc-rio     John Coltrane 333   Charlie Parker  112

我需要保留idinstitution列,并收集其他类似的列:

id  institution name_all        id_all
1   usp         Miles Davis     123
1   usp         Arturo Sandoval 111
2   unb         Chet Baker      321
2   unb         Clifford Brown  121
3   usp         Wayne Shorter   222
3   usp         Hermeto Pascoal 322
4   Puc-rio     John Coltrane   333
4   Puc-rio     Charlie Parker  112

我正在使用gather中的dplyr函数:

df %>%
gather(name_all, id_all, -id, -institution)

但是它是这样的:

id  institution name    id
1   usp         name1   Miles Davis
1   usp         id1     123
2   unb         name1   Chet Baker
2   unb         id2     121

关于如何配对这些值的任何想法?我有超过5列要这样做,我想我缺少一个参数来指定其中一对配对。我希望我已经说清楚了。

2 个答案:

答案 0 :(得分:0)

我确定有一个更优雅的解决方案,但是您可以尝试:

df %>%
 gather(var, name_all, -matches("id|institution")) %>%
 gather(var2, val, -c(id, institution, var, name_all)) %>%
 mutate(id_all = ifelse(parse_number(var) == parse_number(var2), val, NA)) %>%
 na.omit() %>%
 select(-var, -var2, -val) %>%
 arrange(id)

  id institution        name_all id_all
1  1         usp     Miles_Davis    123
2  1         usp Arturo_Sandoval    111
3  2         unb      Chet_Baker    321
4  2         unb  Clifford_Brown    121
5  3         usp   Wayne_Shorter    222
6  3         usp Hermeto_Pascoal    322
7  4     Puc-rio   John_Coltrane    333
8  4     Puc-rio  Charlie_Parker    112

首先,它将数据从宽转换为长,不包括名为机构或id的变量。其次,它执行第二次从宽到长的转换,以将所有编号的“ id”变量及其值作为单独的行。第三,检查“名称”变量是否具有作为“ id变量”的数字。如果是,则分配适当的值,否则分配NA。最后,删除具有NAs,冗余变量的行并排列数据。

样本数据:

df <- read.table(text = "
                 id  institution name1         id1   name2           id2
                 1   usp         Miles_Davis   123   Arturo_Sandoval 111
                 2   unb         Chet_Baker    321   Clifford_Brown  121
                 3   usp         Wayne_Shorter 222   Hermeto_Pascoal 322
                 4   Puc-rio     John_Coltrane 333   Charlie_Parker  112", header = TRUE, stringsAsFactors = FALSE)

答案 1 :(得分:0)

对于tidyverse解决方案,您可以:

library(dplyr)
library(tidyr)

df %>%
  gather(ColType, ColValue, -id, -institution) %>% 
  mutate(id_number = gsub("^(\\D*)(\\d*)$", "\\2", ColType, ignore.case = TRUE, perl = TRUE),
         ColType = gsub("^(\\D*)(\\d*)$", "\\1", ColType, ignore.case = TRUE, perl = TRUE)
         ) %>% 
  spread(ColType, ColValue) %>% 
  select(-id_number)