向上移动行以填充 NA

move rows up to fill NAs

我不确定我是否可以很好地描述我想做的事情。 我从实验中获得的数据文件如下所示

variable1 variable2 variable 3 variable4
23         1         NA         NA
23         0         NA         NA
23         0         NA         NA
23         NA        4          NA
23         NA        3          NA
23         NA        NA         5
23         NA        NA         7
23         NA        NA         1
23         NA        NA         3 
24         1         NA         NA
24         1         NA         NA
24         NA        8          NA
24         NA        3          NA
24         NA        NA         2
24         NA        NA         1    

有点像楼梯。唯一从下到上填充的列是具有参与者 ID 的第一列。其他的按它们在实验中出现的顺序排列(变量 2 的三个问题,然后变量 3 的两个问题和变量 4 的四个问题)。

我想要的是摆脱这些 NA(空字段)并得到类似这样的东西:

variable1 variable2 variable3 variable4
23        1         4         5
23        0         3         7
23        0         NA        1
23        NA        NA        3
24        1         8         2
24        1         3         1 

这可以通过重塑来完成吗?任何解决方案表示赞赏

library(tidyverse)
df %>%
  pivot_longer(-variable1) %>% 
  drop_na() %>% 
  group_by(name) %>%
  mutate(grp = seq(n())) %>%
  pivot_wider(c(grp, variable1)) %>%
  select(-grp)

# A tibble: 4 x 4
  variable1 variable2 variable3 variable4
      <int>     <int>     <int>     <int>
1        23         1         4         5
2        23         0         3         7
3        23         0        NA         1
4        23        NA        NA         3

如果你没有 pivot_longer/pivot_wider 你可以使用 gather/spread:

df %>%
   gather(name,values,-variable1) %>% 
   drop_na() %>% 
   group_by(name) %>%
   mutate(grp = seq(n()))%>%
   spread(name,values)%>%
   select(-grp)
# A tibble: 4 x 4
  variable1 variable2 variable3 variable4
      <int>     <int>     <int>     <int>
1        23         1         4         5
2        23         0         3         7
3        23         0        NA         1
4        23        NA        NA         3

在 BASE R 中你可以这样做:

(array(df[cbind(c(sapply(df,order)),c(col(df)))],dim(df))->a)[rowSums(!is.na(a))>1,]
     [,1] [,2] [,3] [,4]
[1,]   23    0    3    1
[2,]   23    0    4    3
[3,]   23    1   NA    5
[4,]   23   NA   NA    7

甚至:

df1 <- transform(na.omit(cbind(df[1],stack(df[-1]))),time = ind, ind = ave(values,ind,FUN=seq_along))
reshape(df1, v.names = "values", dir="wide", idvar = c("variable1","ind"))
   variable1 ind values.variable2 values.variable3 values.variable4
1         23   1                1                4                5
2         23   2                0                3                7
3         23   3                0               NA                1
27        23   4               NA               NA                3