根据查找使用 dplyr 重新编码矩阵值 table
Recode matrix values with dplyr based on look-up table
我有一个包含大量案例和问卷相应答案的矩阵。下面的大幅简化示例 (raw_responses) 包含 5 个人对 5 个项目的答案。让我们假设这些是多项选择题,每个选项有 4 个可能的答案。如果该项目未被处理,此人将收到代码 9。
raw_responses <- data.frame('id' = 1:10,
'item_1' = sample(c(1:4,9), 10, replace = TRUE),
'item_2' = sample(c(1:4,9), 10, replace = TRUE),
'item_3' = sample(c(1:4,9), 10, replace = TRUE),
'item_4' = sample(c(1:4,9), 10, replace = TRUE),
'item_5' = sample(c(1:4,9), 10, replace = TRUE))
正确答案存储在反映整个测试设计的单独 table 中。下面又是一个大大简化的变体(设计),只有项目名称和相应的正确答案。
design <- data.frame('item' = c('item_1','item_2','item_3','item_4','item_5'),
'key' = sample(1:4, 5, replace = TRUE))
最后,目标是 table 得分答案。正确答案用 1 编码,错误答案用 0 编码,“空”答案用 99 编码。例如,这适用于下面的 for 循环。
scored_responses <- raw_responses
for(item in colnames(raw_responses)[2:6]) {
scored_responses[, item] <- ifelse(scored_responses[, item] == design[design$item == item, 'key'], 1,
ifelse(scored_responses[, item] == 9, 99, 0))
}
但是,我想知道这是否适用于 dplyr(包括 case_when)和可能的 purr 的更高效变体。特别是因为在更长的 dplyr-pipe 的帮助下清理了非常广泛的答案 table,如果可以在其中建立评分将是一个优势。
提前感谢您的所有想法和提示。
获取长格式数据,加入,重新编码值并获取宽格式数据。
library(dplyr)
library(tidyr)
raw_responses %>%
pivot_longer(cols = -id, names_to = 'item') %>%
left_join(design, by = 'item') %>%
mutate(value = case_when(value == 9 ~ 99,
value == key ~ 1,
TRUE ~ 0)) %>%
select(-key) %>%
pivot_wider(names_from = 'item')
# A tibble: 10 x 6
# id item_1 item_2 item_3 item_4 item_5
# <int> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 1 99 99 1 0 0
# 2 2 99 99 99 0 0
# 3 3 1 99 0 99 99
# 4 4 0 1 1 99 1
# 5 5 99 0 1 0 1
# 6 6 0 1 0 0 1
# 7 7 0 0 0 1 99
# 8 8 1 99 0 0 0
# 9 9 0 99 99 0 1
#10 10 99 1 99 1 0
另一种不将数据转换为宽格式的方法是使用 purrr
中的 map2_dfc
:
library(purrr)
map2_dfc(raw_responses[-1], design$key, ~case_when(.x == 9 ~ 99,
.x == .y ~ 1,
TRUE ~ 0))
但是,要使此答案生效,我们需要确保 raw_responses
和 design$item
中的列名顺序相同。在此示例中,它们已经处于相同的顺序,但是在真实数据中,如果它们不是,我们可以通过执行以下操作来实现:
raw_responses[-1] <- raw_responses[-1][design$key]
我有一个包含大量案例和问卷相应答案的矩阵。下面的大幅简化示例 (raw_responses) 包含 5 个人对 5 个项目的答案。让我们假设这些是多项选择题,每个选项有 4 个可能的答案。如果该项目未被处理,此人将收到代码 9。
raw_responses <- data.frame('id' = 1:10,
'item_1' = sample(c(1:4,9), 10, replace = TRUE),
'item_2' = sample(c(1:4,9), 10, replace = TRUE),
'item_3' = sample(c(1:4,9), 10, replace = TRUE),
'item_4' = sample(c(1:4,9), 10, replace = TRUE),
'item_5' = sample(c(1:4,9), 10, replace = TRUE))
正确答案存储在反映整个测试设计的单独 table 中。下面又是一个大大简化的变体(设计),只有项目名称和相应的正确答案。
design <- data.frame('item' = c('item_1','item_2','item_3','item_4','item_5'),
'key' = sample(1:4, 5, replace = TRUE))
最后,目标是 table 得分答案。正确答案用 1 编码,错误答案用 0 编码,“空”答案用 99 编码。例如,这适用于下面的 for 循环。
scored_responses <- raw_responses
for(item in colnames(raw_responses)[2:6]) {
scored_responses[, item] <- ifelse(scored_responses[, item] == design[design$item == item, 'key'], 1,
ifelse(scored_responses[, item] == 9, 99, 0))
}
但是,我想知道这是否适用于 dplyr(包括 case_when)和可能的 purr 的更高效变体。特别是因为在更长的 dplyr-pipe 的帮助下清理了非常广泛的答案 table,如果可以在其中建立评分将是一个优势。
提前感谢您的所有想法和提示。
获取长格式数据,加入,重新编码值并获取宽格式数据。
library(dplyr)
library(tidyr)
raw_responses %>%
pivot_longer(cols = -id, names_to = 'item') %>%
left_join(design, by = 'item') %>%
mutate(value = case_when(value == 9 ~ 99,
value == key ~ 1,
TRUE ~ 0)) %>%
select(-key) %>%
pivot_wider(names_from = 'item')
# A tibble: 10 x 6
# id item_1 item_2 item_3 item_4 item_5
# <int> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 1 99 99 1 0 0
# 2 2 99 99 99 0 0
# 3 3 1 99 0 99 99
# 4 4 0 1 1 99 1
# 5 5 99 0 1 0 1
# 6 6 0 1 0 0 1
# 7 7 0 0 0 1 99
# 8 8 1 99 0 0 0
# 9 9 0 99 99 0 1
#10 10 99 1 99 1 0
另一种不将数据转换为宽格式的方法是使用 purrr
中的 map2_dfc
:
library(purrr)
map2_dfc(raw_responses[-1], design$key, ~case_when(.x == 9 ~ 99,
.x == .y ~ 1,
TRUE ~ 0))
但是,要使此答案生效,我们需要确保 raw_responses
和 design$item
中的列名顺序相同。在此示例中,它们已经处于相同的顺序,但是在真实数据中,如果它们不是,我们可以通过执行以下操作来实现:
raw_responses[-1] <- raw_responses[-1][design$key]