2

Suppose I have this data frame:

df <- data.frame(a=c(1,2))
df$b <- list(NULL, NULL)

Note that sum(is.null(df$b) is 0 because b is a list, not a vector.

How do I get it to be a vector? Some things I tried that didn't work:

# does nothing
df <- df %>% flatten(b)
# removes column b!
df <- df %>% mutate(b=unlist(b))
# destroys df
df <- df %>% unnest(cols=c(b))
# doesn't run
df <- df %>% mutate_at(vars=c('b'), funs(unlist))

There are already several questions that ask this, but their solutions did not work for me.

I am trying to get through data from jsonlite, similar data to this question.

Karolis Koncevičius
  • 9,417
  • 9
  • 56
  • 89
dfrankow
  • 20,191
  • 41
  • 152
  • 214
  • 1
    do you expect a data.frame as output or a `b` only vector. Here, it is not clear about the expected because `c(NULL, NULL)` won't work to be of length 2, it is still a single NULL – akrun Mar 30 '20 at 22:17
  • Good question. I want to end up with a dataframe, with `b` as a column. – dfrankow Mar 31 '20 at 02:04
  • If you know `b` is the list column. Wouldn't `df$b <- NA` work? – Ronak Shah Mar 31 '20 at 04:31
  • @RonakShah I was not super-specific, but some of the NULLs may not be NULL, and I don't want to lose them. I should've had two examples: one all NULLs, one only some NULLs. – dfrankow Mar 31 '20 at 12:47

3 Answers3

3

Set up data:

df <- data.frame(a=c(1,2,3))
df$b <- list(NULL, NULL, 4)

Unlist:

df$d <- unlist(lapply(df$b, function(x) ifelse(is.null(x), NA, x)))

Verify the answer:

df
#   a    b  d
# 1 1 NULL NA
# 2 2 NULL NA
# 3 3    4  4

str(df)
'data.frame':   3 obs. of  3 variables:
 $ a: num  1 2 3
 $ b:List of 3
  ..$ : NULL
  ..$ : NULL
  ..$ : num 4
 $ d: num  NA NA 4
dfrankow
  • 20,191
  • 41
  • 152
  • 214
Sathish
  • 12,453
  • 3
  • 41
  • 59
1

We can use map to replace the NULL elements with NA and then unnest

library(dplyr)
library(tidyr)
library(purrr)
df %>%
    mutate(b = map(b, ~ replace(., is.null(.), NA))) %>% 
    unnest(c(b))
# A tibble: 2 x 2
#      a b    
#  <dbl> <lgl>
#1     1 NA   
#2     2 NA   

Or a hacky option is

df %>%
    mutate(b = coalesce(NA, unlist(b)))
#  a  b
#1 1 NA
#2 2 NA

When there are only NULL elements, it needs to be converted to other value e.g. NA or else it would not work in a vector

c(NULL, NULL)
#NULL
akrun
  • 874,273
  • 37
  • 540
  • 662
1

Starting with the data frame of @Sathish:

df <- data.frame(a=c(1,2,3))
df$b <- list(NULL, NULL, 4)

code to transform:

is.na(df$b) <- lengths(df$b)==0
df$b <- unlist(df$b)

df
  a  b
1 1 NA
2 2 NA
3 3  4
dfrankow
  • 20,191
  • 41
  • 152
  • 214
Karolis Koncevičius
  • 9,417
  • 9
  • 56
  • 89