'Loop R merge multiple data frames together
I am trying to merge multiple dataset (left_join) together inside a loop.
Here is what the data looks like:
Fr1 <- data.frame (v1 = c("a", "b", "c"),
period1 = c("Yes", "Yes", "Yes")
)
Fr2 <- data.frame (v1 = c("b", "d"),
period2 = c("Yes", "Yes")
)
Fr3 <- data.frame (v1 = c("c"),
period3 = c("Yes")
)
Be1 <- data.frame (v1 = c("a", "b", "c"),
period1 = c("Yes", "Yes", "Yes")
)
Be2 <- data.frame (v1 = c("b", "c"),
period2 = c("Yes", "Yes")
)
Be3 <- data.frame (v1 = c("d"),
period3 = c("Yes")
)
table_Fr <- data.frame (v1 = c("a", "b", "c", "d"))
table_Be <- data.frame (v1 = c("a", "b", "c", "d"))
The idea is simple: Fr1, Fr2, and Fr3 go with table_Fr and Be1, Be2 and Be3 go with table_Be.
A simple way to do it dataframe by dataframe goes like this:
table_Fr <- left_join(table_Fr, Fr1, by="v1")
table_Fr <- left_join(table_Fr, Fr2, by="v1")
table_Fr <- left_join(table_Fr, Fr3, by="v1")
table_Fr <- table_Fr %>%
mutate(period1 = ifelse(is.na(period1), "No", period1)) %>%
mutate(period2 = ifelse(is.na(period2), "No", period2)) %>%
mutate(period3 = ifelse(is.na(period3), "No", period3))
However, I have a large number of data frames to merge together, hence I want to use a loop (I know loop are not best in R but I have to do it through a loop...). Unfortunately, I can't get it to work, does anyone can help?
countries <- c("Fr", "Be")
for(c in countries) {
for(i in 1:6) {
p <- paste0("period", i)
cp <- paste0(c, i)
t <- paste0("table_", c)
a <- left_join(t, cp, by="v1") %>%
mutate(!!p := ifelse(is.na(!!p), "No", !!p))
assign(paste0("table_",c), a)
}
}
Solution 1:[1]
You can use base R Reduce or purrr::reduce.
base R
ll <- mget(ls(pattern = "Fr"))
table_Fr <- Reduce(function(x, y) merge(x, y, all=TRUE), ll)
table_Fr[is.na(table_Fr)] <- "No"
# v1 period1 period2 period3
# 1 a Yes No No
# 2 b Yes Yes No
# 3 c Yes No Yes
# 4 d No Yes No
tidyverse
library(tidyverse)
reduce(ll, full_join, by = 'v1') %>%
mutate(across(everything(), ~ replace_na(., 'No')))
# v1 period1 period2 period3
# 1 a Yes No No
# 2 b Yes Yes No
# 3 c Yes No Yes
# 4 d No Yes No
Solution 2:[2]
lapply(countries, function(cntry) {
env=globalenv()
Reduce(dplyr::full_join, mget(ls(pattern=cntry,env=env), env=env))
})
Output:
[[1]]
v1 period1 period2 period3
1 a Yes <NA> <NA>
2 b Yes Yes <NA>
3 c Yes <NA> Yes
4 d <NA> Yes <NA>
[[2]]
v1 period1 period2 period3
1 a Yes <NA> <NA>
2 b Yes Yes <NA>
3 c Yes Yes <NA>
4 d <NA> <NA> Yes
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
