R data.table добавляет новый столбец со значениями из других столбцов, ссылаясь

У меня есть образец data.table, как показано ниже:

> dt = data.table("Label" = rep(LETTERS[1:3], 3),
+                 "Col_A" = c(2,3,5,0,2,7,6,8,9),
+                 "Col_B" = c(1,4,3,5,2,0,7,5,8),
+                 "Col_C" = c(2,0,4,1,5,6,7,3,0))
> dt[order(Label)]

 Label Col_A Col_B Col_C
1:     A     2     1     2
2:     A     0     5     1
3:     A     6     7     7
4:     B     3     4     0
5:     B     2     2     5
6:     B     8     5     3
7:     C     5     3     4
8:     C     7     0     6
9:     C     9     8     0

Я хочу создать новый столбец, который берет значения из существующих столбцов на основе столбца Label. Мой желаемый образец вывода выглядит следующим образом:

 Label Col_A Col_B Col_C Newcol
1:     A     2     1     2      2
2:     A     0     5     1      0
3:     A     6     7     7      6
4:     B     3     4     0      4
5:     B     2     2     5      2
6:     B     8     5     3      5
7:     C     5     3     4      4
8:     C     7     0     6      6
9:     C     9     8     0      0

Логика заключается в том, что значение Newcol относится к соответствующим столбцам на основе столбца Label. Например, первые 3 строки столбца Label — это A, поэтому первые 3 строки столбца Newcol относятся к первым 3 строкам столбца Col_A.

Я пытался использовать код dt[, `:=` ("Newcol" = eval(as.symbol(paste0("Col_", dt$Label))))], но он не дает желаемого результата.

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
35
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Мы можем использовать векторизованную функцию переключения пакета kit, которая, как и data.table, является частью fastverse.

dt[, "Newcol" := kit::vswitch(Label, c("A", "B", "C"), list(Col_A, Col_B, Col_C))]

# or if you want to pass column indices
dt[, "Newcol" := kit::vswitch(Label, c("A", "B", "C"), dt[,2:4])]

dt
   Label Col_A Col_B Col_C Newcol
1:     A     2     1     2      2
2:     A     0     5     1      0
3:     A     6     7     7      6
4:     B     3     4     0      4
5:     B     2     2     5      2
6:     B     8     5     3      5
7:     C     5     3     4      4
8:     C     7     0     6      6
9:     C     9     8     0      0
library(data.table)
dt = data.table("Label" = rep(LETTERS[1:3], 3),
                "Col_A" = c(2,3,5,0,2,7,6,8,9),
                "Col_B" = c(1,4,3,5,2,0,7,5,8),
                "Col_C" = c(2,0,4,1,5,6,7,3,0))

dt[, new := ifelse(Label == "A", Col_A, NA)]
dt[, new := ifelse(Label == "B", Col_B, new)]
dt[, new := ifelse(Label == "C", Col_C, new)]

Если вы можете использовать библиотеку dplyr, я бы использовал оттуда функцию case_when.

dt$newCol <- case_when(dt$Col_A == 'A' ~ Col_A, dt$Col_A == 'B' ~ Col_B, dt$Col_A == 'C' ~ Col_C)

Я не тестировал этот код, но это было бы что-то вроде этого.

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

С fcase:

cols <- unique(dt$Label)
dt[,newCol:=eval(parse(text=paste('fcase(',paste0("Label=='",cols,"',Col_",cols,collapse=','),')')))][]

    Label Col_A Col_B Col_C newCol
   <char> <num> <num> <num>  <num>
1:      A     2     1     2      2
2:      B     3     4     0      4
3:      C     5     3     4      4
4:      A     0     5     1      0
5:      B     2     2     5      2
6:      C     7     0     6      6
7:      A     6     7     7      6
8:      B     8     5     3      5
9:      C     9     8     0      0

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

Похожие вопросы

Порядок имеет значение при использовании all.equal(x,y) vs all.equal(y,x): потенциальная бесконечная рекурсия?
Завершение и заполнение нескольких временных рядов всеми секундами между началом и концом в одной таблице данных в R
Регулярное выражение для поиска строки, содержащей определенную подстроку между двумя разделителями в R
Пропустить несколько строк заголовка при использовании read_excel или read.excel в R
Добавление индекса к тексту в stat_poly_eq
Gtsummary в анализе опроса (метки теряются при использовании функции подмножества опроса)
Переместить текстовую ссылку справки ближе к ярлыку Shiny
Я пытаюсь предсказать новые значения на основе регрессии с помощью функции predict.lm(), но результат показывает неправильное количество новых значений
R xyplot устанавливает грани с помощью разреза, как контролировать порядок?
Цикл для сохранения одного и того же графика с разными бликами с помощью ggplot2