Как заменить значения данных в кадре, совпадающие по идентификатору и выполняющие различные вычисления по столбцу в R? - PullRequest
1 голос
/ 25 марта 2020

Проблема заключается в следующем: у меня есть фрейм данных, который мне нужно обновить внутри al oop. Простой фрейм данных имеет 4 столбца: идентификатор и четыре числа c столбца. Вот простой фрейм данных на начальном этапе:

res_df <- data.frame(id = c("X", "Y", "Z"), 
                     count = NA, 
                     total = NA, 
                     value = NA)

На каждой итерации генерируется новый фрейм данных с тем же идентификатором и одинаковыми цифрами c столбцов. Например,

loop_df <- data.frame(id = c("X", "Z"), 
                      count = c(1, 0),
                      total = c(20, 0),
                      value = c(0.05, 0))

Мне действительно нужно заполнить res_df информацией из loop_df следующим образом:

  1. строка в loop_df с идентификатором "X" необходимо вставить в соответствующую строку res_df и т. д .;

  2. столбец count должен быть заполнен, выполняя простую сумму между значениями res_df и новейшие значения в loop_df (по существу sum(res_df$count, loop_df$count) на основе id);

  3. столбец total должен быть заполнен таким же образом столбца count (т.е. с простой суммой значений на основе id);

  4. столбец value должен быть заполнен, выполняя простое среднее между значениями res_df и новейших значений в loop_df (по существу mean(res_df$count, loop_df$count) на основе id).

Вот как должен результат быть после первого запуска :

res_df   
id    count    total    value
X     1        20       0.05
Y     NA       NA       NA
Z     0        0        0

Теперь предположим, что во второй итерации l oop, что приводит к loop_df как Fol low

loop_df <- data.frame(id = c("X", "Y"), 
                      count = c(1, 0),
                      total = c(50, 0),
                      value = c(2.35, 0))

Затем res_df необходимо обновить следующим образом

res_df   
id    count    total    value
X     2        70       1.2
Y     0        0        0
Z     0        0        0

Обновление: решение

library(dplyr)
res_df <- arrange(res_df, id)
df_new_info <- arrange(loop_df, id)
ids <- loop_df$id

res_df[res_df$id %in% ids,] <- res_df[res_df$id %in% ids,] %>%
   mutate(count = case_when(is.na(count) ~ loop_df$count,
                            TRUE ~ count + loop_df$count),
          total = case_when(is.na(total) ~ loop_df$total,
                            TRUE ~ total + loop_df$total),
          value = case_when(is.na(value) ~ loop_df$value,
                            TRUE ~ ewise_mean(value, loop_df$value, zero.rm = TRUE))
         )

Однако я все еще ищу решение, которое было бы очень эффективным.

Буду очень признателен за вашу помощь и мысли об этом.

1 Ответ

0 голосов
/ 25 марта 2020

Я не совсем понял, зачем вам нужно для l oop генерировать эти loop_df, вы можете рассмотреть возможность использования lapply, чтобы получить список loop_df, а затем использовать следующее для получения желаемого результата. :

rbindlist(dfl)[, .(count=sum(count), total=sum(total), value=mean(value)), id]

вывод:

   id count total value
1:  X     2    70   1.2
2:  Z     0     0   0.0
3:  Y     0     0   0.0

данные:

library(data.table)
dfl <- list(
    setDT(data.frame(id = c("X", "Z"), 
        count = c(1, 0),
        total = c(20, 0),
        value = c(0.05, 0))),
    setDT(data.frame(id = c("X", "Y"), 
        count = c(1, 0),
        total = c(50, 0),
        value = c(2.35, 0)))
)
...