ggplot2 - как изменить порядок точек данных в столбчатой ​​диаграмме с метками по значениям, а не по алфавиту

Я хотел бы изменить порядок суммированных точек данных барплота так, чтобы в каждом баре они сортировались от самого большого к наименьшему КОМПЕТЕНТУ по его общему значению, а не по алфавиту.

Я сгенерировал данные для использования fct_reorder (закомментированная строка), и точки данных отсортированы, но метки не соответствуют измененному порядку. Как я могу сделать так, чтобы метки на графике следовали их примеру и располагались в правильных положениях в середине сегментов стержня?

Вот мой рабочий воспроизводимый пример с закомментированной строкой fct_reorder. Если вы раскомментируете его, точки данных будут отсортированы, но метки останутся в неправильных позициях.

library(tidyverse)
library(scales)


data<- tibble::tribble(
  ~CUSTOMER, ~COMPETITOR, ~VALUE,
      "AAA",    "XXX",  23400,
      "AAA",    "YYY",  10000,
      "AAA",    "ZZZ",  80000,
      "AAA",    "YYY",  60000,
      "BBB",    "XXX",  10000,
      "BBB",    "YYY",  20000,
      "BBB",    "ZZZ",  10000,
      "BBB",    "YYY",  80000,
      "CCC",    "YYY",  30000,
      "CCC",    "ZZZ",  20000,
      "DDD",    "YYY",   7000,
      "CCC",    "VVV",  10000
  )


unit_mln <-
  scales::unit_format(
    unit = "mln",
    sep = " ",
    scale = 1e-6,
    digits = 2,
    justify = "right"
  )

col_competitors <-
  scale_fill_manual( "legend", 
                     values = c(
                       "XXX" = "navyblue",   "YYY" = "red",
                       "ZZZ" = "lightyellow", "VVV" = "green"))



df_cust<- data %>% mutate(COMPETITOR=as.factor(COMPETITOR)) %>% 
  group_by(CUSTOMER) %>%                                                    
  mutate(CUST_VALUE=sum(VALUE)) %>%                                 
  ungroup() %>% 
  group_by(COMPETITOR) %>%      
  mutate(COMP_VALUE=sum(VALUE)) %>%                                 
  ungroup() %>% 
  group_by(CUSTOMER,  COMPETITOR) %>%                                           
  summarise(CUST_VALUE=max(CUST_VALUE), COMP_VALUE=max(COMP_VALUE), VALUE=sum(VALUE))%>% 
  arrange(desc(CUST_VALUE))

# df_cust<-df_cust %>% mutate(COMPETITOR= fct_reorder(COMPETITOR, -COMP_VALUE))



df_comp<- data %>% group_by(COMPETITOR) %>% summarise(VALUE=sum(VALUE)) 

df_cust$CUSTOMER = str_wrap(df_cust$CUSTOMER, width = 30)



plt_main<-df_cust %>% 
  ggplot(aes(x = fct_reorder(CUSTOMER, -CUST_VALUE), y = VALUE)) +
  geom_col(
    aes(fill = COMPETITOR),
    alpha = 0.5,
    position = position_stack(reverse = T),
    col = "darkgray",
    show.legend = F ) +
  geom_text(aes(label = unit_mln(round(VALUE,-4))),
            size = 3,
            position = position_stack(vjust = 0.5)) +
  xlab(" ") + ylab("Market share (GROSS PLN)") + ggtitle(paste("Top competitors in top customers: ", "Poland")) +
  theme_bw(base_size = 11) +
  theme(
    axis.text.x = element_text(
      angle = 90,
      hjust = 1,
      vjust = 0.5 ),
    legend.position = c(0.94, 0.75)) +
  col_competitors +
  scale_y_continuous(
    labels = function(n) {
      unit_mln(n)
    },
    sec.axis = sec_axis(~ . / sum(df$VALUE), labels = scales::percent)
  )

2 ответа

Я думаю, что следующее должно сделать это:

ggplot(df, aes(x = reorder(CUSTOMER, -COMP_VALUE), y = VALUE))

Это упорядочивает столбец CUSTOMER по COMP_VALUE.

Я прокомментировал "#****description****" строки, которые делали возможным упорядочение точек данных и меток в гистограммах с накоплением. Теперь они упорядочены по общему объему продаж КОМПЕТИТОРА, а не по алфавиту. Я признаю, что добился этого методом проб и ошибок, и это не может быть оптимальным ответом.

library(tidyverse)
library(scales)

# Example data

data<- tibble::tribble(
  ~CUSTOMER, ~COMPETITOR, ~VALUE,
      "AAA",    "XXX",  123400,
      "AAA",    "YYY",  10000,
      "AAA",    "ZZZ",  80000,
      "AAA",    "YYY",  60000,
      "BBB",    "XXX",  110000,
      "BBB",    "YYY",  20000,
      "BBB",    "ZZZ",  10000,
      "BBB",    "YYY",  80000,
      "CCC",    "YYY",  30000,
      "CCC",    "ZZZ",  12000,
      "DDD",    "YYY",   7000,
      "CCC",    "VVV",  10000)

# Format labels with scales package

unit_mln <-
  unit_format(
    unit = "mln",
    sep = " ",
    scale = 1e-6,
    digits = 2,
    justify = "right"
  )

# Set your own colors for competitors

col_competitors <-
  scale_fill_manual( "legend", 
                     values = c(
                       "XXX" = "navyblue",   "YYY" = "red",
                       "ZZZ" = "lightyellow", "VVV" = "green"))


# Generate helper data for ordering: totals for CUSTOMER and COMPETITOR.

df_cust<- data %>% mutate(COMPETITOR=as.factor(COMPETITOR)) %>% 
  group_by(CUSTOMER) %>%                                                    
  mutate(CUST_VALUE=sum(VALUE)) %>%                                 
  ungroup() %>% 
  group_by(COMPETITOR) %>%      
  mutate(COMP_VALUE=sum(VALUE)) %>%                                 
  ungroup() %>% 
  group_by(CUSTOMER,  COMPETITOR) %>%                                           
  summarise(CUST_VALUE=max(CUST_VALUE), COMP_VALUE=max(COMP_VALUE), VALUE=sum(VALUE))%>% 
  arrange(desc(CUST_VALUE))

# Reorder COMPETITOR by total VALUE descening                       #***this is needed to reorder labels***
df_cust<-df_cust %>% mutate(COMPETITOR= reorder(COMPETITOR, -COMP_VALUE))


# Prepare data for a small "legend" plot
df_comp<- data %>% group_by(COMPETITOR) %>% summarise(VALUE=sum(VALUE)) 

# Wrap CUSTOMER names if too long
df_cust$CUSTOMER = str_wrap(df_cust$CUSTOMER, width = 30)

# Main plot
(
plt_main<-df_cust %>% 
  ggplot(aes(x = fct_reorder(CUSTOMER, -CUST_VALUE), y = VALUE)) +  #***this fct_ reorders bars***
  geom_col(
    aes(fill = COMPETITOR),
    alpha = 0.5,
    position = position_stack(reverse = T),
    col = "darkgray",
    show.legend = F ) +
  geom_text(aes(label = unit_mln(round(VALUE,-4)), 
                group=fct_reorder(COMPETITOR, COMP_VALUE)),         #***this fct_ reorders labels***
            size = 3, 
            position = position_stack(vjust = 0.5, reverse=F)) +
  xlab(" ") + ylab("Market share (GROSS PLN)") + ggtitle(paste("Top competitors in top customers: ", "Poland")) +
  theme_bw(base_size = 11) +
  theme(
    axis.text.x = element_text(
      angle = 90,
      hjust = 1,
      vjust = 0.5 ),
    legend.position = c(0.94, 0.75)) +
  col_competitors +
  scale_y_continuous(
    labels = function(n) {
      unit_mln(n)
    },
    sec.axis = sec_axis(~ . / sum(df_cust$VALUE), labels = scales::percent)
  )
)
Другие вопросы по тегам