R tidyverse mutate со всеми комбинациями подмножеств столбцов в сгруппированном кадре данных - PullRequest
0 голосов
/ 19 февраля 2020

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

Вот настройка:

library(tidyverse)
a <- c(2018, 2019, 2020) #years
b <- c(23, 24, 25, 26) #cities
c <- c(45, 46, 47, 48, 49) #jobs
rows <- expand.grid(a, b, c) 
colnames(rows) <- c('a', 'b', 'c')
d <-  sample(c(0,1), nrow(rows), replace = TRUE)
obs <- cbind(rows, d) %>% group_by(a, b) %>% mutate(c = str_c("J", c))
wide <- obs %>% spread(c, d)

, которая производит это:

A grouped_df: 12 × 7
a       b   J45 J46 J47 J48 J49
2018    23  1   0   1   1   1
2018    24  0   0   1   1   0
2018    25  0   1   0   1   1
2018    26  1   0   1   1   1
2019    23  0   0   1   1   1
2019    24  0   1   0   0   1
2019    25  1   0   0   1   0
2019    26  0   1   1   1   1
2020    23  0   1   0   1   0
2020    24  1   0   1   0   1
2020    25  1   0   0   1   0
2020    26  0   1   0   0   0

Фрейм данных data сгруппирован по a и b, и я хочу найти сумму всех комбинаций столбцов J*.

У меня есть я обращался к этому [ tidyverse: Chi Square для всех комбинаций столбцов для руководства, но он не использует группировку.

Я расширил кадр данных, чтобы включить все комбинации с

combos <- data.frame(t(combn(unique(obs$c), 2)))
data <- merge(wide, combos) %>% mutate(X1 = as.character(X1), X2 = as.character(X2))

и head (data, 10) производит это:

    a       b   J45 J46 J47 J48 J49 X1  X2
1   2018    23  1   0   1   1   1   J45 J46
2   2018    24  0   0   1   1   0   J45 J46
3   2018    25  0   1   0   1   1   J45 J46
4   2018    26  1   0   1   1   1   J45 J46
5   2019    23  0   0   1   1   1   J45 J46
6   2019    24  0   1   0   0   1   J45 J46
7   2019    25  1   0   0   1   0   J45 J46
8   2019    26  0   1   1   1   1   J45 J46
9   2020    23  0   1   0   1   0   J45 J46
10  2020    24  1   0   1   0   1   J45 J46

Теперь я хочу сумму для каждой строки значения в столбце X1 и значения в столбце X2. Я не могу заставить map2 или без кавычек eval работать. Чего мне не хватает?

Спасибо за внимание.

РЕДАКТИРОВАТЬ: Дополнительная информация, результаты того, что я пробовал, и желаемый результат (@camille).

С data %>% mutate(d = map2(X1, X2, sum(.x, .y))) я получаю

Error in as_mapper(.f, ...): object '.x' not found

и с data %>% mutate(d = sum(!!sym(X1), !!sym(X2))) я получаю

Error in is_symbol(x): object 'X1' not found.

Я не понимаю, почему он не может найти эти элементы, особенно в map2 case.

В качестве вывода мне нужно сохранить значения группировки и комбинации столбцов со значением суммы (в конечном счете, со списком взвешенных ребер). Оба вывода из ответов @andrew_reece и @ 42- в порядке, но мне любопытно, почему что-то более простое в строках «добавить значения в эти два столбца по строкам» не работает.

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Вот один из подходов: от pivot_longer до filter, вплоть до нужных вам комбинированных значений, затем group_by и sum:

data %>%
  pivot_longer(starts_with("J"), names_to = "var", values_to = "val") %>%
  filter(var == X1 | var == X2) %>% 
  group_by(a, b, X1, X2) %>%
  summarise(combo_val = sum(val))

Вы также можете pivot_wider после фильтрации, и получить комбинированные суммы через rowSums:

data %>%
  pivot_longer(starts_with("J"), names_to = "var", values_to = "val") %>%
  filter(var == X1 | var == X2) %>% 
  pivot_wider (id_cols = c(a, b, X1, X2), 
               names_from = "var", 
               values_from = "val", 
               values_fill = list(val = 0)) %>% 
  mutate(combo_val = rowSums(select(., starts_with("J")))) %>%
  select(a, b, X1, X2, combo_val)

В любом случае вывод будет одинаковым:

# A tibble: 120 x 5
       a     b X1    X2    combo_val
   <dbl> <dbl> <chr> <chr>     <dbl>
 1  2018    23 J45   J46           1
 2  2018    24 J45   J46           2
 3  2018    25 J45   J46           0
 4  2018    26 J45   J46           2
 5  2019    23 J45   J46           2
 6  2019    24 J45   J46           0
 7  2019    25 J45   J46           0
 8  2019    26 J45   J46           0
 9  2020    23 J45   J46           0
10  2020    24 J45   J46           2
# … with 110 more rows
0 голосов
/ 19 февраля 2020

Я предполагаю, что вы хотите что-то вроде этого:

data$sum2s <- rowSums( cbind(   #make one two-column matrix
                             # by indexing with two other two-column matrices below
               as.numeric( data[cbind( 1:nrow(data), match(data$X1,names(data)))]), 
               as.numeric( data[cbind( 1:nrow(data), match(data$X2,names(data)))])
                       ) ) 


> str(data)
'data.frame':   120 obs. of  10 variables:
 $ a    : num  2018 2018 2018 2018 2019 ...
 $ b    : num  23 24 25 26 23 24 25 26 23 24 ...
 $ J45  : num  1 1 1 1 1 0 1 1 1 1 ...
 $ J46  : num  0 1 0 0 0 0 0 1 1 1 ...
 $ J47  : num  1 1 1 0 0 1 1 0 0 1 ...
 $ J48  : num  0 1 0 0 0 1 0 0 1 1 ...
 $ J49  : num  1 1 0 1 0 1 1 0 0 1 ...
 $ X1   : chr  "J45" "J45" "J45" "J45" ...
 $ X2   : chr  "J46" "J46" "J46" "J46" ...
 $ sum2s: num  1 2 1 1 1 0 1 2 2 2 ...

Он использует индексирование с двухколоночной матрицей, которая позволяет вытащить несмежные значения вместо необходимости иметь все значения из той же строки или столбца. См ?"["

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...