Уменьшение размера легенды

У меня есть набор данных в следующем формате:

heights <- rnorm(10000, mean=170, sd=10) 
weights <- rnorm(10000, mean=65, sd=15) 

data <- data.frame(heights, weights)
   heights  weights
1 164.0554 75.21385
2 167.8416 80.20245
3 170.8382 64.86342
4 175.3897 73.40080
5 177.6491 42.82188
6 169.2133 79.28145

Я использовал следующий код R, чтобы подсчитать, сколько точек данных содержится в каждом интервале размером 5x5:

max_height <- max(data$heights)
max_weight <- max(data$weights)

height_breaks <- seq(0, max_height, by=5)
weight_breaks <- seq(0, max_weight, by=5)

combinations <- expand.grid(height = seq_along(height_breaks)[-length(height_breaks)],
                            weight = seq_along(weight_breaks)[-length(weight_breaks)])

interval_label <- function(breaks, index) {
  paste0("(", breaks[index], "-", breaks[index + 1], ")")
}

combinations$height_interval <- mapply(interval_label, list(height_breaks), combinations$height)
combinations$weight_interval <- mapply(interval_label, list(weight_breaks), combinations$weight)

height_weight_boxes <- combinations[, c("height_interval", "weight_interval")]
 
count_points_in_box <- function(min_height, max_height, min_weight, max_weight, data) {
    data %>%
        filter(height >= min_height, height <= max_height,
               weight >= min_weight, weight <= max_weight) %>%
        nrow()
}

  library(dplyr)
transformed_df <- height_weight_boxes %>%
    mutate(
        box_number = row_number(), 
        min_height = as.numeric(sub("\\((.*?)-.*", "\\1", height_interval)), 
        max_height = as.numeric(sub(".*-(.*)\\)", "\\1", height_interval)), 
        min_weight = as.numeric(sub("\\((.*?)-.*", "\\1", weight_interval)), 
        max_weight = as.numeric(sub(".*-(.*)\\)", "\\1", weight_interval)) 
    ) 

   count_points_in_box <- function(min_height, max_height, min_weight, max_weight, data) {
    data %>%
        filter(heights >= min_height, heights < max_height,
               weights >= min_weight, weights < max_weight) %>%
        nrow()
}

final <- transformed_df %>%
    rowwise() %>%
    mutate(count = count_points_in_box(min_height, max_height, min_weight, max_weight, data))

Отсюда я хочу сделать тепловую карту этих данных:

library(ggplot2)
library(viridisLite)

distinct_counts <- length(unique(final$count))

color_palette <- magma(distinct_counts)

final$color <- factor(final$count)

ggplot(final, aes(x = min_weight, y = min_height, fill = final$color)) +
    geom_tile() +
    scale_fill_manual(values = color_palette, guide = guide_legend(title = "Count")) +
    labs(x = "Minimum Weight", y = "Minimum Height", title = "2D Heatmap of Counts") +
    theme_minimal() +
    theme(legend.position = "right")

Все выглядит хорошо, но кажется, что в легенде показаны все возможные комбинации цветов, и она выглядит очень длинной. Я пытаюсь уменьшить размер легенды и сделать ее более компактной. Можно ли уменьшить размер этой легенды, «объединив» цвета в одинаковых диапазонах?

Я знаю, что можно напрямую создать тепловую карту в R, используя такие функции, как kde(). Проблема в том, что мой реальный набор данных очень велик, и я фактически использую инструкции SQL CASE WHEN для выполнения подсчетов, а затем переношу агрегированный набор данных в R для создания тепловой карты (т. е. «окончательной»). Отсюда я вручную назначаю цвета и создаю тепловую карту. В этом вопросе, который я задал, длительная манипуляция с данными, которую я включил выше, представляет собой манипуляцию с данными SQL для приведения данных в «окончательный» формат.

Генерация операторов SQL в R:

sql_query <- "SELECT *, CASE"
for (i in 1:nrow(df)) {
  sql_query <- paste0(sql_query, " WHEN height BETWEEN ", df$min_height[i], " AND ", df$max_height[i],
                      " AND weight BETWEEN ", df$min_weight[i], " AND ", df$max_weight[i],
                      " THEN ", df$box_number[i])
}
sql_query <- paste0(sql_query, " END AS box_num FROM my_table;")

Вместо того, чтобы конвертировать ваши значения в коэффициент, вы можете рассматривать их как числовые, то есть использовать fill = count. Затем используйте непрерывную цветовую палитру viridis, например. ggplot2::scale_fill_viridis_c(option = "magma")

stefan 17.06.2024 08:39

Ответы находятся в разделе ответов ниже. Все посты должны быть в актуальном формате и не содержать лишнего шума.

Dharman 18.06.2024 15:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Scale_fill_binned() — это своего рода удобная и не очень гибкая функция, но вы можете использовать use Scale_fill_stepsn() для создания разделенных легенд:

# final$color <- factor(final$count)
breaks <- seq(min(final$count), max(final$count), length.out = 9)
n_breaks <- length(breaks) 
pal <- magma(n_breaks)


ggplot(final, aes(x = min_weight, y = min_height, fill = count)) +
  geom_tile() +
  # scale_fill_manual(values = color_palette, guide = guide_legend(title = "Count")) +
  labs(x = "Minimum Weight", y = "Minimum Height", title = "2D Heatmap of Counts") +
  scale_x_continuous(breaks = weight_breaks, labels = weight_breaks) +
  theme_minimal() +
  theme(legend.position = "right")+
  scale_fill_stepsn(breaks = breaks, colors = pal, values = scales::rescale(breaks, c(0, 1)))

Другие вопросы по теме