使用R中最近的右侧行值填充NA行值

时间:2017-01-03 06:55:49

标签: r dplyr na zoo

我想从

转换给定的数据帧
             c1     c2   c3   c4    c5
    VEG PUFF <NA>    12  <NA>  <NA> 78.43
CHICKEN PUFF <NA>    16  <NA>  88.24 <NA>
BAKERY Total <NA>   <NA>  28   <NA> 84.04

             c1     c2  
    VEG PUFF 12     78.43   
CHICKEN PUFF 16     88.24    
BAKERY Total 28     84.04

我尝试了两种方法,但我没有得到准确的结果,有时候采取左侧行值

step1 <-  t(na.locf(t(df), fromLast=T))
step2 <-  t(na.locf(t(step1), fromLast=F))

library(dplyr)
MyReplace = function(data) {data %>% t %>% na.locf(.,,T) %>% na.locf %>% t

2 个答案:

答案 0 :(得分:4)

<强>更新

由于预期输出存在很多混淆,请使用tidyverse解决方案更新@DavidArenburg建议的答案

library(dplyr)
library(tidyr)
df %>%
  add_rownames() %>%
  gather(variable, value, -rowname) %>%
  filter(!is.na(value)) %>%
  group_by(rowname) %>%
  mutate(indx = row_number()) %>%
  select(-variable) %>%
  spread(indx, value)

#        rowname   `1`   `2`
#*        <chr> <dbl> <dbl>
#1 BAKERY_Total    28 84.04
#2 CHICKEN_PUFF    16 88.24
#3     VEG_PUFF    12 78.43

另一种解决方案可能是

library(data.table)
temp <- apply(df, 1, function(x) data.frame(matrix(x[!is.na(x)], nrow = 1)))
rbindlist(temp, fill = T)

上一个答案

如果我理解正确,您尝试使用同一行中最新的非NA值替换行中的NA

我们可以na.locf使用fromLast设置为TRUE

t(apply(df, 1, function(x) na.locf(x, fromLast = T, na.rm = F)))


#             c1 c2    c3    c4    c5
#VEG_PUFF     12 12 78.43 78.43 78.43
#CHICKEN_PUFF 16 16 88.24 88.24    NA
#BAKERY_Total 28 28 28.00 84.04 84.04

答案 1 :(得分:2)

我们可以使用na.omit

t(apply(df, 1, na.omit))
#             [,1]  [,2]
#VEG PUFF       12 78.43
#CHICKEN PUFF   16 88.24
#BAKERY Total   28 84.04

更新

基于excel数据显示

lst <- apply(df, 1, na.omit)
df2 <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
row.names(df2) <- row.names(df)

或其他选项melt/dcast来自data.table

library(data.table)
dcast(melt(setDT(df1, keep.rownames=TRUE), id.var = 'rn', 
         na.rm = TRUE), rn~ paste0("c", rowid(rn)), value.var = "value")
#             rn c1    c2  c3
#1: BAKERY Total 28 84.04  NA
#2: CHICKEN PUFF 16 88.24 143
#3:     VEG PUFF 12 78.43  NA

提供可重复的例子,

df1 <- structure(list(c1 = c(NA, NA, NA), c2 = c(12L, 16L, NA), c3 = c(NA, 
NA, 28L), c4 = c(NA, 88.24, NA), c5 = c(78.43, 143, 84.04)), .Names = c("c1", 
"c2", "c3", "c4", "c5"), class = "data.frame", row.names = c("VEG PUFF", 
"CHICKEN PUFF", "BAKERY Total"))

lst <- lapply(seq_len(nrow(df1)), function(i) {
               x1 <- unlist(df1[i,])
               x1[complete.cases(x1)]})
df2 <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
row.names(df2) <- row.names(df1)

上述方法与apply方法类似,不同之处在于我们始终可以确保此输出list(在apply中 - 它可以变化。当元素数量时移除NA后,它们将相同,它将输出matrix,在其他情况下输出list)。因此,我们循环遍历行序列,移除NA元素,在末尾填充NA以使list元素的长度相同,然后rbind

或另一个选项which arr.ind=TRUE

ind <- which(!is.na(df), arr.ind=TRUE)
matrix(df[ind[order(ind[,1]),]], ncol=2, byrow=TRUE, 
            dimnames = list(row.names(df), paste0("c", 1:2)))
#             c1    c2
#VEG PUFF     12 78.43
#CHICKEN PUFF 16 88.24
#BAKERY Total 28 84.04