Last Object Carried Forward in columns that have lists in tibbles

113 views Asked by At

I am looking for a function to help fill elements of a column that contains lists with the prior value.

library(tidyverse)

test <- right_join(
data_frame (Numbers = c(1,3,5,10),
          LotsOflist = c(list(A=1),
                         list(B=2),
                         list(C=3),
                         list(D=4)
                         )),
data_frame(Numbers = 1:10))

test 

# A tibble: 10 × 2
      Numbers LotsOflist
       <dbl>     <list>
1        1  <dbl [1]>
2        2     <NULL>
3        3  <dbl [1]>
4        4     <NULL>
5        5  <dbl [1]>
6        6     <NULL>
7        7     <NULL>
8        8     <NULL>
9        9     <NULL>
10      10  <dbl [1]>

The column "LotsOfLists" has a few lists that are NULL due to the join. I want to have the NULL being replaced by the the last list. I would like it to work similar to na.locf() from the zoo packages that fills NA with the last object carried forward but could not find anything that works for columns that are Lists.

test2 <- data_frame(LotsOfNumbers = c(1,2,NA,NA,NA,7))
test2

# A tibble: 6 × 1
       LotsOfNumbers
            <dbl>
1             1
2             2
3            NA
4            NA
5            NA
6             7
library(zoo)

test2 %>% 
  mutate(LotsOfNumbers_Filled = na.locf(LotsOfNumbers))

# A tibble: 6 × 2
        LotsOfNumbers LotsOfNumbers_Filled
            <dbl>                <dbl>
1             1                    1
2             2                    2
3            NA                    2
4            NA                    2
5            NA                    2
6             7                    7

Edit:

The original questions was answered but it turns out that if the column has data.frames the answers don't work. Could anybody find a solution for data.frames?

 test <- right_join( data_frame (Numbers = c(1,3,5,10),
                            LotsOflist = c(list(data.frame(A=1)), 
                                           list(data.frame(B=2)), 
                                           list(data.frame(C=3)),
                                           list(data.frame(D=4)) )),
                data_frame(Numbers = 1:10)) 
2

There are 2 answers

2
G. Grothendieck On

na.locf works if the NULLs are replaced with NA values:

library(zoo)

test %>%
    mutate(LotsOflist = na.locf(replace(LotsOflist, sapply(LotsOflist, is.null), NA)))
0
Marco Blume On

The tidyr version of na.locf works with lists.

test %>% 
fill(LotsOflist)