Считать разные в R groupby, сначала разбивая ячейки на «,»?

#r #dataframe

#r #фрейм данных

Вопрос:

У меня есть данные в формате, приведенном ниже

a b
1 A,B
1 A
1 B
2 A,B
2 D, C
2 A
2 A

Что мне нужно, так это когда столбцу groupby ‘a’ нужны разные значения столбца ‘b’

a количество
1 2
2 4

Потому что для 1 у нас есть только 2 разных значения, то есть A, B, но для 2 у нас есть 4, то есть A, B, C, D.

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

Заранее спасибо

Комментарии:

1. Пожалуйста, предоставьте свои входные данные в виде кода, который воссоздает data.frame в R. Вы могли бы использовать функцию dput() или аналогичную.

Ответ №1:

Мы можем использовать aggregate в базе R :

 aggregate(b~a,df, function(x) length(unique(unlist(strsplit(x, ',')))))

#  a b
#1 1 2
#2 2 4
 

данные

 df <- structure(list(a = c(1L, 1L, 1L, 2L, 2L, 2L, 2L), b = c("A,B", 
"A", "B", "A,B", "D,C", "A", "A")), class = "data.frame", row.names = c(NA, -7L))
 

Комментарии:

1. Спасибо, я использовал это в dplyr, и это сработало

Ответ №2:

Используя tidyr::separate_rows и dplyr::n_distinct это может быть достигнуто следующим образом:

 library(dplyr)

d %>% 
  tidyr::separate_rows(b) %>% 
  group_by(a) %>% 
  summarise(count = n_distinct(b))
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 2 x 2
#>       a count
#>   <int> <int>
#> 1     1     2
#> 2     2     4
 

ДАННЫЕ

 d <- read.table(text = "a   b
1   A,B
1   A
1   B
2   A,B
2   D,C
2   A
2   A", header = TRUE)
 

Комментарии:

1. Привет, спасибо за ответ. Я пробовал это, но, как я уже упоминал, у меня есть несколько других столбцов, которые мне нужно объединить, и с помощью функции separate_rows() дублирую эти строки. Не могли бы вы помочь с этим?

2. Хм. Поскольку это зависит от структуры ваших данных, я могу только догадываться. Если каждый из ваших столбцов содержит одинаковое количество элементов в строке, то вы могли бы сделать tidyr::separate_rows(b, c, d, ...) . В противном случае я бы предложил обновить ваш вопрос и данные примера.

Ответ №3:

База R с использованием Map() :

 setNames(do.call(c, Map(function(x){length(unique(trimws(unlist(strsplit(x, ",")))))}, 
    with(df, split(b, a)))), names(df))