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.
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)))))
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
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
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