Суммирование групп с функциями по группам различной длины нроу - PullRequest
1 голос
/ 28 апреля 2020

Я пытаюсь суммировать группы в большом фрейме данных, используя функцию, которая работает, когда длина nrow группы = 3, но выдает NA для всех групп в данном столбце, когда функция применяется к любым группам, имеющим nrow длина = 1 или 2.

Ниже приведен снимок набора данных, с которым я работаю. Этот фрейм данных является выходом функции group_by, которую я использовал для группировки выборок по зонам (0 или 1) в пределах идентификатора класса ID. Результирующие группы находятся в столбце «grp». Для этого набора данных меня интересуют только группы, у которых значение зоны равно 1 (т.е. группы 2, 4 и 7). Группы со значениями зоны 1 имеют длину 1 или 3 строки.

> df
    ID From To Count Mean_Value Zone
1  ID1    0 48    15 0.04927333    0
2  ID1    0 48    18 0.06273333    0
3  ID1   45 48     3 1.02333333    1
4  ID1   48 49     1 0.10300000    1
5  ID1   49 51     2 0.71500000    1
6  ID1   51 58     7 0.10285714    0
7  ID1   58 59     1 0.55000000    1
8  ID1   59 62     3 0.26333333    0
9  ID2    0 36     9 0.05211111    0
10 ID2   33 34     1 0.70000000    1
11 ID2   34 50     9 0.11666667    0
> grp_test <- group_by(df, grp = data.table::rleid(ID, Zone))
> grp_test
# Groups:   grp [8]
   ID     From    To Count Mean_Value  Zone   grp
   <fct> <int> <int> <int>      <dbl> <int> <int>
 1 ID1       0    48    15     0.0493     0     1
 2 ID1       0    48    18     0.0627     0     1
 3 ID1      45    48     3     1.02       1     2
 4 ID1      48    52     1     0.103      1     2
 5 ID1      49    51     2     0.715      1     2
 6 ID1      51    58     7     0.103      0     3
 7 ID1      58    59     1     0.55       1     4
 8 ID1      59    62     3     0.263      0     5
 9 ID2       0    36     9     0.0521     0     6
10 ID2      33    34     1     0.7        1     7
11 ID2      34    50     9     0.117      0     8

Сейчас я пытаюсь суммировать группы, чтобы получить среднее значение для каждой группы (grp) со значением зоны 1, принимая во внимание «Count» и «Mean_Value» для каждой строки, когда вычисление среднего для группы, которая имеет 3 строки. Я не могу просто использовать функцию «среднее», поскольку среднее значение в каждой строке может иметь различное число. В приведенном выше примере первая строка из группы 2 содержит 3 счета со средним значением 1,02, вторая строка из группы 67 имеет значение 1 со средним значением 0,103, а третья строка имеет значение 2 и среднее значение 0,715. , Среднее значение для этой группы должно быть 0,767167. Ниже приведен код, используемый для вычисления среднего значения, когда группа имеет длину nrow = 3. Проблема заключается в том, что эта функция работает только для групп с длиной nrow 3 и предоставляет значения NA для всего столбца, когда есть группы с длинами nrow. из 1 или 2. Как я могу суммировать группы с длиной nrow = 3, а также группы с длинами nrow 1 или 2?

df_summarise <- summarise(grp_test, ID = first(ID),
                 From = first(From), 
                 To =  last(To), 
                 Number_of_Intervals = n(),
                 Average = (((first(Count) * first(Mean_Value)) + (nth(Count, 2) * nth(Mean_Value, 2)) + (last(Count) * last(Mean_Value))) / (sum(Count))), 
                 Zone = first(Zone))

Ожидаемый результат ниже

   ID From To Count Mean_Value Zone grp
1 ID1   45 51     6  0.7671667    1   2
2 ID1   58 59     1  0.5500000    1   4
3 ID2   33 34     1  0.7000000    1   7

Ответы [ 3 ]

3 голосов
/ 28 апреля 2020

Вы ищете средневзвешенное значение? Т.е.:

df %>% group_by(data.table::rleid(ID, Zone), ID, Zone) %>%
  summarise(
    From = min(From),
    To = max(To),
    Number_of_Intervals = n(),
    Average = weighted.mean(Mean_Value, Count)
  )
1 голос
/ 28 апреля 2020

Мы также можем использовать data.table

library(data.table)
setDT(df)[, .(From = min(From),
               To = max(To),
                Number_of_Intervals = .N,
              Average = weighted.mean(Mean_Value, Count)), 
         .(grp = rleid(ID, Zone), ID, Zone)]
1 голос
/ 28 апреля 2020

Да, я думаю, что @MrGumble прав, вы ищете weighted.mean.

Другой способ рассчитать это:

library(dplyr)

grp_test %>%
  filter(Zone == 1) %>%
  summarise(From = min(From),
            To = max(To),
            Number_of_Intervals = n(),
            Average = sum(Mean_Value * Count)/sum(Count))

#   grp  From    To Number_of_Intervals Average
#  <int> <int> <int>               <int>   <dbl>
#1     2    45    51                   3   0.767
#2     4    58    59                   1   0.55 
#3     7    33    34                   1   0.7  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...