Условное суммирование в R (ddply, суммировать, суммировать)

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

Например, мой фрейм данных выглядит примерно так:

Location  A   B   C   D   SampleWeight
x1        2   1   4   3   .1
x1        4   3   4   2   .3
x2        2   3   7   3   .7
x2        4   3   4   3   .8
.....

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

Location   Total   A2   A4   B1   B3    C4   C7  ...
x1         0.4     .1   .3   .1   .3    .4   0.0
x2         1.5     .7   .8   0.0   1.5   .8   .7

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

newdf <- ddply(mydf, ~ `Location`, summarize, 
                total = sum(`SampleWeight`),
                A2 = sum(within(`SampleWeight`, A == "2")),
                A4 = sum(filter(mydf$SampleWeight, A == "4")),
                B1 = sum((mydf$B=="1")$sample_weight)
                ...
                )

Есть ли более простые способы сделать это? Есть ли хороший способ сделать такой файл?

Большое спасибо!!


person GraceLight    schedule 28.06.2017    source источник


Ответы (1)


Вот решение с использованием dplyr и tidyr. Сгенерировать данные:

library(dplyr)
library(tidyr)

df <- tibble(location     = c("x1", "x1", "x2", "x2"),
             A            = c(2, 4, 2, 4),
             B            = c(1, 3, 3, 3),
             C            = c(4, 4, 7, 4),
             D            = c(3, 2, 3, 3),
             SampleWeight = c(.1, .3, .7, .8))

Затем:

res <- df %>%
  group_by(location) %>%
  mutate(total = sum(SampleWeight)) %>%
  gather(key = "letter", value = "number", A, B, C, D) %>%
  mutate(subgroup = paste0(letter, number)) %>%
  group_by(location, subgroup, total) %>%
  summarize(subgroup_total = sum(SampleWeight)) %>%
  spread(key = subgroup, value = subgroup_total) %>%
  mutate_all(function (x) ifelse(is.na(x), 0, x))

Его можно разбить на четыре части:

  1. group_by местоположение и вычислить общий SampleWeight
  2. gather данные в длинном формате и объединить с помощью paste0 для создания нужных подгрупп (которые станут столбцами)
  3. group_by подгруппировать и вычислить сумму SampleWeight, затем spread данные в широкий формат
  4. заменить NA на 0

Результат:

res
  location total    A2    A4    B1    B3    C4    C7    D2    D3
1       x1   0.4   0.1   0.3   0.1   0.3   0.4   0.0   0.3   0.1
2       x2   1.5   0.7   0.8   0.0   1.5   0.8   0.7   0.0   1.5
person George Wood    schedule 28.06.2017