【问题标题】:How to calculate accuracy based on predictor and true values in R如何根据 R 中的预测变量和真实值计算准确度
【发布时间】:2019-05-20 15:21:28
【问题描述】:

我正在尝试根据正确响应(C 列)计算参与者响应(R 列)的准确性。一些数据以二进制形式(01010 - 例如参与者错误、正确、错误、正确、错误)和字母序列(即字母字符串中字母的正确位置)给出。

查看数据示例:

dput(example) 
structure(list(TRIAL = c("1", "2", "3", "4", "5", "6", "7", "8", 
"9", "10", "11", "12", "13", "14", "15"), EQ_C = c("0101", "1010", 
"1010", "00111", "01011", "01101", "100011", "010101", "001101", 
"0110011", "1101001", "1100101", "11100001", "11001010", "11001010"
), EQ_R = c("0101", "0010", "1010", "00111", "01011", "01101", 
"10101", "11010", "001101", "0100011", "1101001", "0100101", 
"11110001", "11001010", "11001010"), MEM_C = c("ZLHK", "RZKX", 
"DGWL", "BCJSP", "WRKTJ", "CHBXS", "HNDCWX", "SWVNDT", "WLDGPB", 
"DSHRKBV", "HCXLZWB", "HDNBVZC", "BCRHKVDM", "RVTBWKFS", "NWHVZFLD"
), MEM_R = c("ZLHK", "RZKX", "DGWL", "BCJSP", "WRKLTJ", "CHBXS", 
"HNDCWX", "SWVDTN", "WLDGPB", "DSHRKBV", "HCXLZWB", "HDNBVZC", 
"BCRHKVDM", "RVTBWKFS", "NWHVZFLD"), EQ_SUM = c(NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), MEM_SUM = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names             
 = c(NA, 
15L), class = "data.frame")

我为二进制数据 (EQ) 和字母 (MEM) 需要计算的“总和”/准确度分数添加了一个新列。

    OSPAN["EQ_SUM"] <- NA
    OSPAN["MEM_SUM"]<- NA

然后我尝试根据另一个 stackoverflow 线程(使用预测器和实际值)计算总和,但不知何故它无法识别我的变量。我怀疑我的数据格式有误,因为它一直告诉我找不到对象。

example$EQ_SUM <- round(100*rowMeans(EQ_C == EQ_R))

Error in is.data.frame(x) : object 'EQ_C' not found

我的问题是:如何将预测变量 (C) 和实际 (R) 值之间的准确性或一致性匹配/计算到总和列中?例如,在第 1 行中,EQ_SUM 为 1(或 100%),而在第 2 行中为 0.75 或 75%,因为参与者选择了错误的答案(0 而不是 1)。因此,给出了部分信用评分,这不是绝对匹配/一致的问题。

提前谢谢你。 (我希望我没有遗漏任何重要信息 - 这是我第一次发帖)。

【问题讨论】:

  • 您好,请使用dput 提供可用的数据样本,而不是图像。谢谢
  • 使用dput(head(YOUR_DATA, 20)) 之类的方式支持包含您的数据样本的请求,以便我们能够以您拥有的相同格式获取您的数据样本。还想知道在第 7 行这样EQ_C 的位数/字母数与EQ_R 不同的情况下您想做什么。
  • 有关衡量字符串之间差异的方法,请查看此内容,看看您在实施时是否有任何问题:github.com/markvanderloo/stringdist
  • @JonSpring 谢谢你的链接,我会试试看!我编辑了原始帖子并添加了我的数据样本。这也是我问自己的问题 - 想知道在参与者没有给出答案的情况下该怎么办,因此与 EQ_C 中的正确答案相比,EQ_R 中的答案更少。
  • @Jet 我提供了我的数据的摘录,我希望它可以正常工作/正确显示。 :)

标签: r statistics


【解决方案1】:

这是使用stringdist 包的方法。

library(stringdist)
library(dplyr)
example %>%
  mutate(EQ_RIGHT  = nchar(EQ_C) - stringdist(EQ_R, EQ_C, method = "lv"),
         EQ_SUM    = EQ_RIGHT / nchar(EQ_C),
         MEM_RIGHT = nchar(MEM_C) - stringdist(MEM_R, MEM_C, method = "lv"),
         MEM_SUM   = MEM_RIGHT / nchar(MEM_C))

'lv' 方法在这里看起来很合适,但还有其他选择。 Levenshtein 距离:将字符串 a 转换为字符串 b 所需的最少插入、删除和替换次数。

   TRIAL     EQ_C     EQ_R    MEM_C    MEM_R    EQ_SUM   MEM_SUM EQ_RIGHT MEM_RIGHT
1      1     0101     0101     ZLHK     ZLHK 1.0000000 1.0000000        4         4
2      2     1010     0010     RZKX     RZKX 0.7500000 1.0000000        3         4
3      3     1010     1010     DGWL     DGWL 1.0000000 1.0000000        4         4
4      4    00111    00111    BCJSP    BCJSP 1.0000000 1.0000000        5         5
5      5    01011    01011    WRKTJ   WRKLTJ 1.0000000 0.8000000        5         4
6      6    01101    01101    CHBXS    CHBXS 1.0000000 1.0000000        5         5
7      7   100011    10101   HNDCWX   HNDCWX 0.6666667 1.0000000        4         6
8      8   010101    11010   SWVNDT   SWVDTN 0.6666667 0.6666667        4         4
9      9   001101   001101   WLDGPB   WLDGPB 1.0000000 1.0000000        6         6
10    10  0110011  0100011  DSHRKBV  DSHRKBV 0.8571429 1.0000000        6         7
11    11  1101001  1101001  HCXLZWB  HCXLZWB 1.0000000 1.0000000        7         7
12    12  1100101  0100101  HDNBVZC  HDNBVZC 0.8571429 1.0000000        6         7
13    13 11100001 11110001 BCRHKVDM BCRHKVDM 0.8750000 1.0000000        7         8
14    14 11001010 11001010 RVTBWKFS RVTBWKFS 1.0000000 1.0000000        8         8
15    15 11001010 11001010 NWHVZFLD NWHVZFLD 1.0000000 1.0000000        8         8

【讨论】:

  • 我喜欢这种方法的简单性。尽管如此,尽管字符串距离方法的结果看起来与我提供的 check_accuracy 函数相似,但其基本概念不同,产生的结果也不同。
【解决方案2】:

计算预测与实际值的准确性的简单方法 - 或者在您的情况下参与者响应与实际响应 - 通常是执行以下操作:

mean(EC_C == EC_R, na.rm = TRUE)

其中 EC_C 和 EC_R 是包含要计算其准确性的值的列。您将收到一个介于 0 和 1 之间的值,后者表示 100% 准确度。请注意,在这种情况下,每对单元格可以相同也可以不同。上面计算的准确度将告诉您所有单元对中有多少百分比是相同的。如果您想比较每对单元格中的单个数字,这不是一种合适的方法 - 但现在我还不清楚您要做什么。

更新

您可以在下面找到一种可行的方法,但仅适用于 EC_CEC_R 具有相同字符数的行。如果受访者没有给出答案,并且没有记录数字/字符串中缺少哪个数字,则实际上无法计算准确度,因为不再清楚哪个数字/字符对应于哪个问题数字。所以我的方法的基本假设是,在一个四位数的字符串中,例如EC_C = 1010EC_R = 1000EC_C 中的第一个数字映射到EC_R 中的第一个数字。对于EC_C = 1010EC_R = 101,尚不清楚EC_R 中的哪个数字映射到EC_C 中的哪个数字。可以是左起前三位,准确度为 0.75,也可以是右起前三位,此时准确度为 0。

除了这个警告之外,我的方法应该适用于所有字符数相同的行(假设映射是一致的)。对于字符/数字数量不同的所有行,我的函数将生成NA。如果您想使用这种方法来评估学生考试的结果,那么您需要查看生成 NA 的每项考试,并找出遗漏的问题。如果你在答案被忽略的地方插入一个特殊字符,将来会为你省去很多麻烦。

library(stringr)
example <-
  structure(list(TRIAL = c("1", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "11", "12", "13", "14", "15"),
                 EQ_C = c("0101", "1010",
                          "1010", "00111", "01011", "01101", "100011", "010101", "001101",
                          "0110011", "1101001", "1100101", "11100001", "11001010", "11001010"),
                 EQ_R = c("0101", "0010", "1010", "00111", "01011", "01101",
                          "10101", "11010", "001101", "0100011", "1101001", "0100101",
                          "11110001", "11001010", "11001010"),
                 MEM_C = c("ZLHK", "RZKX", "DGWL", "BCJSP", "WRKTJ", "CHBXS", "HNDCWX", "SWVNDT",
                           "WLDGPB",  "DSHRKBV", "HCXLZWB", "HDNBVZC", "BCRHKVDM", "RVTBWKFS", "NWHVZFLD"),
                 MEM_R = c("ZLHK", "RZKX", "DGWL", "BCJSP", "WRKLTJ", "CHBXS",
                           "HNDCWX", "SWVDTN", "WLDGPB", "DSHRKBV", "HCXLZWB", "HDNBVZC",
                           "BCRHKVDM", "RVTBWKFS", "NWHVZFLD"),
                 EQ_SUM = c(NA, NA, NA, NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
                 MEM_SUM = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)),
            row.names = c(NA, 15L), class = "data.frame")

# Function to calculate accuracy
check_accuracy <- function(x,y) {

    # Calculate a matrix which checks if the position of a character in x is corresponding to position in y
    check_mtr = str_split_fixed(x, "", max(nchar(x))) == str_split_fixed(y, "", max(nchar(y)))

    # Calculate the sum of all matching positions
    accuracy_sum = rowSums(check_mtr)

    # Subtract the number of empty strings from accuarcy_sum
    accuracy_sum2 = accuracy_sum - (max(nchar(x)) - nchar(x))

    # Divide sum of all non-empty matching positions by number of non-empty characters
    accuracy_vec = accuracy_sum2 / nchar(x)

    if (any(nchar(x) != nchar(y))) {
    warning("Number of characters in x and y is not corresponding. NAs generated.")
    ifelse(nchar(x) != nchar(y), NA, accuracy_vec)
    } else {
    accuracy_vec
  }

}

example$EQ_SUM <- check_accuracy(example$EQ_C, example$EQ_R)
example$MEM_SUM <- check_accuracy(example$MEM_C, example$MEM_R)
example

更新 2: 请注意,在这种方法中计算的准确度与使用某种字符串距离度量的方法不同。这一点很清楚,当查看MEM_SUM 中第 8 行的结果时,即0.5,因为受访者只得到了一半的答案:比较SWVNDTSWVDTN,其中前三个答案@987654338 @对应,后三个不对应。然而,字符串距离的度量仍然认为最后三个字符是相关的(DTNNDT),因为字母相同,只是顺序不同。此处的字符串距离测量显示 0.67,这与 0.5 的精度不对应。此外,字符串距离方法还将评估忽略答案的响应(字符数不同的情况)。但是,如果不指明遗漏了哪个答案,就不可能进行明确的计算,这就是为什么我的方法在这里分配了一个NA 以及一条警告消息。

结果应该是这样的

   TRIAL     EQ_C     EQ_R    MEM_C    MEM_R    EQ_SUM MEM_SUM
1      1     0101     0101     ZLHK     ZLHK 1.0000000     1.0
2      2     1010     0010     RZKX     RZKX 0.7500000     1.0
3      3     1010     1010     DGWL     DGWL 1.0000000     1.0
4      4    00111    00111    BCJSP    BCJSP 1.0000000     1.0
5      5    01011    01011    WRKTJ   WRKLTJ 1.0000000      NA
6      6    01101    01101    CHBXS    CHBXS 1.0000000     1.0
7      7   100011    10101   HNDCWX   HNDCWX        NA     1.0
8      8   010101    11010   SWVNDT   SWVDTN        NA     0.5
9      9   001101   001101   WLDGPB   WLDGPB 1.0000000     1.0
10    10  0110011  0100011  DSHRKBV  DSHRKBV 0.8571429     1.0
11    11  1101001  1101001  HCXLZWB  HCXLZWB 1.0000000     1.0
12    12  1100101  0100101  HDNBVZC  HDNBVZC 0.8571429     1.0
13    13 11100001 11110001 BCRHKVDM BCRHKVDM 0.8750000     1.0
14    14 11001010 11001010 RVTBWKFS RVTBWKFS 1.0000000     1.0
15    15 11001010 11001010 NWHVZFLD NWHVZFLD 1.0000000     1.0

【讨论】:

  • 谢谢,我编辑了原始帖子并添加了示例数据并澄清了我要计算的内容。我已经尝试计算 Levenshtein 距离,因为它是加权的,但同样,这并没有给我一个相对准确度分数(即比较个位数而不是绝对一致性)。这有意义吗?
  • 我根据你的要求更新了答案。
猜你喜欢
  • 2013-10-04
  • 2018-11-04
  • 2012-07-10
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 2020-12-31
相关资源
最近更新 更多