R: Replace values ​​in a nested list

Suppose we have a nested list:

test <- list( list(a = 1, b = 2, c = NULL), list(a = NULL, b = 2, c = 3)) 

How to replace all NULL values ​​with, for example, NA to preserve the data structure? So I do not lose value / structure when I try to make a data frame from a list. For example:

 data.frame(matrix(unlist(test), nrow = 2, byrow = T)) X1 X2 1 1 2 2 2 3 

The desired output looks something like this:

  X1 X2 X3 1 1 2 NA 2 NA 2 3 

There are suggestions to do this as follows:

 rbind.fill(lapply(test, function(f) { as.data.frame(Filter(Negate(is.null), f)) })) 

This is not quite as we would like. Obviously, size and performance are a problem. The one workaround that comes to mind replaces all NULL values ​​in the same way as you can do for the entire data frame at a time. And then unlist() and matrix() list.

I'm not sure about the performance gains (if any). Perhaps the good old lapply() not so bad.

+7
r
source share
4 answers

We can use stri_list2matrix

 library(stringi) m1 <- matrix(as.numeric(t(sapply(test, stri_list2matrix))), ncol=3) m1 # [,1] [,2] [,3] #[1,] 1 2 NA #[2,] NA 2 3 

It can be converted to data.frame

 as.data.frame(m1) 
+4
source share

The answers below are here , here is a (bit twisted) way to enter base R :

 data.frame(matrix(as.numeric(as.character(unlist(test, recursive=F))), nrow=length(test), byrow=T)) # X1 X2 X3 #1 1 2 NA #2 NA 2 3 
+2
source share

If you know that this is just a two-level list, you can scroll through each item using two testing cycles for is.null .

 test <- list( list(a = 1, b = 2, c = NULL), list(a = NULL, b = 2, c = 3) ) # get structure fyi str(test) # tells you the highest level list length length(test) for(i in 1:length(test)) for(j in 1:length(test[[i]])) # second level if(is.null(test[[i]][[j]])) test[[i]][[j]]<-NA 

EDIT: then of course do what you did before.

+1
source share

Another approach using dput and dget and clipboard.

 test <- list( list(a = 1, b = 2, c = NULL), list(a = NULL, b = 2, c = 3)) dput(test,file="clipboard-1024") tmp=dget(textConnection(gsub("NULL","NA",readChar(con="clipboard-1024",file.info("clipboard-1024")$size)))) data.frame(matrix(unlist(tmp), nrow = 2, byrow = T)) # X1 X2 X3 #1 1 2 NA #2 NA 2 3 

I do not know how fast or slower it is.

0
source share

All Articles