R: Обновить столбец на основе сопоставления строк из другого фрейма данных - PullRequest
1 голос
/ 15 февраля 2020

У меня есть

mydf1 <- data.frame(ID = c(1,2,3,4,5), color = c("red", NA, NA, NA, "green"), name = c("tom", "dick", "harry", "steve", "mike"))
mydf2 <- data.frame(ID = c(1,2,99), color = c("red", "orange", "yellow"), name = c("tom", "dick", "Aaron"))

Я хотел бы обновить цвет mydf1 $ на соответствующий цвет из mydf2 для любых строк, которые совпадают как по ID, так и по имени. Желаемым результатом было бы обновить цвет в строке 2 до оранжевого и оставить все остальное как есть:

   ID  color   name
1  1   red     tom
2  2   orange  dick
3  3   <NA>    harry
4  4   <NA>    steve
5  5   green   mike

Я пробовал решения с асимметрией c слияния, как в некоторых предыдущих постах, но получил нежелательную перезапись некоторые из моих полей в mydf1. Затем я попытался использовать матч, как предложено в другом посте, но получил ошибку. Не уверен, почему условие соответствия не работает.

mydf1$color <- mydf2$color[match(mydf1[c("ID", "name")], mydf2[c("ID", "name")])]

1 Ответ

0 голосов
/ 15 февраля 2020

Мы можем использовать объединение с data.table on столбцом 'ID' и 'name' и обновлять соответствующее значение 'color' из второго набора данных в первом наборе данных путем назначения (:=)

library(data.table)
setDT(mydf1)[mydf2, color := i.color, on = .(ID, name)]
mydf1
#   ID  color  name
#1:  1    red   tom
#2:  2 orange  dick
#3:  3   <NA> harry
#4:  4   <NA> steve
#5:  5  green  mike

match работает на vector/matrix, а не на data.frame. Если нам нужно использовать match, тогда paste 'ID', 'name' из каждого набора данных и сделать match

i1 <- match(paste(mydf1$ID, mydf1$name), paste(mydf2$ID, mydf2$name), nomatch = 0)

Или использовать tidyverse

library(dplyr)
mydf1 %>%
   left_join(mydf2, by = c("ID", "name")) %>%
    transmute(ID, name, color = coalesce(as.character(color.x), 
                                         as.character(color.y)))
#  ID  name  color
#1  1   tom    red
#2  2  dick orange
#3  3 harry   <NA>
#4  4 steve   <NA>
#5  5  mike  green
...