последовательность математических действий, разделенных на группы в R - PullRequest
0 голосов
/ 27 августа 2018

У меня есть данные. Вот пример

 mydat=structure(list(ItemRelation = c(11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 
11628L, 11628L, 11628L, 11628L, 11628L, 11628L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 
11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L, 11627L
), SaleCount = c(0L, 0L, 6L, 0L, 38L, -14L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 33L, 0L, -10L, -2L, 0L, 22L, -4L, 0L, 0L, -5L, 3L, 0L, 
28L, -14L, 0L, 0L, 0L, 0L, 0L, 21L, -5L, 0L, 0L, 0L, 0L, 0L, 
32L, -8L, 6L, 0L, 0L, 0L, 0L, 33L, -7L, 0L, 0L, 0L, 3L, -3L, 
47L, -22L, 0L, 0L, 0L, 0L, 0L, 26L, -3L, 0L, 0L, 0L, 6L, 0L, 
0L, 6L, 0L, 38L, -14L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 33L, 0L, -10L, 
-2L, 0L, 22L, -4L, 0L, 0L, -5L, 3L, 0L, 28L, -14L, 0L, 0L, 0L, 
0L, 0L, 21L, -5L, 0L, 0L, 0L, 0L, 0L, 32L, -8L, 6L, 0L, 0L, 0L, 
0L, 33L, -7L, 0L, 0L, 0L, 3L, -3L, 47L, -22L, 0L, 0L, 0L, 0L, 
0L, 26L, -3L, 0L, 0L, 0L, 6L), DocumentNum = c(3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 3270L, 
3270L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 3271L, 
3271L, 3271L, 3271L, 3271L), IsPromo = c(0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L)), .Names = c("ItemRelation", 
"SaleCount", "DocumentNum", "IsPromo"), class = "data.frame", row.names = c(NA, 
-132L))

Данные содержат две группы по столбцам ItemRelation + DocumentNum.

11628   3270
11627   3271

Есть колонка Испромо. Может принимать только два значения 0 или 1. Так что мне нужно для нулевой категории Испромо по SaleCount получить сумму не отрицательных или нулевых значений. Only сумма положительных значений. В этом случае

6 38 33 22 3 28 21 6 * * +1010

sum=157.

Тогда мне нужно получить сумму only для отрицательного значения

-14
-10
-2
-4
-5
-14
-5


sum=-54

Тогда я должен добавить эти два значения! 157+-54=103 После этого мне нужно 103, чтобы разделить на общее количество положительных значений. Здесь только 8 положительных значений. 103/8 = 12875. Для нулевой категории колонки испромо.

Для первой категории Испромо

по salescount мне нужно получить сумму всех значений, положительных и отрицательных.

32
-8
6
33
-7
3
-3
47
-22
26
-3

sum=104

Тогда этот результат мне нужно разделить на общее значение положительного значения. Это 6

 32
6
33
3
47
26


104/6=17,33333333

И конечный результат. Из этого значения (17,33333333) мне нужно вычесть результат для Zero category of ispromo when we 103 divided by the total number of positive values.

*103/8=12,875*

и умножьте его на количество положительных значений первой категории испромо в нашем случае это 6 17,33333333- (12,875 * 6) = -59,91666667

Эта математическая операция должна быть сделана для каждой группы

11628   3270
11627   3271

Как это сделать? Как ожидается, выход

  ItemRelation DocumentNum Ispromo_by_SaleCount_sum_of_not_negative_or_zero_value for_negative_value
1        11628        3270                                                    157                -54
2        11627        3271                                                    157                -54
  substract_positive_and_negative Ispromo_by_salescount_i_need_get_sum_all_values_and_positive_and_negative
1                             103                                                                       104
2                             103                                                                       104
  divide_on_total_count_positive_value._It_is_5 end_result
1                                        12.875      -59.9
2                                        12.875      -59.9

или ожидаемый результат dput

    expect=sstructure(list(ItemRelation = c(11628L, 11627L), DocumentNum = 3270:3271, 
    Ispromo_by_SaleCount_sum_of_not_negative_or_zero_value = c(157L, 
    157L), for_negative_value = c(-54L, -54L), substract_positive_and_negative = c(103L, 
    103L), Ispromo_by_salescount_i_need_get_sum_all_values_and_positive_and_negative = c(104L, 
    104L), divide_on_total_count_positive_value._It_is_5 = c(12.875, 
    12.875), end_result = c(-59.9, -59.9)), .Names = c("ItemRelation", 
"DocumentNum", "Ispromo_by_SaleCount_sum_of_not_negative_or_zero_value", 
"for_negative_value", "substract_positive_and_negative", "Ispromo_by_salescount_i_need_get_sum_all_values_and_positive_and_negative", 
"divide_on_total_count_positive_value._It_is_5", "end_result"
), class = "data.frame", row.names = c(NA, -2L))

отредактировано с данными

Как это сделать, если для нулевой категории ispromo от SaleCount у меня только нулевые или отрицательные значения, тогда x4 должно быть = 0 по умолчанию. а также есть другой вариант: если для одной категории испромо по SaleCount только ноль или отрицательные значения затем X6 рассчитывается как X6 = 0-x4. Здесь данные и, конечно, может быть два варианта одновременно, как в моем примере.

mydat=structure(list(ItemRelation = c(11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 
11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L, 11709L
), SaleCount = c(0L, 0L, -1L, 0L, 0L, 0L, -2L, 0L, 0L, -1L, 0L, 
0L, 0L, -1L, -1L, 0L, 0L, -1L, 0L, 0L, 0L, 0L, -1L, 0L, 0L, 0L, 
0L, 0L, 0L, -2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, -1L, 0L, 0L, 
0L, -1L, 0L, 0L, 0L, 1L, -2L, 0L, 0L, 0L, 0L), DocumentNum = c(1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 1002L, 
1002L, 1002L, 1002L, 1002L, 1002L, 1002L), IsPromo = c(0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L)), .Names = c("ItemRelation", "SaleCount", "DocumentNum", 
"IsPromo"), class = "data.frame", row.names = c(NA, -52L))

здесь вывод

ItemRelation DocumentNum CalendarYear        X1        X2        X3 X4        X5     X6
1        11709        1002         2018 any value any value any value  0 any value 0-x4=0

1 Ответ

0 голосов
/ 28 августа 2018
library(dplyr)

mydat %>% 
  group_by(ItemRelation, DocumentNum) %>% 
  summarise(X1 = sum(SaleCount[SaleCount > 0 & IsPromo == 0]), 
            X2 = sum(SaleCount[SaleCount < 0 & IsPromo == 0]), 
            X3 = X1 + X2, 
            X4 = X3/sum(SaleCount > 0 & IsPromo == 0),
            X5 = sum(SaleCount[IsPromo == 1]),
            X6 = X5/sum(SaleCount > 0 & IsPromo == 1) - 
                 X3/sum(SaleCount > 0 & IsPromo == 0)*
                 sum(SaleCount > 0 & IsPromo == 1)) %>% 
  ungroup()

# # A tibble: 2 x 8
#   ItemRelation DocumentNum    X1    X2    X3    X4    X5    X6
#          <int>       <int> <int> <int> <int> <dbl> <int> <dbl>
# 1        11627        3271   157   -54   103  12.9   104 -59.9
# 2        11628        3270   157   -54   103  12.9   104 -59.9

Как видите, ключом к этому процессу является возможность sum столбец SaleCount с использованием соответствующего подмножества значений. Например: sum(SaleCount[SaleCount > 0 & IsPromo == 0]) вычислит sum только для положительных значений SaleCount и IsPromo, равных 0.

Аналогичным образом мы можем использовать sum(SaleCount > 0 & IsPromo == 0) для подсчета наблюдений, которые имеют положительные SaleCount и IsPromo равные 0, потому что мы получаем sum (логического) вектора * Значения 1016 * и FALSE.

Для редактирования попробуйте это:

mydat %>% 
  group_by(ItemRelation, DocumentNum) %>% 
  summarise(X1 = sum(SaleCount[SaleCount > 0 & IsPromo == 0]), 
            X2 = sum(SaleCount[SaleCount < 0 & IsPromo == 0]), 
            X3 = X1 + X2, 
            X4 = ifelse(sum(SaleCount > 0 & IsPromo == 0)==0, 0, X3/sum(SaleCount > 0 & IsPromo == 0)),
            X5 = sum(SaleCount[IsPromo == 1]),
            X6 = ifelse(sum(SaleCount > 0 & IsPromo == 1)==0, -X4,  
                        X5/sum(SaleCount > 0 & IsPromo == 1) - 
                        X3/sum(SaleCount > 0 & IsPromo == 0)*
                        sum(SaleCount > 0 & IsPromo == 1))) %>% 
  ungroup() %>%
  mutate_all(~ifelse(. %in% c(-Inf, Inf), 0, .))
...