【问题标题】:Confusion matrix across multiple raters跨多个评估者的混淆矩阵
【发布时间】:2019-10-28 06:49:02
【问题描述】:
test_data <- data.frame(event= c("event1","event2","event3","event4","event5","event6","event7"),
                    rater1_1 = c("red", "orange", "red", "purple", "orange", "red", "yellow"),
                    rater2_1 = c("red", "orange", "orange", "purple", "orange", "red", "purple"),
                    rater3_1 = c("red", "red", "yellow", "purple", "orange", "red", "yellow"),
                    rater4_1 = c("orange", "orange", "blue", "orange", "orange", "red", "purple"), 
                    rater5_1 = c("blue", "blue", "purple", "orange", "orange", "blue", "yellow")
                    )

使用上述数据,我正在尝试创建一个混淆矩阵,我可以在其中观察每个事件的所有评估者之间的分歧。也就是说,对于 event1,3 位评分者给出了“红色”、1 位“橙色”和 1 位“蓝色”。

我认为解决此问题的最佳方法是对每个评估者对进行比较(y 轴上的评估者 1 和 x 轴上的评估者 2),然后在所有评估者对中进行迭代和统计。

我希望得到如下所示的内容:

        red  orange  blue  yellow  purple
red      22    6      2      3      2
orange   6     13     1      4      1
blue     2     1      10     3      1
yellow   3     4      3      9      2
purple   2     1      1      2      9

(注意:这些数值都是编出来的,上面我没有手动统计)

我什至不知道从哪里开始。我搜索的大多数混淆矩阵都是将实际模型输出与预测模型输出进行比较(例如,link)。任何建议将不胜感激。

【问题讨论】:

  • 我不太确定这里使用的逻辑。也许使用示例数据来显示所需的输出。
  • 所需的输出将类似于我上面的表格。通常每个评估者对(对角线)的一致性很高,但有些分歧(非对角线)。

标签: r dplyr tidyr


【解决方案1】:

对于这个解决方案,我使用dplyrpurrr

library(dplyr)
library(purrr)
# convert to long format
df_long <- test_data %>% pivot_longer(-event)

# df_long
# # A tibble: 35 x 3
#   event  name     value 
#   <fct>  <chr>    <fct> 
# 1 event1 rater1_1 red   
# 2 event1 rater2_1 red   
# 3 event1 rater3_1 red   
# 4 event1 rater4_1 orange
# 5 event1 rater5_1 blue  
# 6 event2 rater1_1 orange
# 7 event2 rater2_1 orange
# 8 event2 rater3_1 red   
# 9 event2 rater4_1 orange
#10 event2 rater5_1 blue  
# # ... with 25 more rows

# create function to compute the confusion matrix for two given events
create_confusion_matrix <- function(raters){
 df_long %>% filter(name %in% raters) %>% 
             pivot_wider(names_from=name,values_from=value) %>% 
             select(-event) %>% 
             table()
}

# lets try this function with rater1_1 and rater2_1
create_confusion_matrix(c('rater1_1','rater2_1'))
#        rater2_1
#rater1_1 orange purple red yellow blue
#  orange      2      0   0      0    0
#  purple      0      1   0      0    0
#  red         1      0   2      0    0
#  yellow      0      1   0      0    0
#  blue        0      0   0      0    0


# now we need to get all combinations of two raters
raters2 <- combn(unique(df_long$name),2,simplify=FALSE)


# raters2 is a list, each element is a vector containing 2 raters

# loop over the list and apply create_confusion_matrix for each element
result_list <- map(raters2,create_confusion_matrix)
# result_list is a list, each element is a confusion matrix

#we can them sum all theses tables

contingency <- Reduce('+',result_list)
#        rater2_1
#rater1_1 orange purple red yellow blue
#  orange     14      1   2      1    5
#  purple      6      4   0      3    0
#  red         5      1   9      1    9
#  yellow      0      4   0      3    1
#  blue        0      1   0      0    0

# getting rid of rater1_1 and rater2_1 in dimnames
dimnames(contingency) <- list(dimnames(contingency)[[1]],dimnames(contingency)[[2]])
#       orange purple red yellow blue
#orange     14      1   2      1    5
#purple      6      4   0      3    0
#red         5      1   9      1    9
#yellow      0      4   0      3    1
#blue        0      1   0      0    0

# sum symmetric cells and make contingency table lower triangular
# first lets extract the diagonal
# diag is needed twice, first to extract the diagonal from contingency as a vector
# second to convert this vector to a diagonal matrix
diag_contingency <- diag(diag(contingency))
# sum lower and upper matrices by adding the transposed matrix
# and substracting the diagonal (otherwise added twice)
contingency <- contingency + t(contingency) - diag_contingency
# we know have a symmetrical matrix
#        orange purple red yellow blue
#orange     14      7   7      1    5
#purple      7      4   1      7    1
#red         7      1   9      1    9
#yellow      1      7   1      3    1
#blue        5      1   9      1    0

# set the upper triangular matrix to 0
contingency[upper.tri(contingency)] <- 0

# we get this matrix in the end
contingency
#           orange purple red yellow blue
#orange     14      0   0      0    0
#purple      7      4   0      0    0
#red         7      1   9      0    0
#yellow      1      7   1      3    0
#blue        5      1   9      1    0

【讨论】:

  • 太棒了。这非常接近......而不是比较事件,我需要比较评估者。例如,在create_confusion_matrix() 的测试中需要create_confusion_matrix(rater1_1, rater2_1) 并且结果看起来正确。我对事件之间的比较不感兴趣,就像我在评估者之间进行比较一样。我可以切换东西,但卡在combn() 行。在这里,我需要创建评分者的组合,而不是事件。
  • @b222 很高兴你找到了解决方案,我已经更新了我的答案
  • 抱歉耽搁了,pivot_wider 执行以下操作:从 names_from = name = 不同的评估者中获取所有唯一元素,并为每个评估者创建一列(我们只调用包含两个元素的函数评估者,因此将创建两列),values_from=value 参数告诉我们在这些列中放置什么,这里我们将获得评估者的实际评级。我会更新我对其他问题的回答
  • @b222,更新了答案,希望我回答了你所有的问题
  • 非常感谢。我感谢您的帮助和详细的解释。
猜你喜欢
  • 2021-08-27
  • 2016-08-25
  • 1970-01-01
  • 2021-03-17
  • 2020-12-30
  • 2018-03-01
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多