Turtle
Turtle

Reputation: 55

Row-bind two dataframes, but enforce that the columns' formats of the first dataframe be kept

I'd like to bind (row-wise) two dataframes of different column size, but enforce that the columns' formats of the first dataframe be kept.

Example:

d1 <- tibble(x = 1, y = "b") # before edit: d1 <- tibble(x = 1)
d2 <- tibble(x = c(2, "a"))

When employing, say, plyr's rbind.fill, the combined column will be of the character type. However, I'd like to obtain the (final) result

str(data.frame(x = c(1, 2, NA)))
#> 'data.frame':    3 obs. of  1 variable:
#>  $ x: num  1 2 NA

I suppose for this to work, I'd have to

The problem is, I cannot come up with an elegant solution to this little problem. Any help will be much appreciated!

Edited to account for data frames of different column size.

Upvotes: 0

Views: 272

Answers (2)

Ma&#235;l
Ma&#235;l

Reputation: 51914

In base R with match.fun:

common <- intersect(names(d1), names(d2))
d2[common] <- lapply(common, function(x) {
  match.fun(paste0("as.", class(d1[[x]])))(d2[[x]])
})

dplyr::bind_rows(d1, d2)

output

# A tibble: 3 × 1
      x
  <dbl>
1     1
2     2
3    NA

Upvotes: 1

Allan Cameron
Allan Cameron

Reputation: 173793

Your approach is reasonable and can be done in a single line:

bind_rows(d1, map2_df(d1, d2, ~ `class<-`(.y, class(.x))))
#> # A tibble: 3 x 1
#>       x
#>   <dbl>
#> 1     1
#> 2     2
#> 3    NA

Upvotes: 3

Related Questions