0

I have several lists with similar names, such as "dist124", "dist131" and so on. I am having an issue while binding those lists/arrays in one dataframe. My code is like this:

id <- c(124,131,137,198)
# create the dataframe with nrow as an initial size only for test
# and ncols as the max length of my lists
df <- data.frame(matrix(NA, nrow = 4, ncol = 33))

row.names(df) <- id
a = 1
for(i in id){
    df[a,] <- do.call(rbind, lapply( paste("dist",i, sep=""), get))
    a <- a+1}

Then I get this error message:

Error in [<-.data.frame(*tmp*, a, , value = c(82.4416264694195, 505.003082621159, : replacement has 5 items, need 33

I know that it is because my lists have different lengths, so in order to work around that issue, I thought to change the length of ALL my lists at once (because they are more than 200 lists).

But I couldn't find a solution to get the max length of those lists into the loop.

I've found a solution for lists of unequal lengths here:
adding NA to make all list elements equal length

So I've tried to adapt it to my case, like this:

b <- 1
for(i in id){
    assign()
    n[b] <- length(paste("dist",i, sep=""))
lapply(paste("dist",i, sep=""), `length<-`, n)
b <- b+1}

If I run length(dist124) = length(dist198), for instance, I can make them equal, but I was looking for a loop solution since I have lots of lists to update its lengths.

Community
  • 1
  • 1

2 Answers2

3

To get the maximum length of a large number of lists with similar names, you could to the following:

# put the lists into a list
myLists <- mget(ls(pattern="dist\\d+"))

Here, the pattern argument is a regular expression that matches any object with the name "dist" followed by numerical digits. mget puts the matched objects into a list. Next,

# get the maximum length from these lists
maxLength <- max(lengths(myLists))

The lengths function, introduced in R 3.2.0, calculates the length of each object in a list and is a faster implementation of sapply(myList, length).

lmo
  • 37,904
  • 9
  • 56
  • 69
  • Side question, is there a way to `append` lists the way you `mget` (I mean with `pattern`? – d.b Feb 12 '17 at 22:17
  • lmo, this is what I was looking for, already implemented! Thank you very much :D – Rebeca Ferreira Feb 12 '17 at 23:06
  • 1
    @d.b I'm not entirely sure what you're looking for, here is one attempt: `l1 <- list(a=1, b=5); l2 <- list(e=6, d=5)` This gives a nested list, then flatten it with `unlist` like `unlist(mget(ls(pattern="l\\d+")), recursive=FALSE)`. Also, you can append lists together with `c`. – lmo Feb 13 '17 at 01:58
0

After implementing the code provided by @Imo (thanks!), I was able to convert my list of lists into a dataframe, so the complete code was like this:

# Join all lists in one nested list # 
myLists <- mget(ls(pattern="dist\\d+"))
# Get the max length of those lists #
maxLength <- max(lengths(myLists))
# generating a dataframe from the nested list, making all lengths equal
allDistancesDf <- as.data.frame(do.call(rbind, lapply(myLists, `length<-`, maxLength)))

Thank you all for the help ;)