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
Split Up '...' Arguments and Distribute to Multiple Functions
Linear Regression Loop for Each Independent Variable Individually Against Dependent
Remove/Collapse Consecutive Duplicate Values in Sequence
Avoid Clipping of Points Along Axis in Ggplot
Logical Operators (And, Or) with Na, True and False
Last Observation Carried Forward in a Data Frame
How to Get the Maximum Value by Group
Calculate Row-Wise Proportions
Using Rcpp Within Parallel Code via Snow to Make a Cluster
Why Does R Use Partial Matching
Reduce PDF File Size of Plots by Filtering Hidden Objects
Generate an Incrementally Increasing Sequence Like 112123123412345
How to Name the "Row Names" Column in R
How to Use Spread on Multiple Columns in Tidyr Similar to Dcast
Reset Inputs' Button in Shiny App