Выполнение построчной операции в таблице данных с несколькими элементами

У меня есть следующая таблица данных:

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, но я не уверен, что это лучший подход. Мой набор данных намного больше, поэтому важна эффективность.

Спасибо за любые подсказки, как подойти к этому.

Пожалуйста, покажите желаемый результат. Обратите внимание, что в примере данных нет строки, где x=50 и y=52. Пожалуйста, проверьте ваше семя и ваше объяснение

langtang 06.05.2022 17:11

@langtang спасибо за подсказку. Действительно, каким-то образом это не было тем семенем, которое я использовал. Я отредактировал текст, теперь все должно быть в порядке. Я постараюсь добавить желаемый пример вывода для некоторых элементов

ghx12 06.05.2022 17:18

Если x — заданный идентификатор, то выполнение над ним арифметических операций нелогично, так как идентификатор — это категориальное понятие. Хотя это всего лишь «слова», в науке о данных есть много вещей, которые могут сбить с толку, если их неправильно понять.

r2evans 06.05.2022 17:18

Вам нужна сумма этих сумм для каждого x, что дает 1 строку для x, или вам нужны отдельные суммы, таким образом, расширяясь от 100 строк до 5000 строк (50 строк для каждого x)?

langtang 06.05.2022 17:19

@langtang Я искал 50 строк для каждого x

ghx12 06.05.2022 17:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
47
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ты можешь сделать это:

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.

ghx12 06.05.2022 17:37

Я добавил еще один вариант, менее непрозрачный, а также пояснение к первому подходу.

langtang 06.05.2022 17:39

Если я правильно понимаю, запрошенный результат требует перекрестное соединение, где каждый элемент 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

Другие вопросы по теме