首页 > 解决方案 > R:将多列移动不同的行数

问题描述

我有一个如下的小标题列表:

list(A = structure(list(
                        ID = c(1, 2, 3, 1, 2, 3, 1, 2, 3), 
                        g1 = c(0, 1, 2, NA, NA, NA, NA, NA, NA), 
                        g2 = c(NA, NA, NA, 3, 4, 5, NA, NA, NA), 
                        g3 = c(NA, NA, NA, NA, NA, NA, 6, 7, 8)), 
                   row.names = c(NA, -9L), 
                   class = c("tbl_df", "tbl", "data.frame")), 

     B = structure(list(ID = c(1, 2, 1, 2, 1, 2), 
                        g1 = c(10, 11, NA, NA, NA, NA), 
                        g2 = c(NA, NA, 12,13, NA, NA), 
                        g3 = c(NA, NA, NA, NA, 14, 15)), 
                   row.names = c(NA, -6L), 
                   class = c("tbl_df", "tbl", "data.frame"))
     )

每个元素如下所示:

  ID    g1    g2    g3
<dbl> <dbl> <dbl> <dbl>
  1     0    NA    NA
  2     1    NA    NA
  3     2    NA    NA
  1    NA     3    NA
  2    NA     4    NA
  3    NA     5    NA
  1    NA    NA     6
  2    NA    NA     7
  3    NA    NA     8

g* 列是在先前的变异期间动态创建的,它们的数量可能会有所不同,但在所有列表元素中都是相同的。

每个 g* 列只有某些非 NA 元素(与唯一 ID 一样多)。

我想移动 g* 列,使它们包含非 NA 元素到顶行。

我可以通过

num.shifts<- rle(is.na(myList[[1]]$g1))$lengths[1]
shift(myList[[1]]$g2,-num.shifts)

但是,当我事先不知道 g* 列的数量时,如何对所有 g* 列、所有列表元素执行此操作?

理想情况下,我想要一个 tidyverse 解决方案,但不是必需的......

谢谢!

标签: rdataframedplyr

解决方案


我们可以遍历listwith map,并用于mutate_at遍历matches'g' 后跟数字并order基于非 NA 元素的列

library(dplyr)
library(tidyr)
map(lst1, ~ 
       .x %>%
           mutate_at(vars(matches('^g\\d+')), ~ .[order(is.na(.))]))

base R,我们可以做

lapply(lst1, function(x) {i1 <- grepl("^g\\d+$", names(x))
                     x[i1] <- lapply(x[i1], function(y) y[order(is.na(y))])
                 x})

推荐阅读