dule arnaux
dule arnaux

Reputation: 3800

Fill missing values in data.frame across columns

Normally people want to fill missing values up or down a column. I would like to fill across, left or right.

# all character data.frame, except 1st column
df <- data.frame(a = 1:4, 
                 b = c('row1', 'row2', 'row3', 'row4'),
                 c = paste(9:12),
                 d = paste(13:16))
# remove a few values
df[2,2] <- df[3,3] <- df[4,2] <- NA

> df
  a    b    c  d
1 1 row1    9 13
2 2 <NA>   10 14
3 3 row3 <NA> 15
4 4 <NA>   12 16

# fill down. This is straighforward and works as expected.
df%>%fill(names(.), .direction='down')


How do I fill across???

# this doesn't work
df%>%fill(names(.), direction='right')

Lets assume we coerce to character if the fill value does not match the type of the missing value. But only for the columns that require coercion. So column a should stay numeric

Upvotes: 0

Views: 1175

Answers (2)

arg0naut91
arg0naut91

Reputation: 14764

This would be the equivalent of the right variant:

library(tidyverse)

df %>% 
  rowid_to_column %>% 
  gather(key, val, -rowid) %>% 
  arrange(rowid) %>%
  fill(val) %>% 
  spread(key, val) %>% select(-rowid)

Basically you can turn the data into long format and then use fill.

Direction down is then equivalent to right and direction up equivalent to left if you use the code above.

Output:

  a    b    c  d
1 1 row1    9 13
2 2    2   10 14
3 3 row3 row3 15
4 4    4   12 16

Here the attributes are dropped, and you'd need to re-establish the type of column you want.

Upvotes: 1

Dan
Dan

Reputation: 12074

This solution transposes the data frame, fills down, then transposes back again. The transposition converts the data frame to a matrix, so requires that it is converted back.

df <- data.frame(a = 1:4, 
                 b = c('row1', 'row2', 'row3', 'row4'),
                 c = paste(9:12),
                 d = paste(13:16))
# remove a few values
df[2,2] <- df[3,3] <- df[4,2] <- NA

library(tidyverse)

t(df) %>% 
  as.data.frame %>% 
  fill(names(.),.direction = "down") %>% 
  t %>% 
  as.data.frame
#>    a    b    c  d
#> V1 1 row1    9 13
#> V2 2    2   10 14
#> V3 3 row3 row3 15
#> V4 4    4   12 16

Created on 2019-02-08 by the reprex package (v0.2.1.9000)

Upvotes: 0

Related Questions