Deleting items off a list as I go in R loop

Viewed 99

Apologies in advance for my inefficient code, still learning! I'm trying to create a loop that (1) takes items from a list of semantic characters, copying the ones that are relevant into a new matrix, and (2) deleting the items I copy as I go. I achieved part 1, but cannot get part 2 to work. It only works for the first two rows and then I get a "Error in a[[n]] : subscript out of bounds".

Here is the code that achieves part 1:

for(i in 1:length(split)) {
  a <- strsplit(split[[i]], "\\.") #split each semantic version numeral into individual numbers
  x <- length(a)
  for (n in 1:x){  #for each element in vector r, check if a comment or character
    if (a[[n]][1]==0) {       #comments have a 0 as the first value
        a <- sapply(a, paste, collapse = ".")
        atmatrix[i,n] <- a[n]
        a <- strsplit(a, "\\.")
    }
  }
  
}

My attempt at including part 2

   for(i in 1:length(split)) {
  a <- strsplit(split[[i]], "\\.") #split each semantic version numeral into individual numbers
  x <- length(a)
  for (n in 1:x){  #for each element in vector r, check if a comment or character
    if (a[[n]][1]==0) {       #comments have a 0 as the first value
        a <- sapply(a, paste, collapse = ".")
        atmatrix[i,n] <- a[n]
        a <- a[-n]
        a <- strsplit(a, "\\.")
        x <- length(a)
    }
split[[i]] <- a
  }
  
}

Any help on how I can achieve part 2 within the same loop if possible is greatly appreciated! Sample for one of the split[[i]] items below:

c("0.3 insect damage", "0.12 Apex preserved", "0.113 tertiary", 
"0.14 >1/2 margin preserved", "0.21 USNM type", "1.0 not observed", 
"2.0 not observed", "3.0 not observed", "4.0 not observed", "5.0 not observed", 
"6.0 not observed", "7.0 not observed", "8.4 laminar size notophyll", 
"9.0 not observed", "10.1 laminar shape elliptic", "11.1 medial symmetry", 
"12.0 not observed", "13.1 unlobed", "14.1 untoothed (margin entire)", 
"15.0 not observed", "16.2 obtuse apex angle", "17.2 convex apex", 
"18.0 not observed", "19.0 not observed", "20.0 not observed", 
"21.0 not observed", "22.0 not observed", "23.1 primary venation pinnate", 
"24.0 not observed", "25.0 not observed", "26.0 not observed", 
"27.3.1 major secondaries simple brachidodromous", "28.1 interior secondaries absent", 
"29.0 not observed", "30.0 not observed", "31.2 irregular spacing", 
"32.1 uniform angle", "33.3 excurrent attachment to midvein", 
"34.1.1 proximal course is parallel to major secondaries", "34.2.2 intersecondary length >50% of subjacent secondary", 
"34.3.3 distal course perpendicular to a subjacent major secondary", 
"34.4.2 vein frequency usually 1 per intercostal area", "35.1.1.1.1 intercostal tertiary vein fabric opposite percurrent with straight course", 
"35.1.2.2 obtuse to midvein", "36.4 exmedially decreasing vein angle", 
"37.1.1.1 epimedial tertiaries opposite percurrent", "37.2.1.1 proximal course parallel to the subjacent secondary", 
"37.2.2.1 distal course parallel to the intercostal tertiaries", 
"38.0 not observed", "39.0 not observed", "40.0 not observed", 
"41.0 not observed", "42.0 not observed", "43.0 not observed", 
"44.0 not observed", "45.0 not observed", "46.0 not observed", 
"47.0 not observed", "48.0 not observed", "49.0 not observed", 
"50.0 not observed", "51.0 not observed", "52.0 not observed"
)
1 Answers

I am not 100% sure that I understand what you are trying to do, however, the reason that you are getting an out-of-bounds error is that

  1. You establish the value x here:
x <- length(a)
  1. You then overwrite the entire list a here:
a <- sapply(a, paste, collapse = ".")

The newly created a does not have the same length as as the original a (i.e., it is not x) so it throws an out of bounds error when attempting to access it.

If you are trying to replace the specific item in a, then consider assigning to a[[n]].

Conversely, to simply delete any arbitrary member of a list, you can try:

listname[[indexnumber]] <- NULL

BUT be careful deleting items in a list you are iterating through: this will mess with the indexing of the list as you go. It is probably better to store a vector containing the indices of the list items you want to delete, then, at the end:

# Where del_vec is the vector containing the index positions to delete, e.g.,
del_vec <- c(1, 4, 6, 8)

# Delete all at once
listname[del_vec] <- NULL # note the single square bracket
Related