Как взять данные из одного фрейма данных и скопировать их в существующие столбцы в другом фрейме данных на основе общего идентификатора третьего столбца

#r #dataframe #dplyr

#r #фрейм данных #dplyr

Вопрос:

Итак, у меня есть два разных фрейма данных: тот, над которым я работал (df1), и тот, со всеми новыми данными, которые мне нужно поместить в первый (df2). Df1 содержит несколько столбцов с нулями, ожидающих добавления данных. В Df2 есть данные, которые мне нужны, и еще несколько строк и столбцов, которые меня не интересуют, кроме этих данных. Вот небольшое подмножество типа данных, с которыми я работаю.

Я впервые публикую свои данные, поэтому надеюсь, что все делаю правильно. Дайте мне знать, если вам нужен другой формат.

df1:

 structure(list(season = c(" FA15", " FA15", " FA15", " FA15", 
" FA15", " FA15", " FA15", " FA15", " FA15", " FA15"), year = c("2015", 
"2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", 
"2015"), territory.name = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), plot = c("0", 
"0", "0", "0", "0", "0", "0", "0", "0", "0"), color.band = c("APGBY", 
"APGGU", "APGPW", "APGPW", "APGR", "APGUO", "APGUO", "APGUO", 
"APGUO", "APGYR")), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))
 

df2:

 structure(list(bandnum = c(157328052, 160379101, 157328094, 151313455, 
170364680, 160379104, 151373458, 157328066, 160379103, 160379105
), project = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L), .Label = c("*ISSJ", "ISSJ"), class = "factor"), color.band = c("PAWR", 
"WYWAR", "APGP", "APGO", "ABYG", "URYAR", "APBW", "WABG", "OBWAR", 
"GBGAR"), sex = structure(c(3L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 
2L), .Label = c("?", "F", "M"), class = "factor"), age = structure(c(2L, 
1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L), .Label = c("AHY", "ASY", 
"HY", "N", "SY"), class = "factor")), row.names = c(NA, 10L), class = "data.frame")
 

Я несколько дней размышлял над этой проблемой, пробуя разные вещи и читая так много ответов на переполнение стека, но мне не удается найти четкий ответ о том, как взять данные из одного фрейма данных и скопировать их в существующие столбцы в другом фрейме данных на основе общего идентификатора третьего фрейма данныхстолбец.

В значительной степени я хочу, чтобы r видел, что оба фрейма данных имеют в столбце color.band список для диапазона ABCDEF, а затем берут значение из df2 $ bandnum в той же строке, что и ABCDEF, и копируют его в df1 $ bandnum в строке ABCDEF.

Я не хочу копировать строки, которые находятся в df2, но не в df1, в df1. Я хочу пометить записи, которые существуют в df1, но не в df2, как N / A в столбце bandnum.

Имена столбцов и формат данных для цветовой полосы и номера полосы были стандартизированы для двух фреймов данных, поэтому все должно совпадать. Что у меня есть до сих пор с кодом, так это:

 > practicedf <- left_join(x=df1, y=df2, by = "color.band", all.x = TRUE) 
%>% mutate(y = ifelse(is.na(df1$color.band), df1$bandnum, df1$color.band)) %>% select(df2$bandnum)
 

left_join кажется правильным, потому что он сохраняет все строки в левом (df1) фрейме данных и только совпадающие строки из правого (df2) фрейма данных.
Я получаю эту ошибку, хотя:

 Error in `[[<-.data.frame`(`*tmp*`, col, value = c("APGBY", "APGGU", "APGPW", : 
replacement has 1261 rows, data has 2559
 

color.band — это символьный вектор, а bandnum — числовой, это проблема? В чем может быть проблема здесь?


Редактировать: у меня возникла ошибка с указанием диапазона столбцов в обоих фреймах данных, поэтому я изменил df2 $bandnum на bandnum.y. Теперь мой код

 df1_test <- left_join(x=df1, y=df2, by = "color.band") %>% mutate(y =
 ifelse(is.na(color.band), bandnum, color.band)) %>% select(bandnum.y) 

 

но когда я просматриваю (df1_test), он показывает мне только столбец bandnum.y, и это не то же количество записей, что и в моем исходном df1

Вот подмножество df1_test (не все, потому что это 2600 записей)

Как я могу заставить его отображать и остальные мои данные?

 structure(list(bandnum.y = c("171324972", "171324972", "171324972", 
"178324697", "178324697", "178324697", "178324697", "178324697", 
"178324697", "178324697", "170364505", "170364505", "170364505", 
"170364505", "170364505", "170364505", NA, "178324692", "178324692", 
"178324692")), row.names = c(NA, -20L), class = c("tbl_df", "tbl", 
"data.frame"))
 

Комментарии:

1. В вашем ifelse вы получаете значения из df1 . Вместо этого он был бы без df1$ , потому что столбцы уже находятся в объединенном наборе данных и потому, что вы использовали all.x = TRUE , он может содержать большее количество строк, чем исходный набор данных ‘df1’

Ответ №1:

Мы не можем использовать столбцы исходного набора данных ‘df1’ после объединения, потому что это a left_join . В tidyverse мы указываем имена столбцов без кавычек. all.x Аргумент in отсутствует left_join . Это должно быть из merge

 library(dplyr)
left_join(x=df1, y=df2, by = "color.band") %>% 
     mutate(y = ifelse(is.na(color.band), bandnum, color.band)) 
 

Комментарии:

1. Оттуда я получаю сообщение об ошибке: «Ошибка: невозможно подмножество столбцов, которые не существуют. x Столбец bandnum не существует «. несмотря на то, что bandnum существует в df1 и df2 как столбцы. Почему это может быть?

2. @SarahHays Из вашего примера только ‘df2’ показывает ‘bandnum’, а в ‘df1’ нет ‘bandnum’. Если оба набора данных имеют ‘bandnum’, вам может потребоваться удалить один из этих столбцов из одного из них. В противном случае он изменится на bandnum.x и bandnum.y

3. Спасибо! Еще один вопрос — он запустился и выдал столбец, полный номеров групп, когда я запустил view (df2), но ни одного из моих других столбцов там нет. Как мне их сохранить?

4. @SarahHays Вам может потребоваться назначить выходные данные новому объекту, если это то, что имел в виду ваш комментарий, т.е. out <- left_join(df1, df2, ...

5. @SarahHays хорошо, вы используете select в качестве последнего шага. Затем он выберет только этот столбец. Удалите его, и тогда у вас будут все столбцы. Я думал, что вам нужен только столбец ‘bandnum’. Может быть, select это использовалось как какие-то проверки вывода, а позже забыли их удалить

Ответ №2:

left_join не имеет all.x = TRUE , который является частью базы R. merge

Вы могли бы сделать следующее в base R :

 df1_test <- transform(merge(df1, df2, by = "color.band", all.x = TRUE), 
                      y = ifelse(is.na(color.band), bandnum, color.band))
 

Ответ №3:

Если я не ошибаюсь, вы хотите обновить старый df (df1) информацией из нового df (df2). В data.table , вы можете попробовать это:

 libraty(data.table)
setDT(df1)
setDT(df2)
update.vars = intersect(names(df1), names(df2))  # update only common variables

df1[df2, c(update.vars) := df2[,update.vars, with=FALSE], on= 'color.band'] 
 

Обычно это должно работать. Но в данных идентификаторы «слияния» ( color.band столбец) не являются уникальными, что может повлиять на результаты.