У меня есть следующая таблица данных:
library(data.table)
set.seed(1)
DT <- data.table(ind=1:100,x=sample(100),y=sample(100),group=c(rep("A",50),rep("B",50)))
Теперь проблема заключается в том, что мне нужно взять каждое значение в столбце «x» (то есть каждый заданный идентификатор) и добавить к нему все существующие значения в столбце «y». Мне также нужно сделать это отдельно для столбца «группа». Предположим, что мы начинаем с ID = 1. Этот элемент имеет значение: x_1 = 68 и y_1 = 76. Мы также видим y_2 = 39, y_3 = 24 и т. д. Итак, я хочу вычислить суммы x_1 + y_1, x_1 + y2, x_1 + y_3 и т. д. Но не только для x_1, но и для x_2, x_3 и т. д. Так для x_2 это будет выглядеть так: x_2 + y_1, x_2 + y_2, x_2 + y_3 и т. д. Это также должно выполняться отдельно для каждого столбца «группа» (в связи с этим набор данных должен быть просто разделен по группам).
Обновлено: пример кода для этого только для X_1 и группы A:
current_X <- DT[1,x] # not needed, just to illustrate
vector_current_X <- rep(DT[1,x],nrow(DT[group == "A"]))
DT[group == "A",copy_current_X := vector_current_X]
DT[,sum_current_X_Y := copy_current_X + y]
DT
Одна очевидная проблема с этим подходом заключается в том, что если бы он применялся ко всем x, то в окончательное DT было бы добавлено много столбцов. Поэтому я не уверен, что это лучший подход. В конце концов, я просто ищу наименьшую сумму (на элемент x) для каждого элемента y и для каждой группы.
Я знаю, как выполнять операции на группу, а также знаю функции лапши. Проблема в том, что, насколько я понимаю, мне нужно включить цикл по строкам. А дальше структура результата будет отличаться от исходной таблицы данных, потому что у нас много дополнительных наблюдений. Я видел раньше, что вы можете сохранять списки внутри data.table, но я не уверен, что это лучший подход. Мой набор данных намного больше, поэтому важна эффективность.
Спасибо за любые подсказки, как подойти к этому.
@langtang спасибо за подсказку. Действительно, каким-то образом это не было тем семенем, которое я использовал. Я отредактировал текст, теперь все должно быть в порядке. Я постараюсь добавить желаемый пример вывода для некоторых элементов
Если x
— заданный идентификатор, то выполнение над ним арифметических операций нелогично, так как идентификатор — это категориальное понятие. Хотя это всего лишь «слова», в науке о данных есть много вещей, которые могут сбить с толку, если их неправильно понять.
Вам нужна сумма этих сумм для каждого x, что дает 1 строку для x, или вам нужны отдельные суммы, таким образом, расширяясь от 100 строк до 5000 строк (50 строк для каждого x)?
@langtang Я искал 50 строк для каждого x
Ты можешь сделать это:
DT[, .(.BY$x+DT[group==.BY$group,y]), by=.(x,group)]
Это возвращает N строк на x, где N — размер группы x. Мы используем специальный (.BY
), который доступен в j
при использовании by
. По сути, .BY
— это именованный список, содержащий значения группирующих переменных. Здесь я добавляю значение x (.BY$x
) к вектору значений y
из подмножества DT
, где group
равно текущему значению группы (.BY$group
)
Выход:
x group V1
<int> <char> <int>
1: 68 A 144
2: 68 A 107
3: 68 A 92
4: 68 A 121
5: 68 A 160
---
4996: 4 B 25
4997: 4 B 66
4998: 4 B 83
4999: 4 B 27
5000: 4 B 68
Вы также можете выполнить это с помощью соединения:
DT[,!c("y")][DT[, .(y,group)], on=.(group), allow.cartesian=T][, total:=x+y][order(ind)]
Выход:
ind x group y total
<int> <int> <char> <int> <int>
1: 1 68 A 76 144
2: 1 68 A 39 107
3: 1 68 A 24 92
4: 1 68 A 53 121
5: 1 68 A 92 160
---
4996: 100 4 B 21 25
4997: 100 4 B 62 66
4998: 100 4 B 79 83
4999: 100 4 B 23 27
5000: 100 4 B 64 68
Превосходно! Одна строка кода. Я знал, что было ошибкой начинать думать о петлях. Не могли бы вы немного объяснить свой код? Никогда раньше не видел такого синтаксиса BY
.
Я добавил еще один вариант, менее непрозрачный, а также пояснение к первому подходу.
Если я правильно понимаю, запрошенный результат требует перекрестное соединение, где каждый элемент x
объединяется с каждым элементом y
(внутри каждого group
).
Это можно легко сделать с помощью функции CJ()
:
DT[, CJ(x, y, sorted = FALSE), by = group][, sum_x_y := x + y][]
group x y sum_x_y 1: A 68 76 144 2: A 68 39 107 3: A 68 24 92 4: A 68 53 121 5: A 68 92 160 --- 4996: B 4 21 25 4997: B 4 62 66 4998: B 4 79 83 4999: B 4 23 27 5000: B 4 64 68
Пожалуйста, покажите желаемый результат. Обратите внимание, что в примере данных нет строки, где x=50 и y=52. Пожалуйста, проверьте ваше семя и ваше объяснение