Home > Enterprise >  R- How to merge/bind several dataframes considering that some of the called dataframes might not exi
R- How to merge/bind several dataframes considering that some of the called dataframes might not exi

Time:01-19

I have to bind/merge dataframes in an iterative process in R. In occasions, some of the dataframes might not exist for reasons I will not explain here. I would like to know how I could bind dataframes even when calling some dataframe that does not exist. As an example, I have these dataframes:

df.R_H <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

df.B_C <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

df.G_H <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

However, in my code I have this:

df5 <- rbind(df.R_H,df.B_C,df.G_H,df.R_C)
df5

How can I bind dataframes although df.R_C does not exist? I can not check individually which dataframes exists or not since I have hundreds of situations like this and I want to do it automatically even when some dataframe does not exist.

CodePudding user response:

You can use mget() to get rbind() all data frames found in the environment. Alternatively for your example you could pass in x explicitly to mget() as paste0("df", 1:4) instead of ls().

df1 <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

df2 <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

df3 <- data.frame(A=c(0,4,5,6,7),
                  B=c(3,9,4,5,8),
                  C=c(1,2,4,2,6))

df5 <- do.call(rbind, mget(ls(), mode = "list", ifnotfound = list(NULL)))
df5
#>       A B C
#> df1.1 0 3 1
#> df1.2 4 9 2
#> df1.3 5 4 4
#> df1.4 6 5 2
#> df1.5 7 8 6
#> df2.1 0 3 1
#> df2.2 4 9 2
#> df2.3 5 4 4
#> df2.4 6 5 2
#> df2.5 7 8 6
#> df3.1 0 3 1
#> df3.2 4 9 2
#> df3.3 5 4 4
#> df3.4 6 5 2
#> df3.5 7 8 6

If you have a crowded environment, which is likely, then you can utilize the pattern argument of ls() to ensure we only pull in relevant data frames through mget(). So if all your data frames start with df..., then you could use:

do.call(rbind, mget(ls(pattern = "^df*"), mode = "list", ifnotfound = list(NULL)))

CodePudding user response:

Another possible solution:

library(tidyverse)

df.R_H <- data.frame(A=c(0,4,5,6,7),
                     B=c(3,9,4,5,8),
                     C=c(1,2,4,2,6))

df.B_C <- data.frame(A=c(0,4,5,6,7),
                     B=c(3,9,4,5,8),
                     C=c(1,2,4,2,6))

df.G_H <- data.frame(A=c(0,4,5,6,7),
                     B=c(3,9,4,5,8),
                     C=c(1,2,4,2,6))

map_dfr(list("df.R_H","df.B_C","df.G_H","df.R_C"), ~ if (exists(.x)) {get(.x)})

#>    A B C
#> 1  0 3 1
#> 2  4 9 2
#> 3  5 4 4
#> 4  6 5 2
#> 5  7 8 6
#> 6  0 3 1
#> 7  4 9 2
#> 8  5 4 4
#> 9  6 5 2
#> 10 7 8 6
#> 11 0 3 1
#> 12 4 9 2
#> 13 5 4 4
#> 14 6 5 2
#> 15 7 8 6
  •  Tags:  
  • Related