Преобразуйте широкие данные в длинные со всеми возможными комбинациями - PullRequest
1 голос
/ 27 февраля 2020

Я пытаюсь преобразовать широкие данные в длинный формат, где я беру несколько столбцов и помещаю их в два столбца, включая все возможные комбинации.

Пример широких данных:

> dfWide <- data.frame("id" = 1:5, "code1" = c("a","b", "c", "d", "a"), "code2" = c("b","c", NA, "c", "b"), "code3" = c("c", NA, NA,"b", NA), "code4" = c(NA, NA, NA, "a", NA))
> dfWide
  id code1 code2 code3 code4
1  1     a     b     c  <NA>
2  2     b     c  <NA>  <NA>
3  3     c  <NA>  <NA>  <NA>
4  4     d     c     b     a
5  5     a     b  <NA>  <NA>

Желаемый длинный формат ниже. Меня не беспокоит порядок (т. Е. Если я объединю «а» с «б», мне не нужно «б» с «а».)

> dfLong <- data.frame("id" = c(1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5), "one" = c("a", "a", "b", "b", "c", "d", "d", "d", "c", "c", "b", "a"), "two" = c("b", "c", "c", "c", NA, "c", "b", "a", "b", "a", "a", "b"))
> dfLong
   id one  two
1   1   a    b
2   1   a    c
3   1   b    c
4   2   b    c
5   3   c <NA>
6   4   d    c
7   4   d    b
8   4   d    a
9   4   c    b
10  4   c    a
11  4   b    a
12  5   a    b

1 Ответ

2 голосов
/ 27 февраля 2020

Мы можем повернуть в «длинный» формат и затем использовать group_by combn

library(dplyr)
library(tidyr)
dfWide %>%
   pivot_longer(cols = -id, values_drop_na = TRUE) %>%
   group_by(id) %>%
   summarise(out = if(n() > 1) combn(as.character(unique(value)), 2,
      FUN = function(x) tibble(one = x[1], two = x[2]),
      simplify = FALSE) else list(tibble(one =value, two = NA_character_))) %>% 
  unnest(c(out))
# A tibble: 12 x 3
#      id one   two  
#   <int> <chr> <chr>
# 1     1 a     b    
# 2     1 a     c    
# 3     1 b     c    
# 4     2 b     c    
# 5     3 c     <NA> 
# 6     4 d     c    
# 7     4 d     b    
# 8     4 d     a    
# 9     4 c     b    
#10     4 c     a    
#11     4 b     a    
#12     5 a     b    

В версии dplyr отличается, мы можем сделать summarise чтобы вернуть одну строку, а затем дважды unnest

dfWide %>%
   pivot_longer(cols = -id, values_drop_na = TRUE) %>%
    group_by(id) %>%
    summarise(out = list(if(n() > 1) combn(as.character(unique(value)), 2,
       FUN = function(x) tibble(one = x[1], two = x[2]),
       simplify = FALSE) else list(tibble(one =value, two = NA_character_)))) %>%
    unnest(c(out)) %>% 
    unnest(c(out))
# A tibble: 12 x 3
#     id one   two  
#   <int> <chr> <chr>
# 1     1 a     b    
# 2     1 a     c    
# 3     1 b     c    
# 4     2 b     c    
# 5     3 c     <NA> 
# 6     4 d     c    
# 7     4 d     b    
# 8     4 d     a    
# 9     4 c     b    
#10     4 c     a    
#11     4 b     a    
#12     5 a     b    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...