我将使用罗兰选择的“分数”。由于您提到可以将分数表更改为 2x2 矩阵,因此我提供了以下解决方案,该解决方案与其他 2 个解决方案的不同之处在于分数的数据结构不同。
在为您提供代码之前,请允许我解释一下逻辑:
- 我希望逐行处理 df
- 对于每一行,我希望将分数用于每个问题选择的答案
- 我想总结一下
基于 2,我觉得需要一个关联数组,我可以根据问题编号和输入的答案对其进行索引。因此,我为分数创建了以下表示:
> scores <- list(
+ Q1 = list(A1=10,A2=20,A3=30),
+ Q2 = list(B1=30,B2=10,B3=20),
+ Q3 = list(C1=10,C2=30,C3=20)
+ )
基本上,分数现在是一个列表列表。通过这样做,我可以执行以下操作:
> scores[["Q1"]][["A1"]]
[1] 10
现在我需要做的就是找出一种方法来参数化上面的“Q1”和“A1”。
数据框“df”如下:
> df
ID Q1 Q2 Q3
1 1 A1 B2 C3
2 2 A2 B1 C2
3 3 A1 B2 C3
我关心的是没有 ID 列的每一行。所以,我只提取:
> df[1,-1]
Q1 Q2 Q3
1 A1 B2 C3
现在你可以看到我需要选择第一个索引的列名到分数和第二个索引的行中的值。因此,如果我能得到 score[[column-M]][[row-NvalueForColumn-M]] 那么我可以总结它们。
列名很容易获得,因此:
> columnNames <- colnames(df[1,-1])
> columnNames
[1] "Q1" "Q2" "Q3"
所以你做必要逻辑的最后一段代码是这样的:
> columnNames <- colnames(df[1,-1])
> score <- c(0,0,0)
> for (i in 1:length(df[1,-1]))
+ {
+ for (j in 1:length(columnNames))
+ {
+ score[i] <- score[i] + scores[[columnNames[j]]][[df[i,-1][[columnNames[j]]]]]
+ }
+ }
> final <- cbind(df,score)
> final
ID Q1 Q2 Q3 score
1 1 A1 B2 C3 40
2 2 A2 B1 C2 80
3 3 A1 B2 C3 40
>
我相信上面的代码可以减少至少 5 行(使用 rowsums 等)。我确信像 Sven 这样有经验的人可以将上面的代码改进到几行。将不胜感激输入。