我需要迭代数据帧中的一对列。每列都有一个带有“_ans”后缀(和相同前缀)的相应列。如果“_ans”列和比较列相等,我需要创建带有后缀“_score”的新列。
可重复的例子:
set.seed(42)
df <- as.data.frame(matrix(sample(1:9, 10 * 5, replace = TRUE),
ncol = 10, dimnames = list(NULL, c("CB1", "LB2", "CW3", "WC1",
"LW20", "CB1_ans", "LB2_ans", "CW3_ans", "WC1_ans", "LW20_ans"))))
> df
CB1 LB2 CW3 WC1 LW20 CB1_ans LB2_ans CW3_ans WC1_ans LW20_ans
1 3 9 6 9 1 7 3 2 5 1
2 3 3 4 2 5 1 3 7 4 4
3 7 7 7 1 7 6 4 6 3 4
4 5 8 7 5 2 6 2 7 2 3
5 6 3 3 2 3 1 9 9 1 4
如果我手动执行此操作,它将如下所示:
df$CB1_score <- df$CB1 == df$CB1_ans
df$LB2_score <- df$LB2 == df$LB2_ans
df$CB3_score <- df$CW3 == df$CW3_ans
结果输出:
CB1 LB2 CW3 WC1 LW20 CB1_ans LB2_ans CW3_ans WC1_ans LW20_ans CB1_score LB2_score CB3_score
1 3 9 6 9 1 7 3 2 5 1 FALSE FALSE FALSE
2 3 3 4 2 5 1 3 7 4 4 FALSE TRUE FALSE
3 7 7 7 1 7 6 4 6 3 4 FALSE FALSE FALSE
4 5 8 7 5 2 6 2 7 2 3 FALSE FALSE TRUE
5 6 3 3 2 3 1 9 9 1 4 FALSE FALSE FALSE
等等。我已经研究了一个小时试图找到一种方法来自动化这个没有for循环,但不能想到正确的方法。
答案 0 :(得分:2)
以下是使用tidyverse
的{{1}}解决方案:
purrr:map
答案 1 :(得分:1)
一个基础R解决方案:
nms <- colnames(df)
ans <- nms[grepl("_ans$", nms)]
qstn <- gsub("_ans$", "", ans)
# in case there's something wrong with the names??
ans <- ans[ qstn %in% nms ]
qstn <- qstn[ qstn %in% nms ]
scores <- df[qstn] == df[ans]
colnames(scores) <- paste0(qstn, "_score")
cbind(df, scores)
# CB1 LB2 CW3 WC1 LW20 CB1_ans LB2_ans CW3_ans WC1_ans LW20_ans CB1_score LB2_score CW3_score
# 1 9 5 5 9 9 5 7 8 4 9 FALSE FALSE FALSE
# 2 9 7 7 9 2 4 8 1 4 8 FALSE FALSE FALSE
# 3 3 2 9 2 9 9 4 2 1 6 FALSE FALSE FALSE
# 4 8 6 3 5 9 5 7 9 9 9 FALSE FALSE FALSE
# 5 6 7 5 6 1 8 1 6 4 6 FALSE FALSE FALSE
# WC1_score LW20_score
# 1 FALSE TRUE
# 2 FALSE FALSE
# 3 FALSE FALSE
# 4 FALSE TRUE
# 5 FALSE FALSE
答案 2 :(得分:1)
一个基本的R选项是迭代数据框中的所有列,不在_ans
中结束,然后将它们与_ans
进行比较同行。我们可以在此处使用grepl
和sapply
:
cols <- names(df)[grepl("^(?!.*_ans).*$", names(df), perl=TRUE)]
for (name in cols) {
df[paste0(name, "_score")] <- df[[name]] == df[[paste0(name, "_ans")]]
}
df
CB1_score LB2_score CW3_score WC1_score LW20_score
1 FALSE FALSE FALSE FALSE TRUE
2 FALSE FALSE FALSE FALSE FALSE
3 FALSE FALSE FALSE FALSE FALSE
4 FALSE FALSE FALSE FALSE TRUE
5 FALSE FALSE FALSE FALSE FALSE