# Splitting a numeric column for a dataframe

I have a dataframe df as shown below

  name  position
1 HLA   1:1-15
2 HLA   1:2-16
3 HLA   1:3-17


I would like to split the position column into two more columns based on the ":" character such that i get

name    seq    position
1 HLA   1       1-15
2 HLA   1       2-16
3 HLA   1       3-17


So i thought this would do the trick,

df <- transform(df,pos = as.character(position))

df_split<- strsplit(df$pos, split=":") #found this hack from an old mailing list post df <- transform(df, seq_name= sapply(df_split, "[[", 1),pos2= sapply(df_split, "[[", 2))  however I get an error Error in strsplit(df$pos, split = ":") : non-character argument


What could be wrong? How do you achieve this in R. I have simplified my case here, actuality the dataframe runs to over a hundred thousand rows.

• May be I am doing something wrong, but your I don't get any error if df$pos is a character vector. Can you pls dput your data.frame? Feb 2 '11 at 14:29 • @suncoolsu : The transform call uses the as.data.frame convention of stringsAsFactors=TRUE so the goal of getting a character column was defeated. It was another factor column. Better would have been to use as.character around the argument passed to strsplit. Full code below. – DWin Feb 2 '11 at 14:57 ## 3 Answers df_split<- strsplit(as.character(df$position), split=":")
df <- transform(df, seq_name= sapply(df_split, "[[", 1),pos2= sapply(df_split, "[[", 2))
>
> df
name position    pos seq_name pos2
1  HLA   1:1-15 1:1-15        1 1-15
2  HLA   1:2-16 1:2-16        1 2-16
3  HLA   1:3-17 1:3-17        1 3-17

• +1, did not know that you can pass [[ as a function. Feb 3 '11 at 9:00
• @mpiktas: Yes, and one can also pass "[" as a function, including sometimes adding an extra comma with an empty argument followed by an second index expression in order to work on columns in dataframes or to get to parts of other lists. Probably "[<-" as well, but I don't have a ready made example in mind, and I don't know if there might be some sort of environment issue.
– DWin
Feb 3 '11 at 12:19

Here is a one line method using tidyr.separate():

library(tidyr)
df <- separate(df, position, into = c("seq","position"), sep = ":", extra = "merge")


The "trick" is to use do.call.

> a <- data.frame(x = c("1:1-15", "1:2-16", "1:3-17"))
> a
x
1 1:1-15
2 1:2-16
3 1:3-17
> a$x <- as.character(a$x)
> a.split <- strsplit(a\$x, split = ":")
> tmp <-do.call(rbind, a.split)
> data.frame(a, tmp)
x X1   X2
1 1:1-15  1 1-15
2 1:2-16  1 2-16
3 1:3-17  1 3-17