【问题标题】:Column name of last non-NA row per row; using tidyverse solution?每行最后一个非 NA 行的列名;使用 tidyverse 解决方案?
【发布时间】:2018-09-03 21:23:57
【问题描述】:

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

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

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

  • 1) 一个新列 (lastq) 列出每一行(即每个参与者)的最后一个非 NA 列的名称(即他们完成的最后一个问题的名称)。
  • 2) 第二个新列列出了 lastq 中的列号

示例数据帧 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

还有一些其他相关问题,但我似乎找不到任何专注于基于混合变量类(vs.all numeric)提取列名(vs.the values themselves)的答案,使用一个tidyverse解决方案

我一直在尝试的东西 - 我知道我在这里缺少一些东西......:

  • ds %&gt;% map(which(!is.na(.)))
  • ds %>% map(tail(!is.na(.), 2))
  • ds %>% rowwise() %>% mutate(last = which(!is.na(ds)))

?


非常感谢您的帮助!

【问题讨论】:

  • max(which(!is.na(ds)))?

标签: r dplyr na tidyverse tibble


【解决方案1】:

按照 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])

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

【讨论】:

  • 我不确定这是否遵循 idomatic tidyverse,考虑到使用 ifelse 代替 if_else、cbind 代替 bind_cols 等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-21
  • 2014-11-10
  • 2012-11-14
相关资源
最近更新 更多