У меня есть три фрейма данных, которые я хочу сравнить с dplyr.
df1 <- data.frame(
id = c(1, 2, 3),
name = c("Smith", "Winter", "Summer"),
zip = c(12345, 23456, 34567),
value = c(1, 2, 3)
)
df2 <- data.frame(
id = c(1, 2, 3, 5),
name = c("Smith", "Winter", "Summer", "Taylor"),
zip = c(12345, 23456, 34567, 56789),
value = c(4, 5, 6, 0)
)
df3 <- data.frame(
id = c(1, 2, 4),
name = c("Smith", "Winter", "Miller"),
zip = c(12345, 23456, 45678),
value = c(7, 8, 9)
)
Фреймы данных имеют столбцы с одинаковыми значениями (например, id, name, zip) и столбец со случайным числом (value).
Чего я хотел бы добиться, так это кадра данных, который показывает, какие строки столбцов с похожими значениями (id, name, zip) присутствуют в каких кадрах данных (я знаю, что могу удалить столбец value с помощью select, я просто хотел оставьте его, чтобы показать, что набор данных также содержит переменные элементы).
Я ищу что-то вроде этого в конце концов.
Конечно, я также открыт для других решений, если есть лучший способ сделать это вместо этого представления в конце.
Спасибо!
Вы можете связать свои кадры данных по строке, а затем использовать, например. pivot_wider:
library(dplyr, warn=FALSE)
library(tidyr)
dplyr::lst(df1, df2, df3) |>
bind_rows(.id = "df") |>
mutate(value = TRUE) |>
pivot_wider(names_from = df, values_from = value, names_prefix = "present_in_", values_fill = FALSE)
#> # A tibble: 5 × 6
#> id name zip present_in_df1 present_in_df2 present_in_df3
#> <dbl> <chr> <dbl> <lgl> <lgl> <lgl>
#> 1 1 Smith 12345 TRUE TRUE TRUE
#> 2 2 Winter 23456 TRUE TRUE TRUE
#> 3 3 Summer 34567 TRUE TRUE FALSE
#> 4 5 Taylor 56789 FALSE TRUE FALSE
#> 5 4 Miller 45678 FALSE FALSE TRUE
С reduce и joins:
library(purrr)
library(dplyr)
lst(df1, df2, df3) %>%
imap(\(x, y){colnames(x)[4] <- glue::glue("present_in_{y}"); x}) %>%
reduce(full_join, by = c("id", "name", "zip")) %>%
mutate(across(contains("present"), complete.cases))
id name zip present_in_df1 present_in_df2 present_in_df3
1 1 Smith 12345 TRUE TRUE TRUE
2 2 Winter 23456 TRUE TRUE TRUE
3 3 Summer 34567 TRUE TRUE FALSE
4 5 Taylor 56789 FALSE TRUE FALSE
5 4 Miller 45678 FALSE FALSE TRUE
library(dplyr)
list(df1,df2,df3) |> purrr::reduce(full_join, by = c("id", "name", "zip"), ) |>
mutate(across(contains("value"), ~ifelse(is.na(.x), FALSE, TRUE))) |>
rename(present_in_df1 = value.x,
present_in_df2 = value.y,
present_in_df3 = value)
Соедините их, затем измените форму от длинной к широкой:
library(data.table)
l <- rbindlist(mget(ls(pattern = "^df")), idcol = "df")
dcast(l, id + name + zip ~ df)
# id name zip 1 2 3
# 1: 1 Smith 12345 1 4 7
# 2: 2 Winter 23456 2 5 8
# 3: 3 Summer 34567 3 6 NA
# 4: 4 Miller 45678 NA NA 9
# 5: 5 Taylor 56789 NA 0 NA
Вы можете связать три df вместе, group_by соответствующие столбцы, а затем использовать summarise, чтобы вывести, какая df содержит необходимую информацию.
library(tidyverse)
bind_rows(df1, df2, df3, .id = "df") %>%
group_by(id, name, zip) %>%
summarize(df = paste(df, collapse = ","))
# A tibble: 5 × 4
id name zip df
<dbl> <chr> <dbl> <chr>
1 1 Smith 12345 1,2,3
2 2 Winter 23456 1,2,3
3 3 Summer 34567 1,2
4 4 Miller 45678 3
5 5 Taylor 56789 2
Это может быть вашей конечной точкой, если вы найдете вышеуказанный формат полезным. Чтобы извлечь их в три разных столбца, мы можем grepl на номере df.
bind_rows(df1, df2, df3, .id = "df") %>%
group_by(id, name, zip) %>%
summarize(df = paste(df, collapse = ","), .groups = "drop") %>%
mutate(present_in_df1 = grepl("1", df),
present_in_df2 = grepl("2", df),
present_in_df3 = grepl("3", df), .keep = "unused")
# A tibble: 5 × 6
id name zip present_in_df1 present_in_df2 present_in_df3
<dbl> <chr> <dbl> <lgl> <lgl> <lgl>
1 1 Smith 12345 TRUE TRUE TRUE
2 2 Winter 23456 TRUE TRUE TRUE
3 3 Summer 34567 TRUE TRUE FALSE
4 4 Miller 45678 FALSE FALSE TRUE
5 5 Taylor 56789 FALSE TRUE FALSE