Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compact a data frame by removing some of the NA cells?

If I have a data frame as follows:

data.frame(
  cola = c(3,NA,NA),
  colb = c(1,NA,NA),
  colc = c(NA,6,NA),
  cold = c(NA,7,NA),
  cole = c(NA,3,NA),
  colf = c(NA,NA,9), 
  colg = c(NA,NA,8)
)

How can I shift all fields to the left, eliminating NA values as needed, as here:

data.frame(
  cola = c(3,6,9),
  colb = c(1,7,8),
  colc = c(NA,3,NA)
)

Thanks for any help.

like image 302
FatBerg Avatar asked Aug 05 '18 19:08

FatBerg


3 Answers

We loop through the rows, remove the NA elements with na.omit and then append NA at the end based on the max length of the list

lst <- apply(df1, 1, na.omit)
out <- as.data.frame(do.call(rbind, lapply(lst, `length<-`, max(lengths(lst)))))
like image 101
akrun Avatar answered Sep 22 '22 02:09

akrun


Another option could be:

library(tidyverse)

df %>% rownames_to_column() %>%
    gather(measure, value, -rowname) %>%
    group_by(rowname) %>%
    na.omit() %>%
    mutate(measure = paste0("col", row_number())) %>%
    spread(measure, value) %>%
    ungroup() %>%
    select(-rowname)
#    col1  col2  col3
# 1     3     1    NA
# 2     6     7     3
# 3     9     8    NA
like image 25
AndS. Avatar answered Sep 20 '22 02:09

AndS.


You can transpose, drop NAs, transpose back:

library(magrittr)
library(data.table)

DF %>% transpose %>% lapply(na.omit) %>% transpose %>% 
  data.frame %>% setNames(names(DF)[seq_along(.)])

  cola colb colc
1    3    1   NA
2    6    7    3
3    9    8   NA
like image 33
Frank Avatar answered Sep 22 '22 02:09

Frank