Search code examples
rfor-loopnested-for-loop

Nested For loop in R with error "numerical expression has 2 elements: only the first used"


I am trying to print combinations of 3 consecutive characters in a string using nested for loops in R. The code does print the combinations however I get an error about only doing it for one of the elements and not every row in the dataframe.

x <- data.frame(Pattern = c("abcdef", "hijklmnop"), id = 1:2)

output <- vector("character", length(x$Pattern))

for (i in 1:nrow(x)) {  

  file <- x$Pattern[i]

  for (j in 1:(str_length(x$Pattern))) {
    output[j] <- substr(file, j, j+2)
  }

}

numerical expression has 2 elements: only the first usednumerical expression has 2 elements: only the first used
> 
> output
[1] "hij" "ijk" "jkl" "klm" "lmn" "mno"

There are 2 things happening here that's not working. One is that the var output initiated is using the length of the first pattern (length = 6) and printing combinations based on that length, however I am looking for an output that is the length of the string (length = 9). The intended output is below without using the nested for loop.

  for (j in 1:9) {
    
    output[j] <- substr(file, j, j+2)
    
  }

output
[1] "hij" "ijk" "jkl" "klm" "lmn" "mno" "nop" "op"  "p"  

I trim it down further so that I only have a list of combinations for 3 consecutive characters per string.

list(output[1:(length(output)-3)])
[[1]]
[1] "hij" "ijk" "jkl" "klm" "lmn" "mno"

The second issue that I'm having is that the output is only printing the combinations for the second character string in my list. I've tried changing1:nrow(a) to seq_along and length(a) as advised in other posts, but that's not working. The intended output is below.

a$combo <- output

a$combo
[1] c("abc","bcd","cde","def") c("hij","ijk","jkl","klm","lmn","mno")


Solution

  • x <- data.frame(Pattern = c("abcdef", "hijklmnop"), id = 1:2)
    
    # number of additional letters in individual character string
    add_letters = 2
    
    library(stringr)
    
    output = list()
    
    
    for (i in 1:nrow(x)) {  
        
        file <- x$Pattern[i]
        
        l = list()
        
        for (j in 1:(str_length(x$Pattern[i])-add_letters)) {
            
            l[j] <- c(substr(file, j, j+add_letters))
        
        }
        
        output[[i]] = l 
        
    }
    
    x$combo = output
    

    A solution with lists - as Gregor Thomas suggested.