Замена значений столбцов, если они соответствуют одному из двух столбцов в другом наборе данных

У меня есть пример данных следующим образом:

library(data.table)
dat1 <- fread("code1 code2 code3
              A3     B2   C1
              A4     B3   C2")

dat2 <- fread("codes
              A3  
              A4
              B2
              B3")

Я просто хотел бы заменить коды в dat2 на code3 из dat1.

Желаемый результат:

dat_out <- fread("codes
              C1  
              C2
              C1
              C2")

Как мне это сделать?

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

Ответы 5

Это может быть один из способов сделать это:

library(tidyverse)

dat2 %>% 
  inner_join(dat1 %>% pivot_longer(!code3), by = c('codes'='value')) %>%
  select(!name) %>%
  mutate(codes = coalesce(!!!rev(.))) %>%
  select(codes)

   codes
1:    C1
2:    C2
3:    C1
4:    C2
Ответ принят как подходящий

Вы можете использовать match:

`%r%`<- function(x, y) replace(x %% y, x %% y == 0, y)
dat2[, codes := dat1$code3[match(dat2$codes, unlist(dat1)) %r% nrow(dat1)]]

#   codes
#1:    C1
#2:    C2
#3:    C1
#4:    C2

Объяснение:

  • Это использует match для unlisted значения dat1 (вы также можете сосредоточиться только на выбранных столбцах).
  • Затем вы можете использовать %% (по модулю), чтобы получить оставшуюся часть целочисленного деления на nrow(dat1). По сути, он восстанавливает размер столбцов (релист).
  • Проблема в том, что он создает значение 0 там, где нам нужно 2 (или nrow), отсюда и новый оператор.

Мы можем использовать melt вместе с join by on = ..., если вы работаете с data.table, например,

dat2[
  melt(dat1, id.var = "code3"), 
  .(codes = code3),
  on = c(codes = "value")
]

который дает


> dat2[melt(dat1, id.var = "code3"), .(codes = code3), on = c(codes = "value")]
   codes
1:    C1
2:    C2
3:    C1
4:    C2

где melt(dat1, id.var = "code3") выглядит

> melt(dat1, id.var = "code3")
   code3 variable value
1:    C1    code1    A3
2:    C2    code1    A4
3:    C1    code2    B2
4:    C2    code2    B3

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

dat2[, codes := setNames(rep(dat1$code3, 2), unlist(dat1[, 1:2]))[codes]]

-вывод

> dat2
    codes
   <char>
1:     C1
2:     C2
3:     C1
4:     C2

Другое решение, основанное на функции match:

dat2[, codes := dat1[, rep(code3, 2)[match(codes, c(code1, code2))]]]

    codes
1:     C1
2:     C2
3:     C1
4:     C2

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