每行最后一个非 NA 行的列名;使用 tidyverse 解决方案?

Column name of last non-NA row per row; using tidyverse solution?

数据集简要说明:我有从 Qualtrics 生成的调查数据,我已将其作为 tibble 导入到 R 中。每列对应一个调查问题,我保留了原来的列顺序(以对应调查中问题的顺序)。

通俗易懂的问题:由于正常的参与者流失,并非所有参与者都完成了调查中的所有问题。我想知道每个参与者在调查中走了多远,以及他们在停止之前回答的最后一个问题。

R 中的问题陈述: 我想生成(使用 tidyverse):


示例数据帧 df

df <- tibble(
  year = c(2015, 2015, 2016, 2016),
  grade = c(1, NA, 1, NA),
  height = c("short", "tall", NA, NA),
  gender = c(NA, "m", NA, "f")
 )

原df

  # A tibble: 4 x 4
   year grade height gender
  <dbl> <dbl>  <chr>  <chr>
1  2015     1  short   <NA>
2  2015    NA   tall      m
3  2016     1   <NA>   <NA>
4  2016    NA   <NA>      f

期望的最终 df

   # A tibble: 4 x 6
   year grade height gender  lastq lastqnum
  <dbl> <dbl>  <chr>  <chr>  <chr>    <dbl>
1  2015     1  short   <NA> height        3
2  2015    NA   tall      m gender        4
3  2016     1   <NA>   <NA>  grade        2
4  2016    NA   <NA>      f gender        4

还有其他一些相关问题,但我似乎找不到任何专注于提取列名的答案(相对于 ) based on a tibble of mixed variable classes (vs. all numeric),使用 tidyverse 解决方案

我一直在尝试的东西 - 我知道我在这里缺少一些东西...:[=​​17=]

?


非常感谢您的帮助!

按照 James 的建议编写一个解决问题的函数,但更稳健一点(处理所有答案都为 NA 的情况)

f0 = function(df) {
    idx = ifelse(is.na(df), 0L, col(df))
    apply(idx, 1, max)
}

L 使 0 成为整数,而不是数字。为了提高速度(当有很多行时),使用 matrixStats 包

f1 = function(df) {
    idx = ifelse(is.na(df), 0L, col(df))
    matrixStats::rowMaxs(idx, na.rm=TRUE)
}

按照 markus 的建议在 dplyr 上下文中使用它

mutate(df, lastqnum = f1(df), lastq = c(NA, names(df))[lastqnum + 1])
df %>% mutate(lastqnum = f1(.), lastq = c(NA, names(.))[lastqnum + 1])

或者直接去做

lastqnum = f1(df)
cbind(df, lastq=c(NA, names(df))[lastqnum + 1], lastqnum)

接受后编辑我想整洁的方法是先把数据整理成长格式

df1 = cbind(gather(df), id = as.vector(row(df)), event = as.vector(col(df)))

然后分组总结

group_by(df1, id) %>%
    summarize(lastq = tail(event[!is.na(value)], 1), lastqname = key[lastq])

这里不处理没有答案的情况。