【问题标题】:How to create R output likes confusion matrix table如何创建 R 输出喜欢混淆矩阵表
【发布时间】:2015-05-19 15:46:06
【问题描述】:

我有两个目录。第一个目录名为“model”,第二个目录名为“test”,两个目录下的文件列表相同,但内容不同。两个目录中的文件总数也相同,即 37 个文件。

我展示了其中一个文件的内容示例。

模型目录中的第一个文件

文件名:Model_A5B45

                               data
1  papaya | durian | orange | grapes
2                             orange
3                             grapes
4                    banana | durian
5                             tomato
6                     apple | tomato
7                              apple
8                        mangostine 
9                         strawberry
10                strawberry | mango

输入输出:

structure(list(data = structure(c(7L, 6L, 4L, 3L, 10L, 2L, 1L, 
5L, 8L, 9L), .Label = c("apple", "apple | tomato", "banana | durian", 
"grapes", "mangostine ", "orange", "papaya | durian | orange | grapes", 
"strawberry", "strawberry | mango", "tomato"), class = "factor")), .Names = "data", class = "data.frame", row.names = c(NA, 
-10L))

测试目录下的第二个文件

文件名:Test_A5B45

                               data
1                             apple
2            orange | apple | mango
3                             apple
4                            banana
5                            grapes
6                            papaya
7                            durian
8 tomato | orange | papaya | durian

输入输出:

structure(list(data = structure(c(1L, 5L, 1L, 2L, 4L, 6L, 3L, 
7L), .Label = c("apple", "banana", "durian", "grapes", "orange | apple | mango", 
"papaya", "tomato | orange | papaya | durian"), class = "factor")), .Names = "data", class = "data.frame", row.names = c(NA, 
-8L))

我想计算目录 test 中的文件与目录模型中的文件相交和除外数据的百分比。

这是我的代码示例,仅适用于两个文件(Model_A5B45 和 Test_A5B45)。

library(dplyr)

data_test <- read.csv("Test_A5B45")
data_model <- read.csv("Model_A5B45")
intersect <- semi_join(data_test,data_model)
except <- anti_join(data_test,data_model)
except_percentage <- (nrow(except)/nrow(data_test))*100
intersect_percentage <- (nrow(intersect)/nrow(data_test))*100
sprintf("%s/%s",intersect_percentage,except_percentage) 

输出:"37.5/62.5"

我的问题是,我想对所有文件(在两个目录中循环)实现我的代码,所以输出看起来像混淆矩阵。

我的预期输出示例:

##             y
##              Model_A5B45       Model_A6B46    Model_A7B47
##   Test_A5B45     37.5/62.5          value         value
##   Test_A6B46      value             value         value
##   Test_A7B47      value             value         value

我的回答:

我已经创建了可以处理这些东西的代码,但我仍然不知道如何使输出看起来像混淆矩阵。

这是我的代码:(我不知道这是否有效,我使用for循环)

f_performance_testing <- function(data_model_path, data_test_path){
  library(dplyr)
  data_model <- read.csv(data_model_path, header=TRUE)
  data_test <- read.csv(data_test_path, header=TRUE)
  intersect <- semi_join(data_test,data_model)
  except <- anti_join(data_test,data_model)
  except_percentage <- (nrow(except)/nrow(data_test))*100
  intersect_percentage <- (nrow(intersect)/nrow(data_test))*100

  return(list("intersect"=intersect_percentage,"except"=except_percentage))
}


for (model in model_list){
  for (test in test_list){
    result <- f_performance_testing(model,test)
    intersect_percentage <- round(result$intersect,3)
    except_percentage <- round(result$except,3)
    final_output <- sprintf("intersect : %s | except : %s",intersect_percentage,except_percentage) 
    cat(print(paste(substring(model,57),substring(test,56), final_output,sep=",")),file="outfile.txt",append=TRUE,"\n")
    print("Writing to file.......")
  }
}

输出是:

Model_A5B45,Test_A5B45, 37.5/62.5 
Model_A5B45,Test_A6B46, value
Model_A5B45,Test_A7B47, value
Model_A6B46,...... 
Model_A7B47,.....
...............
......
....

如何将此输出转换为看起来像混淆矩阵表?

【问题讨论】:

  • 你为什么不把你的 dplyr 方法转换成一个函数呢?然后您可能只使用sapply 或其中一个函数来生成矩阵。

标签: r for-loop dataframe plyr dplyr


【解决方案1】:

这不会直接回答您的问题,但希望为您提供足够的信息以得出您自己的解决方案。

我建议创建如下函数:

myFun <- function(model, test, datasource) {
  model <- datasource[[model]]
  test <- datasource[[test]]
  paste(rev(mapply(function(x, y) (x/y)*100, 
                   lapply(split(test, test %in% model), length), 
                   length(test))), 
        collapse = "/")
}

此函数将与两列 data.frame 一起使用,其中列代表“测试”和“模型”的所有组合(为什么要使用 data.frame 结构当一个字符vector 就足够了?)

下面是这样一个data.frame 的示例(其他示例数据在答案末尾找到)。

models <- c("model_1", "model_2", "model_3")
tests <- c("test_1", "test_2", "test_3")
A <- expand.grid(models, tests, stringsAsFactors = FALSE)

接下来,为您的模型和测试创建一个名为 list 的名称。如果您已经使用lapply 读取了您的数据,那么您很可能仍然可以使用名称。

dataList <- mget(c(models, tests))

现在,计算相关值。在这里,我们可以使用apply循环遍历每一行并进行相关计算。

A$value <- apply(A, 1, function(x) myFun(x[1], x[2], dataList))

最后,您reshape 将数据从“长”表单转换为“宽”表单。

reshape(A, direction = "wide", idvar = "Var1", timevar = "Var2")
#      Var1 value.test_1 value.test_2 value.test_3
# 1 model_1        75/25          100        75/25
# 2 model_2        50/50        50/50    62.5/37.5
# 3 model_3    62.5/37.5        50/50    87.5/12.5

这是一些示例数据。请注意,它们是基本字符向量,而不是 data.frames。

set.seed(1)
sets <- c("A", "A|B", "B", "C", "A|B|C", "A|C", "D", "A|D", "B|C", "B|D")

test_1 <- sample(sets, 8, TRUE)
model_1 <- sample(sets, 10, TRUE)
test_2 <- sample(sets, 8, TRUE)
model_2 <- sample(sets, 10, TRUE)
test_3 <- sample(sets, 8, TRUE)
model_3 <- sample(sets, 10, TRUE)

在现实世界的应用程序中,您可能会执行以下操作:

testList <- lapply(list.files(path = "path/to/test/files"),
                   function(x) read.csv(x, stringsAsFactors = FALSE)$data)
modelList <- lapply(list.files(path = "path/to/model/files"),
                   function(x) read.csv(x, stringsAsFactors = FALSE)$data)
dataList <- c(testList, modelList)

但是,这纯粹是我的猜测,基于您在问题中作为工作代码(例如,没有文件扩展名的 csv 文件)共享的内容。

【讨论】:

  • 感谢 Ananda Mahto 的长篇解释,它让我更了解 lapply 等,我修改了我的问题,我创建了可以给出正确结果的代码,但我需要转换我的输出更具可读性(看起来像混淆矩阵表),你知道吗,怎么做?谢谢
  • @user46543,关于您的问题更新,这就是 reshape 步骤的用途。假设你在“outfile.txt”中读到yourDataSet &lt;- read.csv("outfile.txt", header = FALSE, stringsAsFactors = FALSE),试试reshape(yourDataSet, direction = "wide", idvar = "V2", timevar = "V1")
猜你喜欢
  • 2021-03-02
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-08
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
相关资源
最近更新 更多