split columns in "the middle" in R

Viewed 57

I have an example data frame as such:

df_1 <- as.data.frame(cbind(c(14, 27, 38), c(25, 33, 52), c(85, 12, 23)))

Now, I want to split all these columns down the middle so that i get something that would look like this:

df_2 <- as.data.frame(cbind(c(1, 2, 3), c(4, 7, 8), c(2,3,5), c(5, 3, 2), c(8, 1, 2), c(5, 2, 3)))

So my question then is: Is there a command/package that can do this automatically?

In my real data frame I am looking to split columns by name, from an earlier regression where i got the names by inserting: paste0(names(df)[i], "~", names(df)[j]) into my loop. My thought, however, is that this will be quite easy once i find the right command for the data frames given above.

Thanks in advance!

5 Answers

You can use strsplit in base R:

as.data.frame(t(apply(df_1, 1, \(x) as.numeric(unlist(strsplit(as.character(x), ""))))))

  V1 V2 V3 V4 V5 V6
1  1  4  2  5  8  5
2  2  7  3  3  1  2
3  3  8  5  2  2  3

Another possible solution:

library(tidyverse)

map(df_1, ~ str_split(.x, "", simplify = T)) %>% as.data.frame %>% 
  `names<-`(str_c("V", 1:ncol(.))) %>% type.convert(as.is = T) 

#>   V1 V2 V3 V4 V5 V6
#> 1  1  4  2  5  8  5
#> 2  2  7  3  3  1  2
#> 3  3  8  5  2  2  3

Thanks for the answers, they were a lot of help! I ended up using the tidyr package with command:

test <- as.data.frame(separate(data = test, col = "V1", into = c("col_1", "col_2"), sep = "\\~"))

This worked great for me since I ran a regression earlier and had a good operator for separation: "~"

A base R, option would be to use read.fwf

v1 <- do.call(paste0, df_1)
read.fwf(textConnection(v1), widths = rep(1, max(nchar(v1))))

-output

  V1 V2 V3 V4 V5 V6
1  1  4  2  5  8  5
2  2  7  3  3  1  2
3  3  8  5  2  2  3

Another option is to use the splitstackshape package:

df_2 <- df_1 %>%
  splitstackshape::cSplit(., names(.), sep = "", stripWhite = F, type.convert = F) %>%
  setnames(paste0("V", 1:ncol(.)))

Output

df_2

   V1 V2 V3 V4 V5 V6
1:  1  4  2  5  8  5
2:  2  7  3  3  1  2
3:  3  8  5  2  2  3
Related