如何创建 R 输出喜欢混淆矩阵 table
How to create R output likes confusion matrix table
我有两个目录。第一个目录的名称为"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
dput输出:
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
dput输出:
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 中的文件的交叉和排除数据的百分比。
这是我的代码示例,仅适用于两个文件(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,.....
...............
......
....
如何将此输出转换为看起来像混淆矩阵 table?
这不会直接回答您的问题,但希望能为您提供足够的信息以得出您自己的解决方案。
我建议创建如下函数:
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
一起使用,其中列表示 "test" 和 "model" values[=48] 的所有组合=](当字符 vector
就足够时,为什么要使用 data.frame
结构?)
这里有一个这样的例子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
将数据从 "long" 表格转换为 "wide" 表格。
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.frame
s.
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 文件)。
我有两个目录。第一个目录的名称为"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
dput输出:
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
dput输出:
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 中的文件的交叉和排除数据的百分比。
这是我的代码示例,仅适用于两个文件(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,.....
...............
......
....
如何将此输出转换为看起来像混淆矩阵 table?
这不会直接回答您的问题,但希望能为您提供足够的信息以得出您自己的解决方案。
我建议创建如下函数:
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
一起使用,其中列表示 "test" 和 "model" values[=48] 的所有组合=](当字符 vector
就足够时,为什么要使用 data.frame
结构?)
这里有一个这样的例子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
将数据从 "long" 表格转换为 "wide" 表格。
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.frame
s.
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 文件)。