#r
#r
Вопрос:
У меня есть два фрейма данных
df1:
Id Name Column3
3 name1 fdf
12 name343 dfd
32 name65 sis
45 name23 rir
16 name98 tit
df2: столбец Name обновлен новыми именами в этом фрейме данных. Обновите те же новые имена в фрейме данных df1.
Id Name Column3
12 newName1 dfd
45 newName34 rir
16 newName111 tit
Я хочу заменить имя в df1 новыми именами в df2 на основе столбца Id.
Ожидаемый результат:
Id Name Column3
3 name1 fdf
12 newName1 dfd
32 name65 sis
45 newName34 rir
16 newName111 tit
Ответ №1:
dplyr 1.0.0 добавил новую экспериментальную функцию rows_update()
, которая делает именно это:
library(tidyverse)
df1 <- read_table("Id Name Column3
3 name1 fdf
12 name343 dfd
32 name65 sis
45 name23 rir
16 name98 tit")
df2 <- read_table("Id Name Column3
12 newName1 dfd
45 newName34 rir
16 newName111 tit")
df1 %>% rows_update(df2, by = "Id")
#> # A tibble: 5 x 3
#> Id Name Column3
#> <dbl> <chr> <chr>
#> 1 3 name1 fdf
#> 2 12 newName1 dfd
#> 3 32 name65 sis
#> 4 45 newName34 rir
#> 5 16 newName111 tit
Ответ №2:
Вы можете использовать match
:
df1$Name[match(df2$Id, df1$Id)] <- df2$Name
df1
# Id Name Column3
#1 3 name1 fdf
#2 12 newName1 dfd
#3 32 name65 sis
#4 45 newName34 rir
#5 16 newName111 tit
Если все значения в df2
отсутствуют в df1
, в этом случае было бы безопаснее объединить и выбрать значения.
library(dplyr)
df1 %>%
left_join(df2, by = 'Id') %>%
mutate(Name = coalesce(Name.y, Name.x)) %>%
select(Id, Name, Column3 = Column3.x)
Комментарии:
1. Здесь я привел только 3 столбца, в моем случае у меня 60 столбцов, запись всех этих 60 столбцов в select не будет хорошей. есть ли какая-либо альтернатива для выбора всех столбцов
2.
select
используется только дляselect
столбцов. Требуемый ответ содержится в самомmutate
шаге. Если столбцов много, то вы можете использоватьselect(Id, Name, matches('\.x$'))
для выбора только столбцов изdf1
.
Ответ №3:
Я бы сделал что-то вроде этого:
library(dplyr)
data <- data1 %>%
left_join(data2, by = "Id") %>%
mutate(Name = ifelse(is.na(Name.y), Name.x, Name.y),
Col3 = ifelse(is.na(Col3.y), Col3.x, Col3.y)) %>%
select(Id, Name, Col3)
Что даст вам требуемый результат. Вы также можете использовать merge
и if else
from base.
Или вы могли бы сделать:
data <- bind_rows(data1, data2) %>%
group_by(Id) %>%
slice(n())
Оба решения не являются надежными по отношению к порядку, в котором вы соединяете фреймы данных.