5
votes
$\begingroup$

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.

$\endgroup$
2
  • 1
    $\begingroup$ 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? $\endgroup$
    – suncoolsu
    Feb 2 '11 at 14:29
  • 1
    $\begingroup$ @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. $\endgroup$
    – DWin
    Feb 2 '11 at 14:57
10
votes
$\begingroup$
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
$\endgroup$
2
  • 2
    $\begingroup$ +1, did not know that you can pass [[ as a function. $\endgroup$
    – mpiktas
    Feb 3 '11 at 9:00
  • $\begingroup$ @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. $\endgroup$
    – DWin
    Feb 3 '11 at 12:19
3
votes
$\begingroup$

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

library(tidyr)
df <- separate(df, position, into = c("seq","position"), sep = ":", extra = "merge")
$\endgroup$
2
votes
$\begingroup$

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
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.