Добавить горизонтальную линию в полосу Лайкерта ggplot

У меня есть объект ggplot с именем p:

library(dplyr, warn = FALSE)

likert_levels <- c(
  "Strongly disagree",
  "Disagree",
  "Neither agree nor disagree",
  "Agree",
  "Strongly agree"
)

df <-
  tibble(
    "there is an argument sort_prop_include_center that could be set up to TRUE in order to include half of the centered level when sorting data" = sample(likert_levels, 150, replace = TRUE),
    "Similarly, the argument totals_include_center allows you to include half of the centered level into the left and the right totals" = sample(likert_levels, 150, replace = TRUE, prob = 5:1),
    "Here is one possible option which uses reorder and an ifelse to reorder the variable mapped on y using the counts (aka the sum) of Strictly disagree " = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
    "and disagree answers. Under the hood ggstats::gglikert reshape the data to long where the question id's are stored in a column named .question and the answers in a column named .answer:" = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
    "They used sampling data and create a data frame called df. I am using the same as given in the link.(the df not the df_dk). Ok, if i run in R the following code :" = sample(c(likert_levels, NA), 150, replace = TRUE),
    "proportion of answers higher than the centered level. I want the plot to be sorted according to very left proportions that are the combination (sum) of the two lower levels. (i.e Respectively the percentages on the very right in the sum of the two lower categories. )" = sample(likert_levels, 150, replace = TRUE, prob = c(1, 0, 1, 1, 0))
  ) %>%
  mutate(across(everything(), ~ factor(.x, levels = likert_levels)))



library(ggplot2)
library(ggstats)

p = ggstats::gglikert(df) +
  aes(y = reorder(.question,
                  ifelse(
                    .answer %in% c("Strongly disagree", "Disagree"),
                    1, 0
                  ),
                  FUN = sum
  ))+ theme(axis.text.y = element_text(size = 8))

Я хочу добавить горизонтально две строки:

  1. линия, которая будет отделять ось Y, как сейчас, отсортирована по убыванию на 20% и

  2. вторая линия на уровне 50%.

дополнительно хочу текстом от 0 до 20% написать "зона предупреждения" внутри панели (сюжета) слева и от 20% до 50% "так себе" и от 50% до 100% написать "зона предупреждения отсутствует" "

Как я могу добиться этого, используя пакет ggplot2 в R на этом отсортированном графике Лайкерта?

Вы имеете в виду «зону предупреждения» для нижней полосы, потому что с ней не согласны только 19%, «так себе» для средних четырех полос и «зону отсутствия предупреждений» для верхней полосы (63% не согласны)?

Carl 20.04.2024 20:17

@Carl, график отсортирован по убыванию на основе суммы процентов двух нижних категорий слева от средней категории. Поэтому мне нужна горизонтальная линия на уровне 20%. Да, 19% попадут в зону предупреждения. следующая строка будет на уровне 50%.

Homer Jay Simpson 20.04.2024 23:05
Стоит ли изучать 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
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Чтобы определить положение линий и текста, сохраните исходный график как p, затем используйте layer_data(p, 3) для проверки данных (в частности, столбцов x, y и label) за третьим слоем ggplot (тот, который содержит текстовые проценты).

Затем добавьте geom_hline и annotate в определенные позиции.

library(dplyr, warn = FALSE)
library(ggplot2)
library(ggstats)
library(purrr)

likert_levels <- c(
  "Strongly disagree",
  "Disagree",
  "Neither agree nor disagree",
  "Agree",
  "Strongly agree"
)

df <-
  tibble(
    "there is an argument sort_prop_include_center that could be set up to TRUE in order to include half of the centered level when sorting data" = sample(likert_levels, 150, replace = TRUE),
    "Similarly, the argument totals_include_center allows you to include half of the centered level into the left and the right totals" = sample(likert_levels, 150, replace = TRUE, prob = 5:1),
    "Here is one possible option which uses reorder and an ifelse to reorder the variable mapped on y using the counts (aka the sum) of Strictly disagree " = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
    "and disagree answers. Under the hood ggstats::gglikert reshape the data to long where the question id's are stored in a column named .question and the answers in a column named .answer:" = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
    "They used sampling data and create a data frame called df. I am using the same as given in the link.(the df not the df_dk). Ok, if i run in R the following code :" = sample(c(likert_levels, NA), 150, replace = TRUE),
    "proportion of answers higher than the centered level. I want the plot to be sorted according to very left proportions that are the combination (sum) of the two lower levels. (i.e Respectively the percentages on the very right in the sum of the two lower categories. )" = sample(likert_levels, 150, replace = TRUE, prob = c(1, 0, 1, 1, 0))
  ) %>%
  mutate(across(everything(), ~ factor(.x, levels = likert_levels)))

# function to save retyping common arguments
anno <- partial(annotate, "text", x = -1, angle = 90, size = 5, fontface = "bold")

gglikert(df) +
  aes(y = reorder(.question,
                  ifelse(
                    .answer %in% c("Strongly disagree", "Disagree"),
                    1, 0
                  ),
                  FUN = sum, decreasing = TRUE
  )) +
  theme(axis.text.y = element_text(size = 8)) + 
  geom_hline(yintercept = c(1.5, 5.5), linetype = "dashed", colour = "grey20") +
  anno(y = 1, label = "warning\nzone", color = "#A6611A") +
  anno(y = 3.5, label = "so-so", color = "black") +
  anno(y = 6, label = "no warning\nzone", color = "#018571") +
  labs(y = NULL)

Created on 2024-04-21 with reprex v2.1.0

Да, работает нормально. Но как выбрать, чтобы yintercept был вектором 1,5, 5,5, а y — 1, 3,5 или 6? Я спрашиваю из любопытства. Я имею в виду как?

Homer Jay Simpson 21.04.2024 00:00

Ось Y является категориальной, поэтому просто имеет значения от 1 до 6. Вы можете увидеть это, если сохраните исходный график как p, а затем запустите layer_data(p, 3), который покажет данные за третьим слоем ggplot (в частности, столбец y). Таким образом, зона предупреждения равна только 1 (столбец label равен 19%), а линия идет на уровне 1,5, то есть между 1 и 2.

Carl 21.04.2024 00:16
layer_data(p, 3) также рассказал мне о положении x ваших крайних левых текстовых меток, т. е. -0.82 и, следовательно, о том, где расположить текст зоны.
Carl 21.04.2024 00:41

Мои извинения.Я сейчас это увидел.Сюжет должен быть отсортирован наоборот.Т.е. когда сумма двух нижних категорий больше 50, то будет зона предупреждения.от 50 до 20 так себе и от 20 до 0 нет зоны предупреждения. Но сортировка здесь имеет решающее значение. Итак, на вашей картинке в ответе 61 должен быть внизу и попадать в зону предупреждения. 45,40,38,23 должен попадать в зону так себе и только 19 будет вверху графика как 61 сейчас находится и будет находиться в зоне без предупреждения.

Homer Jay Simpson 21.04.2024 10:02

Но вы можете видеть, что теперь он правильно отсортирован даже сейчас. Я имею в виду 45 - 38 -40 не отсортирован. Прошу прощения за неясность. Если вы можете отредактировать свой ответ, я был бы очень признателен. Не беспокойтесь о зеленый ответ. Ваш.

Homer Jay Simpson 21.04.2024 10:02

Не беспокойся. Я перевернул это с помощью decreasing = TRUE.

Carl 21.04.2024 10:58

если бы я хотел, чтобы одна линия на уровне 20% разделяла график на две зоны: зона предупреждения ниже 20% и зона предупреждения без зоны ниже 20%, какие изменения мне нужно сделать? Из данных слоя я не понимаю шаблон от x, y, столбцы меток

Homer Jay Simpson 22.04.2024 11:40

Закомментируйте третью строку anno. Измените «так себе» на «без предупреждения\nзоны» во втором anno. Уберите , 5.5 из geom_hline.

Carl 22.04.2024 11:45

теперь я понимаю.!!!! Спасибо!!!! И последний вопрос: почему в столбце layer_data(p, 3) x указаны положительные и отрицательные значения? чтобы вертикально поставить линию?

Homer Jay Simpson 22.04.2024 17:17

6 отрицательных значений — это положение 6 процентных меток слева, а 6 положительных значений — это положение 6 процентных меток справа.

Carl 22.04.2024 18:33

Добавьте + scale_fill_manual(values = c("red", "indianred", "lightblue", "lightgreen", "green")) в последнюю строку.

Carl 24.04.2024 12:51

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