Объединение нескольких матриц путаницы — участок плитки с прямоугольниками вместо плиток?

#r #ggplot2

Вопрос:

У меня есть несколько матриц путаницы, и я хочу их сравнить. Я подумал, что было бы здорово визуализировать самое высокое и самое низкое значение для каждой категории на одном графике. Я представляю себе что-то вроде этого (простите меня за уродливые каракули):

чего я хочу

Для каждой категории есть верхний прямоугольник, показывающий наибольшее значение во всех матрицах путаницы, нижний прямоугольник показывает наименьшее значение во всех матрицах путаницы. Цвет указывает, к какому набору данных относится прямоугольник.

Итак, как я могу этого достичь? Я подумал , что мог бы использовать его для работы geom_polygon() , но я никогда им не пользовался и представляю, что это довольно сложная работа. Есть ли способ, который позволил бы мне использовать geom_tile() , но использовать треугольники вместо прямоугольников? Я видел несколько ggplots с прямоугольниками, которые были горизонтально разделены на меньшие прямоугольники, поэтому я подумал, может быть, есть возможность сделать треугольники тоже?

Вот некоторые фиктивные данные:

 datasets <- c("Data Set 1", "Data Set 2", "Data Set 3", "Data Set 4")
df <- data.frame(
  "Truth" = c(rep(c("A","B","C","D"), 8)),
  "Prediction" = c(rep(c("A","B","C","D"), each = 8)),
  "Type" = c(rep(rep(c("min", "max"), each = 4), 4)),
  "Data_Set" = sample(datasets, 8*4, replace = TRUE),
  "Value" = round(runif(8*4)*100))
 

Создать один график на максимальное / минимальное значение было бы несложно. Например:

 ggplot(df[df$Type == "min",])  
  geom_tile(aes(x = Truth, y = Prediction, fill = Data_Set))  
  geom_text(aes(x = Truth, y = Prediction, label = Value))
 

введите описание изображения здесь

Но я ищу красивый способ объединить схему листов для максимального и минимального. Я также открыт для других идей. Я предполагаю, что многие люди хотели сравнить несколько матриц путаницы в одном сюжете до меня?

Ответ №1:

Я не могу придумать способ построения треугольников ggplot2 без определения их как многоугольников, что требует небольшого изменения формы данных. Если мы начнем с ваших исходных данных:

 datasets <- c("Data Set 1", "Data Set 2", "Data Set 3", "Data Set 4")

set.seed(2)

df <- data.frame(
  "Truth" = c(rep(c("A","B","C","D"), 8)),
  "Prediction" = c(rep(c("A","B","C","D"), each = 8)),
  "Type" = c(rep(rep(c("min", "max"), each = 4), 4)),
  "Data_Set" = sample(datasets, 8*4, replace = TRUE),
  "Value" = round(runif(8*4)*100))
 

Теперь получите координаты центра каждой плитки, преобразовав коэффициенты в числа, и добавьте столбец, в котором записан исходный номер строки:

 df$x <- as.numeric(factor(df$Truth))
df$y <- as.numeric(factor(df$Prediction))
df$observation <- seq(nrow(df))
 

Теперь сделайте три копии каждой строки:

 df <- df[rep(seq(nrow(df)), each = 3),]
 

И мы можем вычислить координаты вершин треугольников:

 polyxmin <- df$x   c(-0.5, 0.5, 0.5)
polyxmax <- df$x   c(-0.5, -0.5, 0.5)
polyymin <- df$y   c(-0.5, -0.5, 0.5)
polyymax <- df$y   c(-0.5, 0.5, 0.5)

df$polyx <- numeric(nrow(df))
df$polyx[df$Type == "min"] <- polyxmin[df$Type == "min"]
df$polyx[df$Type == "max"] <- polyxmax[df$Type == "max"]

df$polyy <- numeric(nrow(df))
df$polyy[df$Type == "min"] <- polyymin[df$Type == "min"]
df$polyy[df$Type == "max"] <- polyymax[df$Type == "max"]
 

И добавьте места для текста:

 df$x[df$Type == "min"] <- df$x[df$Type == "min"]   0.25
df$x[df$Type == "max"] <- df$x[df$Type == "max"] - 0.25
df$y[df$Type == "min"] <- df$y[df$Type == "min"] - 0.25
df$y[df$Type == "max"] <- df$y[df$Type == "max"]   0.25
 

Тогда мы сможем составить заговор с geom_polygon :

 ggplot(df)  
  geom_tile(aes(x = Truth, y = Prediction, fill = Data_Set))  
  geom_polygon(aes(x = polyx, y = polyy, group = observation, fill = Data_Set),
               color = "gray30")  
  geom_text(aes(x = x, y = y, label = Value), check_overlap = TRUE)  
  scale_fill_manual(values = c("#a7ca88", "#b4c7e7", "#f4b184", "#fdda65"))
  coord_equal()
 

введите описание изображения здесь

Комментарии:

1. Большое спасибо! Это действительно хорошее решение. Обработка полигонов заняла бы у меня целую вечность. Я попытался использовать циклы for для координат многоугольника, но заблудился в промежутке, пытаясь понять, как объединить мои данные и позиции многоугольника.