Я пытаюсь сравнить два разных фрейма данных, которые имеют разные столбцы и строки в R. Необходимо получить одни и те же данные в формате df3, любая строка или столбец - это разные данные в формате df4. В моем примере id F, col1 и col2 в обеих двух таблицах одинаковы, но другие столбцы - нет.
Ниже показано, как выглядит мой набор данных:
set.seed(22)
df1 <- data.frame(id=sample(LETTERS, 9, FALSE), col1=sample(0:2, 9, TRUE),
col2 = sample(0:2, 9, TRUE))
df2 <- data.frame(id=sample(LETTERS, 17, FALSE), col1=sample(0:2, 17, TRUE),
col2 = sample(0:2, 17, TRUE),
col6 = sample(0:2, 17, TRUE))
df1
дф2
Я прочитал много решений, но еще не нашел краткого решения, какие-нибудь предложения? Буду признателен за любую оказанную помощь.
Вы можете использовать generics::intersect()
, чтобы найти общие значения, и generics::setdiff()
, чтобы найти разные значения. Обратите внимание, что вам нужно указать пакет generics
, чтобы получить его в нужном формате.
df3 <- generics::intersect(df1, df2[,1:3])
# id col1 col2
# 1 F 1 0
# 2 K 0 2
df4 <- generics::setdiff(df1, df2[,1:3])
# id col1 col2
#1 I 1 2
#2 X 2 0
#3 J 0 2
#4 L 0 1
#5 Q 1 0
#6 E 1 0
#7 C 1 0
Если вы используете tidyverse
или dplyr
, вы можете использовать semi_join
и anti_join
. Вам нужно будет указать столбцы, которые вы хотите использовать для сравнения, используя параметр by
: by = c("id", "col1", "col2")
. (Вы можете оставить by
неуказанным, и *_join
выполнит сравнение, используя все совпадающие имена столбцов, но этого лучше избегать.)
semi_join
возвращает все строки из первого data.frame с совпадением во втором data.frame:
library(dplyr)
# Or:
# library(tidyverse)
# We'll pass df2 as the first argument, to preserve the values in `col6`.
# Swap the order of `df2` and `df1` to drop column `col6`.
df3 <- semi_join(df2, df1, by = c("id", "col1", "col2"))
df3
# id col1 col2 col6
# 1 K 0 2 2
# 2 F 1 0 2
anti_join
возвращает все строки из первого data.frame без совпадений во втором data.frame. Это немного сложнее, потому что мы получим только те строки в первом data.frame, которые отсутствуют во втором. Чтобы получить строки, которые присутствуют в одном из data.frames, но отсутствуют в другом, нам нужно выполнить соединение дважды:
library(dplyr)
# Or:
# library(tidyverse)
df4_a <- anti_join(df1, df2, by = c("id", "col1", "col2"))
df4_b <- anti_join(df2, df1, by = c("id", "col1", "col2"))
df4 <- bind_rows(df4_a, df4_b)
df4
# id col1 col2 col6
# 1 I 1 2 NA
# 2 X 2 0 NA
# 3 J 0 2 NA
# 4 L 0 1 NA
# 5 Q 1 0 NA
# 6 E 1 0 NA
# 7 C 1 0 NA
# 8 Y 1 0 2
# 9 T 2 1 0
# 10 P 2 0 1
# 11 A 1 2 1
# 12 R 2 0 0
# 13 V 2 1 1
# 14 M 0 0 1
# 15 S 1 2 2
# 16 O 0 0 2
# 17 B 2 0 0
# 18 U 0 1 0
# 19 W 1 1 2
# 20 G 1 2 1
# 21 H 2 1 0
# 22 C 2 0 1
Кроме того, вы можете получить df4
более лаконично, если не будете хранить промежуточные результаты:
library(dplyr)
# Or:
# library(tidyverse)
df4 <- bind_rows(
anti_join(df1, df2, by = c("id", "col1", "col2")),
anti_join(df2, df1, by = c("id", "col1", "col2"))
)
df4
# id col1 col2 col6
# 1 I 1 2 NA
# 2 X 2 0 NA
# 3 J 0 2 NA
# 4 L 0 1 NA
# 5 Q 1 0 NA
# 6 E 1 0 NA
# 7 C 1 0 NA
# 8 Y 1 0 2
# 9 T 2 1 0
# 10 P 2 0 1
# 11 A 1 2 1
# 12 R 2 0 0
# 13 V 2 1 1
# 14 M 0 0 1
# 15 S 1 2 2
# 16 O 0 0 2
# 17 B 2 0 0
# 18 U 0 1 0
# 19 W 1 1 2
# 20 G 1 2 1
# 21 H 2 1 0
# 22 C 2 0 1
Существует функция symdiff
, которая должна выполнять оба антисоединения. например symdiff(df1, df2[names(df1)])
Хотя у него не будет столбца 6
Могут ли быть повторяющиеся строки внутри
df1
илиdf2
и должны ли они быть отфильтрованы перед выполнением сравнения? Кроме того, вам нужно иметьcol6
в результате?