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