Here is a small piece of code creating three named vectors, all with the same three names of the elements:
# Create three similarly named vectors
vec_1 <- c("element_one" = 3, "element_two" = 7, "element_three" = 9)
vec_2 <- c("element_one" = 7, "element_two" = 2, "element_three" = 4)
vec_3 <- c("element_one" = 10, "element_two" = 16, "element_three" = 1)
I am looking to find a simple and elegant solution to the problem of combining multiple similarly named vectors using the bind_cols function, whilst maintaining those names as a new column in the final tibble. Up to this point I have used the base r cbind function to achieve this.
# Combined the three vectors by their names
combined_vec <- cbind(vec_1, vec_2 = vec_2[names(vec_1)], vec_3 = vec_3[names(vec_1)])
# Create a tibble that keeps the vector names as a column
new_combined <- combined_vec %>%
as.data.frame() %>%
rownames_to_column() %>%
tibble()
Is there a way of achieving this more simply, for example, with the bind_cols function? Or can anyone suggest a simpler solution to achieve this result?
CodePudding user response:
You could use enframe()
to convert each named vector to a 2-column dataframe and merge them by their names.
library(tidyverse)
mget(ls(pattern = 'vec_')) %>%
imap(~ enframe(.x, name = "id", value = .y)) %>%
reduce(left_join, by = "id")
# # A tibble: 3 × 4
# id vec_1 vec_2 vec_3
# <chr> <dbl> <dbl> <dbl>
# 1 element_one 3 7 10
# 2 element_two 7 2 16
# 3 element_three 9 4 1
CodePudding user response:
We can convert named vectors into dataframes using stack, then use merge with Reduce to merge multiple dataframes:
Reduce(function(...) merge(..., all = TRUE, by = "ind"),
lapply(mget(ls(pattern = 'vec_')), stack))
# ind values.x values.y values
# 1 element_one 3 7 10
# 2 element_three 9 4 1
# 3 element_two 7 2 16
CodePudding user response:
Assuming identically named vectors (I'm not sure how you would resolve the ambiguity with similarly named columns), how about:
library(tibble)
library(magrittr)
library(dplyr)
tibble() %>%
bind_rows(list(vec_1, vec_2, vec_3)) %>%
add_column(id=names(vec_1), .before=1)
# A tibble: 3 × 4
id element_one element_two element_three
<chr> <dbl> <dbl> <dbl>
1 element_one 3 7 9
2 element_two 7 2 4
3 element_three 10 16 1
Or, a general solution:
doIt <- function(...) {
x <- list(...)
tibble() %>%
bind_rows(x) %>%
add_column(id=names(x[[1]]), .before=1)
}
doIt(vec_1, vec_2, vec_3)
# A tibble: 3 × 4
id element_one element_two element_three
<chr> <dbl> <dbl> <dbl>
1 element_one 3 7 9
2 element_two 7 2 4
3 element_three 10 16 1
If @DarrenTsai is correct, then
tibble(vec_1, vec_2, vec_3) %>%
add_column(id=names(vec_1), .before=1)
# A tibble: 3 × 4
id vec_1 vec_2 vec_3
<chr> <dbl> <dbl> <dbl>
1 element_one 3 7 10
2 element_two 7 2 16
3 element_three 9 4 1
appears to give the required result.