Взвешенная разница наблюдений относительно всех других наблюдений в группе (R) - PullRequest
0 голосов
/ 21 января 2019

У меня есть следующие образцы данных. Есть три группы X, Y и Z и наблюдения с 1 по 9, которые разделены на эти группы. Для каждого наблюдения я наблюдаю переменные A и B. Итак:

test <- data.frame(
  id = 1:9,
  group = c(rep("X", 3), rep("Y", 3), rep("Z", 3)),
  A = seq(from = 0.15, to = 0.55, by = 0.05),
  B = 5:13
)

Что дает

  id group    A  B
1  1     X 0.15  5
2  2     X 0.20  6
3  3     X 0.25  7
4  4     Y 0.30  8
5  5     Y 0.35  9
6  6     Y 0.40 10
7  7     Z 0.45 11
8  8     Z 0.50 12
9  9     Z 0.55 13

То, чего я пытался достичь в течение достаточно долгого времени, таково: для каждого наблюдения от 1 до 9 суммируйте взвешенную разницу значения A этого наблюдения относительно значения A всех других наблюдений группы этого наблюдения. Поэтому для наблюдений с 1 по 4 (в качестве примеров) это должно выглядеть так:

id 1: (0.15 - 0.15) * 5 + (0.15 - 0.20) * 6 + (0.15 - 0.25) * 7 = -1
id 2: (0.20 - 0.15) * 5 + (0.20 - 0.20) * 6 + (0.20 - 0.25) * 7 = -0.1
id 3: (0.25 - 0.15) * 5 + (0.25 - 0.20) * 6 + (0.25 - 0.25) * 7 = 0.8
id 4: (0.30 - 0.30) * 8 + (0.30 - 0.35) * 9 + (0.30 - 0.40) * 10 = -1.45

Например, для наблюдения 3 это означает:

шаг 1: 0,25 - это значение наблюдения 3 для A, это значение сравнивается со значением наблюдения 1 для A (которое составляет 0,15), эта разница в 0,10 взвешивается на 5 (значение наблюдения 1 для B)

шаг 2: 0,25 (значение наблюдения 3 на А) сравнивается со значением наблюдения 2 на А (0,20), а эта разница 0,05 взвешивается на 6 (значение наблюдения 2 на В)

шаг 3: 0,25 (значение наблюдения 3 для A) сравнивается с (его собственным) значением для A, и эта разница 0 взвешивается на 7 (его собственное значение для B) (я вижу, что этот шаг не является необходимым, учитывая разница 0; добавлена ​​для полноты).

шаг 4: сумма шагов 1-3

Есть ли реальный способ реализовать это в R? Я пробовал с mutate и group_by, но пока безуспешно. Любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вы можете сделать это с помощью group_by() и небольшой линейной алгебры:

library(dplyr)

test <- data.frame(
  id = 1:9,
  group = c(rep("X", 3), rep("Y", 3), rep("Z", 3)),
  A = seq(from = 0.15, to = 0.55, by = 0.05),
  B = 5:13
)

test %>% group_by(group) %>%
  mutate(res = A*sum(B) - c(A%*%B))
#> # A tibble: 9 x 5
#> # Groups:   group [3]
#>      id group     A     B    res
#>   <int> <fct> <dbl> <int>  <dbl>
#> 1     1 X      0.15     5 -1.   
#> 2     2 X      0.2      6 -0.1  
#> 3     3 X      0.25     7  0.800
#> 4     4 Y      0.3      8 -1.45 
#> 5     5 Y      0.35     9 -0.1  
#> 6     6 Y      0.4     10  1.25 
#> 7     7 Z      0.45    11 -1.90 
#> 8     8 Z      0.5     12 -0.1  
#> 9     9 Z      0.55    13  1.70

Создано в 2019-01-21 с помощью пакета contex (v0.2.1)

0 голосов
/ 21 января 2019

Вы можете попробовать использовать data.table:

> test[, out := colSums(sapply(A, function(x) (x - A) * B)), by = "group"]
> test
   id group    A  B   out
1:  1     X 0.15  5 -1.00
2:  2     X 0.20  6 -0.10
3:  3     X 0.25  7  0.80
4:  4     Y 0.30  8 -1.45
5:  5     Y 0.35  9 -0.10
6:  6     Y 0.40 10  1.25
7:  7     Z 0.45 11 -1.90
8:  8     Z 0.50 12 -0.10
9:  9     Z 0.55 13  1.70

Что я делаю: я применяю пользовательскую функцию function(x) (x - A) * B) к каждому элементу столбца A, что дает мне матрицу из (A[i] - A[j]) * B[j] элементов. Затем я суммирую столбцы, получая результирующий вектор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...