Широкий формат, приводящий к удвоению данных гистограммы в ggplot

В процессе создания наложенной гистограммы с данными в широком формате я заметил, что мои значения для гистограммы удваиваются.

Быстрое решение состояло в том, чтобы просто разделить значения на 2.

Но что именно происходит под капотом, из-за чего это происходит?

    # Data

status <- c("Infected","Not Infected")
female <- c(0.3,0.7)
male <- c(0.8,0.2)

# Colors

dark <- '#008AFE' # blue
lightest <-'#CCE8FF'
light_accent <-'#FFCB93' #peachy
lightest_accent <- '#FFE5C9'



df <- data.frame("Covid" = status,"female_perc" = female, "male_perc" = male)


gender_claim <- ggplot() +
  geom_col(data = df, 
           mapping= aes(x = c("Male"), y = male_perc[2]/2), 
           fill = light_accent, width = .25) +
  geom_col(data = df, 
           mapping= aes(x = c("Male"), y = male_perc[1]/2), 
           fill = lightest, width = .15) +
  scale_y_continuous(limits = c(0, 1), breaks = seq(0, 1, by = .25),
                     labels = function(y) paste0(round(y*100,0),"%"), 
                     seq(0, 1, by = .25),expand = expansion(mult = c(0, 0))) +
  geom_col(data = df, 
           mapping= aes(x = c("Female"), y = female_perc[2]/2), 
           fill = lightest_accent, width = .25) +
  geom_col(data = df, 
           mapping= aes(x = c("Female"), y = female_perc[1]/2), 
           fill = dark, width = .15) +
  coord_flip()
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
470
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

ggplot использует ваш фрейм данных. Когда вы используете geom_col(data = df, ...), geom_col попытается нарисовать геометрию для каждой строки df. Вы явно устанавливаете, что x = "Male" и y male_perc[2]/2, и эти отдельные значения будут перерабатываться для каждой строки фрейма данных.

Это то же самое, что:

ggplot(data = data.frame(x = c(1, 2, 3, 4)) +
  geom_line(aes(x = x, y = 1))

Я даю ggplot фрейм данных с 4 строками. Я говорю это y = 1, поэтому значение y1 перерабатывается и применяется ко всем 4 рядам. Ваши x = "Male" и y = male_perc[2]/2 будут переработаны во всех двух строках данных.

По умолчанию geom_col будет накладывать перекрывающиеся значения друг на друга. Так вот как ваши данные удваиваются.

Лучше, чем делить на 2, вы можете использовать position = "identity", чтобы ничего не складывалось. Более того, поместите свои данные в длинный формат и используйте эстетические сопоставления.

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

Чтобы расширить поясняющий ответ от Грегора Томаса, вот пример того, как повернуть ваши данные и построить их:

df %>%
  pivot_longer(
    -Covid,
    values_to = "fraction",
    names_to = c("sex", "type"),
    names_sep = "_"
  ) %>%
  ggplot(aes(x = sex, y = fraction, fill = Covid)) +
  geom_col(position = "dodge")

Здесь pivot_longer берет информацию о поле, встроенную в имена столбцов вашего исходного data.frame, и делает их доступными для ggplot в качестве переменной, чтобы вы могли программно получить к ним доступ и заставить свой график реагировать на них.

ОБНОВЛЯТЬ:

«Аккуратное» решение с более ручным управлением эстетикой каждого бара для достижения желаемого внешнего вида:

df %>%
  pivot_longer(
    -Covid,
    values_to = "fraction",
    names_to = c("sex", "type"),
    names_sep = "_"
  ) %>%
  arrange(desc(Covid)) %>%
  ggplot(aes(x = sex, y = fraction, group = Covid)) +
  geom_col(position = "identity", aes(width = rep(c(0.25, 0.15), each = 2), fill = letters[1:4]), alpha = 1) +
  scale_fill_manual(values = c(lightest_accent, light_accent, dark, lightest)) +
  scale_y_continuous(limits = c(0, 1), breaks = seq(0, 1, by = .25),
                     labels = function(y) paste0(round(y*100,0),"%"), 
                     seq(0, 1, by = .25),expand = expansion(mult = c(0, 0))) + 
  theme(legend.position = "none") +
  coord_flip()

Обратите внимание, что здесь вызов arrange строит полосу в нужном порядке, поэтому последние в data.frame отображаются последними и идут вверху. width и fill необходимо установить вручную, чтобы они соответствовали желаемому порядку.

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

Bjc51192 14.12.2020 23:15

@Bjc51192 Bjc51192 - Только что обновил свой ответ с некоторыми изменениями, чтобы он выглядел как ваш оригинал. Конечно, чтобы получить такой уровень ручного управления, код становится немного громоздким, но я думаю, что он все же значительно более удобочитаем, удобен в сопровождении и обобщаем, чем оригинал.

Dan Adams 14.12.2020 23:56

На самом деле я сделал это немного иначе, используя фильтрацию. Но твой ответ помог.

Bjc51192 14.12.2020 23:57

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