Add Nas to Make All List Elements Equal Length

Add NAs to make all list elements equal length

You could use

lapply(lolz, `length<-`, max(lengths(lolz)))
# $a
# [1] 2 4 5 2 3 NA NA
#
# $b
# [1] 3 3 2 NA NA NA NA
#
# $c
# [1] 1 1 2 4 5 3 3
#
# $d
# [1] 1 2 3 1 NA NA NA
#
# $e
# [1] 5 4 2 2 NA NA NA

or

n <- max(lengths(lolz))
lapply(lolz, `length<-`, n)

Equalizing the lengths of all the lists within a list?

Here is your code fixed.
The function should return x, not length(x).
Also, I used vectors, not lists for clarity.

list1 <- c(1, 2, 3)
list2 <- c(1, 2, 3, 4, 5)
list3 <- c(1, 2, 3, 4, 5, 6)

list_lists <- list(list1, list2, list3)

max_length <- max(unlist(lapply (list_lists, FUN = length)))

list_lists <- lapply (list_lists, function (x) {length (x) <- max_length;x})

# [[1]]
# [1] 1 2 3 NA NA NA
#
# [[2]]
# [1] 1 2 3 4 5 NA
#
# [[3]]
# [1] 1 2 3 4 5 6

For original lists the result is:

# [[1]]
# [[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [1] 2
#
# [[1]][[3]]
# [1] 3
#
# [[1]][[4]]
# NULL
#
# [[1]][[5]]
# NULL
#
# [[1]][[6]]
# NULL
#
#
# [[2]]
# [[2]][[1]]
# [1] 1
#
# [[2]][[2]]
# [1] 2
#
# [[2]][[3]]
# [1] 3
#
# [[2]][[4]]
# [1] 4
#
# [[2]][[5]]
# [1] 5
#
# [[2]][[6]]
# NULL
#
#
# [[3]]
# [[3]][[1]]
# [1] 1
#
# [[3]][[2]]
# [1] 2
#
# [[3]][[3]]
# [1] 3
#
# [[3]][[4]]
# [1] 4
#
# [[3]][[5]]
# [1] 5
#
# [[3]][[6]]
# [1] 6

Combine a list of similar length vectors with NAs to one vector

Here's a vectorised version of your code :

dat <- do.call(cbind, x)
#Logical matrix
mat <- !is.na(dat)
#Number of non-NA's in each row
rs <- rowSums(mat)
#First non-NA value
val <- dat[cbind(1:nrow(dat), max.col(mat, ties.method = 'first'))]
#More than 1 non-NA value
val[rs > 1] <- 'conflict'
#Only NA value
val[rs == 0] <- 'none'
val

#[1] "A" "A" "A" "A" "Conflict" "B"
#[7] "B" "B" "B" "none"

EDIT - Updated to include suggestion from @Henrik to avoid nested ifelse which should make the solution faster.

I have a numeric list where I'd like to add 0 or NA to extend the length of the list

I will assume that you start with several lists like that:

n=as.list(1:2)
a=as.list(letters[1:3])
A=as.list(LETTERS[1:4])

First, I'd suggest to combine them into a list of lists:

z <- list(n,a,A)

so you can find the length of the longest sub-lists:

max.length <- max(sapply(z,length))

and use length<- to fill the missing elements of the shorter sub-lists with NULL values:

# z2 <-  lapply(z,function(k) {length(k) <- max.length; return(k)}) # Original version
# z2 <- lapply(z, "length<-", max.length) # More elegant way

z2 <- lapply(lapply(z, unlist), "length<-", max.length) # Even better because it makes sure that the resulting data frame will consists of atomic vectors

The resulting list can be easily transformed into data.frame:

df <- as.data.frame(do.call(rbind,z2))

Convert a list of dataframes of different lengths to an array

I'm not sure about real purpose of OP which lead him to think of creating a 3-D array, for which he needs all data frames of list containing same number of of rows.

But, whatever the reason be, one can achieve it using lapply. Please make a note that lengths function doesn't work properly on list containing data frames. As lengths function simply returns number of columns in each data frame contained in list.

Hence, the approach is to first find maximum number of rows in a data frame contained in mylist. And then iterate over each data frame to extend its rows to maximum number of rows.

# Find maximum row across all data frames in mylist
maxrow <- max(sapply(mylist, nrow))

# Iterate over and increase the row count to maxrow
mylist_mod <- lapply(mylist, function(x,nRow){
if(nrow(x) < nRow){
x[(nrow(x)+1):nRow,] <- NA
}
x
}, nRow = maxrow)

mylist_mod
# $df1
# one two three
# 1 101 111 131
# 2 102 112 132
# 3 103 113 133
# 4 NA NA NA
# 5 NA NA NA
#
# $df2
# one two three
# 1 201 211 231
# 2 202 212 232
# 3 NA NA NA
# 4 NA NA NA
# 5 NA NA NA
#
# $df3
# one two three
# 1 301 311 331
# 2 302 312 332
# 3 303 313 333
# 4 304 314 334
# 5 305 315 335

Sample Data:

df1 <- data.frame(one = 101:103, two = 111:113, three = 131:133)
df2 <- data.frame(one = 201:202, two = 211:212, three = 231:232)
df3 <- data.frame(one = 301:305, two = 311:315, three = 331:335)

mylist <- list(df1 = df1, df2 = df2, df3 = df3)

mylist
# $df1
# one two three
# 1 101 111 131
# 2 102 112 132
# 3 103 113 133
#
# $df2
# one two three
# 1 201 211 231
# 2 202 212 232
#
# $df3
# one two three
# 1 301 311 331
# 2 302 312 332
# 3 303 313 333
# 4 304 314 334
# 5 305 315 335

Make all elemants of a character vector the same length

We can use base R functions to pad 0 at the end of a string to get the number of characters equal. The format with width specified as max of nchar (number of characters) of the vector gives an output with trailing space at the end (as format by default justify it to right. Then, we can replace each space with '0' using gsub. The pattern in the gsub is a single space (\\s) and the replacement is 0.

gsub("\\s", "0", format(test, width=max(nchar(test))))
#[1] "ab12" "cd30" "ef00" "gh03"

Or if we are using a package solution, then str_pad does this more easily as it also have the argument to specify the pad.

library(stringr)
str_pad(test, max(nchar(test)), side="right", pad="0")

How to make sure there are an equal amount of elements in two Python lists?

In your example, the corresponding items are either identical, or the one in list_B should be replaced by a list of NA's of the same length as the item in list_A. This generator expression should be fast enough:

(a if a==b else len(a)*['NA'] for a,b in zip(list_A,list_B)) 

Make all elements of a list equal in dimensions

Create example list like yours:

x <- lapply(2:4, function(i) structure(matrix(1:(i^2), nrow=i, ncol=i),
dimnames=list(100*1:i, 100*1:i)))

Fill in missing rows and columns by row/column name:

cols <- unique(unlist(sapply(x, colnames)))
rows <- unique(unlist(sapply(x, rownames)))

result <- lapply(x, function(m) {
missingrows <- setdiff(rows, rownames(m))
missingcols <- setdiff(cols, colnames(m))
rbind(cbind(m,
structure(matrix(0, nrow=nrow(m), ncol=length(missingcols)),
dimnames=list(NULL, missingcols))),
structure(matrix(0, nrow=length(missingrows), ncol=length(cols)),
dimnames=list(missingrows)))
})

Note that an identical ordering of the rows and columns across tables is not guaranteed using this method (this won't generally be possible because we have no guarantees that the order of the existing rows/columns is identical between the individual tables). Also, corresponding rows/columns between tables can always be identified by their matching names.

Adding NA's to a vector

You could use your own modification of diff:

mydiff <- function(data, diff){
c(diff(data, lag = diff), rep(NA, diff))
}

mydiff(foo, 1)
[1] 0.62 -0.62 -1.38 2.57 0.43 -0.87 NA

data.frame(foo = foo, diff = mydiff(foo, 3))

foo diff
1 102.25 -1.38
2 102.87 0.57
3 102.25 1.62
4 100.87 2.13
5 103.44 NA
6 103.87 NA
7 103.00 NA


Related Topics



Leave a reply



Submit