R — Связать два разных фрейма данных разной длины, добавив NA или логические критерии

#r #dataframe #conditional-statements #rbind

#r #фрейм данных #условные операторы #rbind

Вопрос:

У меня есть следующие 2 базы данных (отображаются только head и tail)

DF 1

 dput(head(df1))
structure(list(id = c(43, 44, 45, 46, 47, 48), seed = 
c(919028655, 
119103778, 110460177, 724234636, 661955607, 1505343599)), 
row.names = c(NA, 
6L), class = "data.frame")


dput(tail(df1))
structure(list(id = c(183, 184, 185, 186, 187, 188), seed = 
c(618503388, 
1892186421, 1623243403, 1851570303, 26744271, 152317517)), 
row.names = 140:145, class = "data.frame")
  

этот фрейм имеет длину 145 строк и каждого участника в качестве уникального идентификационного номера.

DF 2

Это результат переменной, которую нужно было отправить внешним судьям. Как только они вернули данные, они выдали мне CSV-файл всего со 130 строками (что делает невозможным cbind и вызывает сомнения в том, что оценки соответствуют уникальному идентификатору участников)

 dput(head(df2))
structure(list(Response.ID = 43:48, DTT_SCORE.fluency = c(NA, 
NA, 3L, 4L, 14L, NA), 
DTT_SCORE.fluencyAll = c(NA, 
NA, 2L, 4L, 9L, NA)), row.names = c(NA, 6L), class = 
"data.frame")

dput(tail(df2))
structure(list(Response.ID = 168:173, DTT_SCORE.fluency = 
c(NA, 
NA, NA, 6L, 5L, 5L), 
DTT_SCORE.fluencyAll = c(NA, 
NA, NA, 8L, 5L, 6L)), row.names = 125:130, class = 
"data.frame")
  

Вопрос 1

На глаз строка идентификатора, похоже, совпадает с исходной, она просто останавливается на 130-м элементе. Есть ли способ принудительно связать два фрейма данных, принудительно отображая несуществующие строки как NA (превращая 130 длинных df в 145 длинных df со строками от 130 до 145 как пустыми или NA)

Вопрос 2

Поскольку у каждого респондента есть уникальный идентификатор, можно ли было бы написать фрейм данных, который отображает значения, только если идентификатор в df1 совпадает с идентификатором в df2, например,

если df1 $ id == df2 $id display (df2 $ DTT SCORE.fluency) * 1, иначе, если df1 $ id != df2 $id display (df2 $ DTT SCORE.fluency) * 0

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

1. Это больше похоже R на вопрос с тегом, удаление тега pandas

2. Вы ищете merge(df1, df2, by.x="id", by.y="Response.ID") ?

Ответ №1:

Из того, что вы описали, вам действительно нужна операция объединения. Как вам грустно, если идентификатор в обеих таблицах, в каждой строке, совпадает, вы могли бы использовать cbind() . Но поскольку вы больше не можете этого гарантировать, лучше всего использовать соединение, чтобы сделать это сопоставление для вас. У base R есть merge() функция для этого. Поскольку имя столбца идентификаторов в вашем DF2 отличается, я просто переименовываю его так же, как этот столбец отображается в DF1.

 colnames(df2)[1] <- "id"
merge(df1, df2, by = "id", all.x = TRUE)
  

В результате этого:

     id       seed DTT_SCORE.fluency DTT_SCORE.fluencyAll
1   43  919028655                NA                   NA
2   44  119103778                NA                   NA
3   45  110460177                 3                    2
4   46  724234636                 4                    4
5   47  661955607                14                    9
6   48 1505343599                NA                   NA
7  183  618503388                NA                   NA
8  184 1892186421                NA                   NA
9  185 1623243403                NA                   NA
10 186 1851570303                NA                   NA
11 187   26744271                NA                   NA
12 188  152317517                NA                   NA
  

Для создания таблицы, отображающей идентификаторы DF1, которые отображаются в DF2, вы можете использовать следующий код:

 ids <- data.frame(
  ids = unique(df1$id)
)

ids$test <- ids$ids %in% unique(df2$id)
  

В результате этого:

    ids  test
1   43  TRUE
2   44  TRUE
3   45  TRUE
4   46  TRUE
5   47  TRUE
6   48  TRUE
7  183 FALSE
8  184 FALSE
9  185 FALSE
10 186 FALSE
11 187 FALSE
12 188 FALSE
  

Ответ №2:

Оба вопроса можно решить с помощью dplyr *_join() функций. В базе R merge() имеет аналогичную функциональность.

Чтобы объединить все строки из каждого фрейма данных, вы можете использовать full_join() . По умолчанию *_join функции совпадают по любым столбцам с одинаковыми именами, но поскольку ваши столбцы идентификаторов называются по-разному, я указываю это вручную:

 library(dpylr)

full_join(df1, df2, by = c("id" = "Response.ID"))
  

Любые идентификаторы, которые отображаются только в одной таблице, будут иметь NA в других столбцах.

Если вы хотите сохранить только идентификаторы, которые отображаются в обоих фреймах данных, вы можете заменить full_join на inner_join instead . Если вы хотите сохранить все строки из df1 и использовать только совпадающие строки df2 left_join (или right_join наоборот).