#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
столбец) не являются уникальными, что может повлиять на результаты.