每行最后一个非 NA 行的列名;使用 tidyverse 解决方案?
Column name of last non-NA row per row; using tidyverse solution?
数据集简要说明:我有从 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
还有其他一些相关问题,但我似乎找不到任何专注于提取列名的答案(相对于 ) based on a tibble of mixed variable classes (vs. all numeric),使用 tidyverse 解决方案
我一直在尝试的东西 - 我知道我在这里缺少一些东西...:[=17=]
ds %>% map(which(!is.na(.)))
ds %>%
map(tail(!is.na(.), 2))
ds %>%
rowwise() %>%
mutate(last = which(!is.na(ds)))
?
非常感谢您的帮助!
按照 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])
这里不处理没有答案的情况。
数据集简要说明:我有从 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
还有其他一些相关问题,但我似乎找不到任何专注于提取列名的答案(相对于
我一直在尝试的东西 - 我知道我在这里缺少一些东西...:[=17=]
ds %>% map(which(!is.na(.)))
ds %>% map(tail(!is.na(.), 2))
ds %>% rowwise() %>% mutate(last = which(!is.na(ds)))
?
非常感谢您的帮助!
按照 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])
这里不处理没有答案的情况。