Split a line at regular intervals

I would like to split the string at regular intervals. My question is almost identical to this: How to split a string into substrings of a given length? , except that I have a row column in the dataset, and not just a single row.

Here is an example dataset:

df = read.table(text = "
my.id   X1    
010101   1
010102   1
010103   1
010104   1
020101   1
020112   1
021701   0
021802   0
133301   0
133302   0  
241114   0
241215   0
", header = TRUE, colClasses=c('character', 'numeric'), stringsAsFactors = FALSE)

Here is the desired result. I would prefer to remove the leading zeros as shown:

desired.result = read.table(text = "
A1 A2 A3   X1
 1  1  1   1
 1  1  2   1
 1  1  3   1
 1  1  4   1
 2  1  1   1
 2  1 12   1
 2 17  1   0
 2 18  2   0
13 33  1   0
13 33  2   0
24 11 14   0
24 12 15   0
", header = TRUE, colClasses=c('numeric', 'numeric', 'numeric', 'numeric'), stringsAsFactors = FALSE)

Here is a loop that seems to be close and maybe I can use it. However, I think there is a more efficient way.

for(i in 1:nrow(df)) {
     print(substring(df$my.id[i], seq(1, 5, 2), seq(2, 6, 2)))
}

This statement applydoes not work:

apply(df$my.id, 1,  function(x) substring(df$my.id[x], seq(1, 5, 2), seq(2, 6, 2))   )

Thanks for any suggestions. I prefer the solution in base R.

+5
source share
4 answers

, read.fwf, textConnection, . , read. *.

cbind( read.fwf(file=textConnection(df$my.id), 
              widths=c(2,2,2), col.names=paste0("A", 1:3)), 
     X1=df$X1)
#-----------
   A1 A2 A3 X1
1   1  1  1  1
2   1  1  2  1
3   1  1  3  1
4   1  1  4  1
5   2  1  1  1
6   2  1 12  1
7   2 17  1  0
8   2 18  2  0
9  13 33  1  0
10 13 33  2  0
11 24 11 14  0
12 24 12 15  0

(, Rhelp 6 .)

, , read.table. :

read.table(text=gsub('(.{2})','\\1\t',df$my.id) )
#---------
   V1 V2 V3
1   1  1  1
2   1  1  2
3   1  1  3
4   1  1  4
5   2  1  1
6   2  1 12
7   2 17  1
8   2 18  2
9  13 33  1
10 13 33  2
11 24 11 14
12 24 12 15
+10

. apply sapply vapply , substring:

splt <- sapply(df$my.id, function(x) substring(x, seq(1, 5, 2), seq(2, 6, 2))   )
#this will produce the same thing
splt <- vapply(df$my.id, function(x) substring(x, seq(1, 5, 2), seq(2, 6, 2)),c("","","")   )
#     010101 010102 010103 010104 020101 020112 021701 021802 133301 133302 241114 241215
#[1,] "01"   "01"   "01"   "01"   "02"   "02"   "02"   "02"   "13"   "13"   "24"   "24"  
#[2,] "01"   "01"   "01"   "01"   "01"   "01"   "17"   "18"   "33"   "33"   "11"   "12"  
#[3,] "01"   "02"   "03"   "04"   "01"   "12"   "01"   "02"   "01"   "02"   "14"   "15"

. . :

splt <- apply(splt,1,as.numeric)
    # [,1] [,2] [,3]
 # [1,]    1    1    1
 # [2,]    1    1    2
 # [3,]    1    1    3
 # [4,]    1    1    4
 # [5,]    2    1    1
 # [6,]    2    1   12
 # [7,]    2   17    1
 # [8,]    2   18    2
 # [9,]   13   33    1
# [10,]   13   33    2
# [11,]   24   11   14
# [12,]   24   12   15

. , - .

df <- cbind(splt,df)
#    1  2  3  my.id X1
#1   1  1  1 010101  1
#2   1  1  2 010102  1
#3   1  1  3 010103  1
#4   1  1  4 010104  1
#5   2  1  1 020101  1
#6   2  1 12 020112  1
#7   2 17  1 021701  0
#8   2 18  2 021802  0
#9  13 33  1 133301  0
#10 13 33  2 133302  0
#11 24 11 14 241114  0
#12 24 12 15 241215  0

names(df)[1:3] <- c("A1","A2","A3").

+3

Using gsuband some regular expression. I would do something like this (not very elegant, but it does the job)

cbind(
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\1',df$my.id)),
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\2',df$my.id)),
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\3',df$my.id)),
df$X1)

    [,1] [,2] [,3] [,4]
 [1,]    1    1    1    1
 [2,]    1    1    2    1
 [3,]    1    1    3    1
 [4,]    1    1    4    1
 [5,]    2    1    1    1
 [6,]    2    1   12    1
 [7,]    2   17    1    0
 [8,]    2   18    2    0
 [9,]   13   33    1    0
[10,]   13   33    2    0
[11,]   24   11   14    0
[12,]   24   12   15    0

EDIT

I said that it is not very elegant, so I add the @mnel sentence:

x <- gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\1-\\2-\\3',df$my.id)
do.call(rbind, lapply(strsplit(x,'-'), as.numeric)) 
+2
source

You can also use regexto extract each two-digit section.

I used this in conjunction with str_extract_allfromstringr

do.call(rbind,lapply(str_extract_all(as.character(df[['my.id']]), pattern = '[[:digit:]]{2}'), as.numeric))
+2
source

All Articles