Условное агрегирование по парам столбцов в R - PullRequest
1 голос
/ 23 марта 2020

ОБНОВЛЕНИЕ: я обновил пример, потому что он не был достаточно понятен.

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

df <- data.frame(year = rep(2005, 8),
             id = 1:8,
             crash_x = c(0, 2, 0, 0, 4, 0,1,2),
             crash_y = c(1, 0, 0, 0, 0, 1,0,0),
             crash_z = c(0, 0, 3, 1, 0, 0,0,0),
             injured_x = c(0, 1, 0, 0, 3, 0,0,0),
             injured_y = c(0, 0, 2, 1, 0, 0,1,2),
             injured_z = c(3, 0, 0, 0, 0, 2, 0,0))

year id crash_x crash_y crash_z injured_x injured_y injured_z
2005 1    0       1       0         0        0          3
2005 2    2       0       0         1        0          0
2005 3    0       0       3         0        2          0
2005 4    0       0       1         0        1          0
2005 5    4       0       0         3        0          0
2005 6    0       1       0         0        0          2
2005 7    1       0       0         0        1          0
2005 8    2       0       0         0        2          0

Я хотел бы суммировать столбцы при условии, что столбцы crash_ и injured_ имеют одинаковый суффикс (x , y или z) имеют числа больше 0 в одних и тех же строках, например, строки 1 и 6, строки 3 и 4, строки 2 и 5, строки 7 и 8 и т. д. c.

. вывод должен выглядеть примерно так:

year crash_x crash_y crash_z injured_x injured_y injured_z
2005     0       2       0         0        0          5
2005     6       0       0         4        0          0
2005     0       0       4         0        3          0
2005     3       0       0         0        3          0

Возможно ли это? Спасибо !!

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Это решение сначала создает новый столбец с «шаблоном» 0 и ненулевыми значениями:

df <- data.frame(year = rep(2005, 8),
                 id = 1:8,
                 crash_x = c(0, 2, 0, 0, 4, 0,1,2),
                 crash_y = c(1, 0, 0, 0, 0, 1,0,0),
                 crash_z = c(0, 0, 3, 1, 0, 0,0,0),
                 injured_x = c(0, 1, 0, 0, 3, 0,0,0),
                 injured_y = c(0, 0, 2, 1, 0, 0,1,2),
                 injured_z = c(3, 0, 0, 0, 0, 2, 0,0))

df %<>% unite("pattern", c(crash_x, crash_y, crash_z, injured_x, injured_y, injured_z), remove = FALSE) %>%
  mutate(pattern = gsub("[1-9]", "1", pattern))

Затем суммирует каждый столбец в соответствии с группой шаблонов с dplyr:

df %>% group_by(pattern, year) %>% 
  summarise_at(vars(crash_x, crash_y, crash_z, injured_x, injured_y, injured_z), sum)
0 голосов
/ 23 марта 2020

Самый простой способ - изменить форму (базовый вариант R):

library(reshape2)

d <- read.table(text = "year id crash_x crash_y crash_z injured_x injured_y injured_z
2005 1    0       1       0         0        0          3
2005 2    2       0       0         1        0          0
2005 3    0       0       3         0        2          0
2005 4    0       0       1         0        1          0
2005 5    4       0       0         3        0          0
2005 6    0       1       0         0        0          2", header = T, stringsAsFactors = F)

want <- melt(subset(d, select = -id), id.vars = "year", variable.name = "crash", value.name = "val")
want$postfix <- gsub("(^crash_)|(^injured_)", "", want$crash)
want <- aggregate(val ~ crash + year + postfix, want, sum)
dcast(want, year + postfix ~ crash, value.var = "val", fill = 0)

#  year postfix crash_x crash_y crash_z injured_x injured_y injured_z
#1 2005       x       6       0       0         4         0         0
#2 2005       y       0       2       0         0         3         0
#3 2005       z       0       0       4         0         0         5
...