Appending NA into a list

Viewed 392

I have this list of lists:

list<-list(c(0.295017919325516, 0.280103991013988, 0.240898624596022, 
0.199677069304782, 0.173637393108632, 0.222134859203746, 0.39823944169409, 
0.391882741855366, 0.21577600728402), c(0.28121757181295, 0.277422184992648, 
0.230017887789819, 0.191847488360009, 0.17455140669152, 0.205591186569629, 
0.4063428966179, 0.429863712702859, 0.248064462722642), c(0.271557391953248, 
0.294647273450576, 0.259500615962201, 0.248402892690127, 0.178084892253651, 
0.215066463654523, 0.40516205719907, 0.27382824544534), c(0.260821771231842, 
0.260253867737171, 0.264572075610469, 0.175500821018062, 0.181187522322482, 
0.197811527945056, 0.393032174562975, 0.336606928254994), c(0.274566347073192, 
0.271933284859567, 0.267972728722684, 0.211355730670407, 0.180921784930061, 
0.185393876280435, 0.384058108716521, 0.374405949140189, 0.312466672989218
), c(0.282151980564761, 0.28721079361022, 0.31787138268144, 0.24739190298477, 
0.186615966111228, 0.158811690362167, 0.395599896385276, 0.386374201627084, 
0.297715499076704))

I would like to append a NA after the seventh position of vectors when they have a length < 9.

My attempt :

for (i in length(list){
  if (length(list[[i]]) < 9){
    list[[i]]<-append(list[[i]],NA,after=list[[i]][7])
  }
}

But it gives the wrong result.

The core problem is that

append(list[[1]],NA,after=list[[1]][7])

gives

 [1] 0.2950179        NA 0.2950179 0.2801040 0.2408986 0.1996771 0.1736374 0.2221349
 [9] 0.3982394 0.3918827

while I'd like it to be

 [1] 0.2950179 0.2950179 0.2801040 0.2408986 0.1996771 0.1736374 0.2221349        NA
 [9] 0.3982394 0.3918827

And I don't understand why.

3 Answers

Here is a base R way.

list[lengths(list) < 9] <- lapply(list[lengths(list) < 9], function(x){
  n <- length(x)
  y <- c(x[seq_len(min(n, 7))], NA)
  if(n > 7) c(y, x[(7 + 1):n]) else y
})

list[3:4]
#[[1]]
#[1] 0.2715574 0.2946473 0.2595006 0.2484029 0.1780849 0.2150665 0.4051621
#[8]        NA 0.2738282
#
#[[2]]
#[1] 0.2608218 0.2602539 0.2645721 0.1755008 0.1811875 0.1978115 0.3930322
#[8]        NA 0.3366069

Perhaps more readable:

list[lengths(list) < 9] <- lapply(list[lengths(list) < 9], function(x){
  n <- length(x)
  i <- seq_len(min(n, 7))
  j <- seq_len(n)[-i]
  c(x[i], NA, x[j])
})

Just use which to find the list items that are too short, and use append in lapply to insert your NA values:

ind <- which(lengths(L) < 9)
if (any(ind)) L[ind] <- lapply(L[ind], append, NA, after = 7)
L
# [[1]]
# [1] 0.2950179 0.2801040 0.2408986 0.1996771 0.1736374 0.2221349 0.3982394
# [8] 0.3918827 0.2157760
# 
# [[2]]
# [1] 0.2812176 0.2774222 0.2300179 0.1918475 0.1745514 0.2055912 0.4063429
# [8] 0.4298637 0.2480645
# 
# [[3]]
# [1] 0.2715574 0.2946473 0.2595006 0.2484029 0.1780849 0.2150665 0.4051621
# [8]        NA 0.2738282
# 
# [[4]]
# [1] 0.2608218 0.2602539 0.2645721 0.1755008 0.1811875 0.1978115 0.3930322
# [8]        NA 0.3366069
# ...

If I understood correctly, you would like to replace the 7th element... if so, the code to replace the 7th element of each vector in the list would be:

for (i in length(list){
  if (length(list[[i]]) < 9){
    list[[i]][7]<-NA
  }
}
Related