Свернуть / объединить / объединить несколько столбцов в одну строку через запятую в каждой группе - PullRequest
2 голосов
/ 14 февраля 2020

Это расширение для публикации Свернуть / объединить / объединить столбец в одну строку через запятую в каждой группе

Цель: объединить несколько столбцов в соответствии с одной переменной группировки и отдельным отдельным значения по выбору разделителя.

Воспроизводимый пример:

data <- data.frame(A = c(rep(111, 3), rep(222, 3)), B = c(rep(c(100), 3), rep(200,3)), C = rep(c(1,2,NA),2), D = c(15:20), E = rep(c(1,NA,NA),2))
data
    A   B  C  D  E
1 111 100  1 15  1
2 111 100  2 16 NA
3 111 100 NA 17 NA
4 222 200  1 18  1
5 222 200  2 19 NA
6 222 200 NA 20 NA

A - это переменная группировки, но B по-прежнему отображается в общем результате (B зависит от A в моем приложении) и C , D и E - это переменные, которые нужно объединить в отдельные character строки.

Желаемый результат

    A   B  C    D         E
1 111 100  1,2  15,16,17  1
2 222 100  1,2  18,19,20  1    

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

Какая будет правильная реализация для получения желаемого результата?

Я сосредоточился именно на group_by и summarise_all и aggregate в моих попытках. Они представляют собой полный беспорядок, поэтому я не верю, что это было бы даже полезно для отображения.

РЕДАКТИРОВАТЬ: Опубликованные решения отлично работают для отображения желаемого результата! Продолжать улучшать значение в этом посте для тех, кто его находит.

Как пользователи могут выбирать собственные символы разделения. например, '-', '\n' Текущие решения @akrun и @tmfmnk оба приводят к появлению списков вместо объединенной строки character. Пожалуйста, поправьте меня, если я сказал это неправильно.

data$D
[1] 15 16 17 18 19 20
> data$A
[1] 111 111 111 222 222 222
> data$B
[1] 100 100 100 200 200 200
> data$C
[1]  1  2 NA  1  2 NA
> data$D
[1] 15 16 17 18 19 20
> data$E
[1]  1 NA NA  1 NA NA

Ответы [ 2 ]

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

Мы можем сгруппировать по 'A', 'B' и использовать от summarise_at до paste всех не-NA элементов

library(dplyr)
data %>% 
    group_by(A, B) %>%
    summarise_at(vars(-group_cols()), ~ toString(.[!is.na(.)]))
# A tibble: 2 x 5
# Groups:   A [2]
#      A     B C     D          E    
#  <dbl> <dbl> <chr> <chr>      <chr>
#1   111   100 1, 2  15, 16, 17 1    
#2   222   200 1, 2  18, 19, 20 1   

Если нам нужно передать пользовательский разделитель, используйте paste или str_c

library(stringr)
data %>% 
    group_by(A, B) %>%
    summarise_at(vars(-group_cols()), ~ str_c(.[!is.na(.)], collapse="_"))

Или используя base R с aggregate

aggregate(. ~ A + B, data, FUN = function(x) 
      toString(x[!is.na(x)]), na.action = NULL)
1 голос
/ 14 февраля 2020

С dplyr вы можете сделать:

data %>%
 group_by(A, B) %>%
 summarise_all(~ toString(na.omit(.)))

      A     B C     D          E    
  <dbl> <dbl> <chr> <chr>      <chr>
1   111   100 1, 2  15, 16, 17 1    
2   222   200 1, 2  18, 19, 20 1 
...