Given a list:
alist = list(
list(name="Foo",age=22),
list(name="Bar"),
list(name="Baz",age=NULL)
)
what's the best way to convert this into a dataframe with name and age columns, with missing values (I'll accept NA or "" in that order of preference)?
Simple methods using ldply
fail because it tries to convert each list element into a data frame, but the one with the NULL barfs because the lengths don't match. Best I have at the moment is:
> ldply(alist,function(s){t(data.frame(unlist(s)))})
name age
1 Foo 22
2 Bar <NA>
3 Baz <NA>
but that's pretty icky and the numeric variable becomes a factor...
Firstly, we use brackets with complete. cases() function to exclude missing values in R. Secondly, we omit missing values with na. omit() function.
Convert List to DataFrame using data. data. frame() is used to create a DataFrame in R that takes a list, vector, array, etc as arguments, Hence, we can pass a created list to the data. frame() function to convert list to DataFrame. It will store the elements in a single row in the DataFrame.
In R, missing values are represented by the symbol NA (not available). Impossible values (e.g., dividing by zero) are represented by the symbol NaN (not a number). Unlike SAS, R uses the same symbol for character and numeric data.
The R function is. null indicates whether a data object is of the data type NULL (i.e. a missing value). The function returns TRUE in case of a NULL object and FALSE in case that the data object is not NULL.
Step1: remove NULL
items
non.null.list <- lapply(alist, Filter, f = Negate(is.null))
Step2: stack everything together:
library(plyr)
rbind.fill(lapply(non.null.list, as.data.frame))
# name age
# 1 Foo 22
# 2 Bar NA
# 3 Baz NA
Edit: In case you had a variable that is NULL
for all your list items, it would not show up in your final output. If instead, you'd like a column filled with NA
, the first step should not remove NULL
s but replace them with NA
s:
Step 1 alternative: replace NULL
with NA
:
non.null.list <- lapply(alist, lapply, function(x)ifelse(is.null(x), NA, x))
A comment mentioned wanting only a single loop, which can be achieved with @flodel's answer just by putting the body of the two loops together:
rbind.fill(lapply(alist, function(f) {
as.data.frame(Filter(Negate(is.null), f))
}))
giving
name age
1 Foo 22
2 Bar NA
3 Baz NA
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With