Группировать, обобщать, распространять в R не работает - PullRequest
1 голос
/ 19 апреля 2020

У меня есть фрейм данных, который выглядит следующим образом:

  ID  Code  Desc
  1   0A    Red
  1   NA    Red
  2   1A    Blue
  3   2B    Green

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

  ID  Combined_Code  Desc
  1    0A | NA       Red
  2    1A            Blue
  3    2B            Green

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

  ID  Combined_Code 0A  NA  1A  2B  Desc
  1    0A | NA      1   1   0   0   Red
  2    1A           0   0   1   0   Blue
  3    2B           0   0   0   1   Green

Я пробовал:

sample_data %>%
 group_by(ID) %>%
 summarise(Combined_Code = paste(unique(Combined_Code), collapse ='|'))

Это работает для создания конкатенации. Однако я не могу заставить это работать в тандеме со спредом:

 sample_data %>%
  group_by(ID) %>%
  summarise(Combined_Code = paste(unique(Combined_Code), collapse ='|'))

sample_data <- spread(count(sample_data, ID, Combined_Code, Desc., Code), Code, n, fill = 0)

Делая это, спреды, но сбрасывают конкатенацию. Я также попробовал это с фильтром вместо суммирования, что дает тот же результат. Это приводит к:

 ID  Combined_Code 0A  NA  1A  2B  Desc
  1    0A          1   0   0   0   Red
  1    NA          0   1   0   0   Red
  2    1A          0   0   1   0   Blue
  3    2B          0   0   0   1   Green

Наконец, я попытался распределить по трубам через функцию суммирования:

sample_data %>%
  group_by(ID) %>%
  summarise(Combined_Code = paste(unique(Combined_Code), collapse ='|')) %>%
  spread(count(sample_data, ID, Combined_Code, Desc., Code), Code, n, fill = 0)

Это приводит к ошибке:

Error: `var` must evaluate to a single number or a column name, not a list
Run `rlang::last_error()` to see where the error occurred.

Что я могу сделать, чтобы решить эти проблемы?

1 Ответ

0 голосов
/ 19 апреля 2020

Мы можем сделать группу с помощью paste

library(dplyr)
library(stringr)
df1 %>%
   group_by(ID, Desc) %>%
   summarise(Combined_Code = str_c(Code, collapse="|"))
# A tibble: 3 x 3
# Groups:   ID [3]
#     ID Desc  Combined_Code
#  <int> <chr> <chr>        
#1     1 Red   0A|0B        
#2     2 Blue  1A           
#3     3 Green 2B     

Во втором случае, после создания столбца 'val' из 1 с, paste элементы 'Code' после группирования по 'ID', 'Des c', затем используйте pivot_wider из tidyr для преобразования из 'длинного' в 'широкоформатный формат.

library(tidyr)
df1 %>% 
   mutate(val = 1) %>%
   group_by(ID, Desc) %>% 
   mutate(Combined_Code = str_c(Code, collapse="|")) %>% 
   pivot_wider(names_from = Code, values_from = val, values_fill = list(val = 0))
# A tibble: 3 x 7
# Groups:   ID, Desc [3]
#    ID Desc  Combined_Code  `0A`  `0B`  `1A`  `2B`
#  <int> <chr> <chr>         <dbl> <dbl> <dbl> <dbl>
#1     1 Red   0A|0B             1     1     0     0
#2     2 Blue  1A                0     0     1     0
#3     3 Green 2B                0     0     0     1

Ожидаемый вывод OP -

  ID  Combined_Code 0A  0B  1A  2B  Desc
  1    0A | 0B      1   1   0   0   Red
  2    1A           0   0   1   0   Blue
  3    2B           0   0   0   1   Green

Обновление

Для обновленного набора данных в «Коде» есть NA элементов, и по умолчанию str_c возвращает NA, если в качестве одного из элементов есть какое-либо NA, тогда как paste по-прежнему возвращает NA вместе с другими элементами. Здесь мы заменяем str_c на paste

df2 %>% 
    mutate(val = 1) %>%
    group_by(ID, Desc) %>% 
    mutate(Combined_Code = paste(Code, collapse="|")) %>% 
    pivot_wider(names_from = Code, values_from = val, values_fill = list(val = 0))
# A tibble: 3 x 7
# Groups:   ID, Desc [3]
#     ID Desc  Combined_Code  `0A`  `NA`  `1A`  `2B`
#  <int> <chr> <chr>         <dbl> <dbl> <dbl> <dbl>
#1     1 Red   0A|NA             1     1     0     0
#2     2 Blue  1A                0     0     1     0
#3     3 Green 2B                0     0     0     1

data

df1 <- structure(list(ID = c(1L, 1L, 2L, 3L), Code = c("0A", "0B", "1A", 
"2B"), Desc = c("Red", "Red", "Blue", "Green")), 
class = "data.frame", row.names = c(NA, 
-4L))



df2 <- structure(list(ID = c(1L, 1L, 2L, 3L), Code = c("0A", NA, "1A", 
"2B"), Desc = c("Red", "Red", "Blue", "Green")), class = "data.frame",
row.names = c(NA, 
-4L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...