最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

r - ggplot2 Ignores Factor Order in Dodged Bar Plot - Stack Overflow

programmeradmin4浏览0评论

Apologies in advance for anything amateurish; this is my first stack post.

I'm trying to create a dodged bar plot in ggplot2, where the bars within each date bin are ordered by count. However, ggplot2 just seems to ignore the levels. I can't tell if it's defaulting to alphabetical ordering or something else.

Here's a reproducible example that demonstrates the issue. Any suggestions on how to order the bars within each date bin by count? Thanks in advance!

library(ggplot2)
library(dplyr)
library(forcats)

set.seed(42)
daily_data <- expand.grid(
  date = seq.Date(from = as.Date("2024-01-01"), to = as.Date("2024-01-10"), by = "1 day"),
  location = c("West", "East", "North")
) %>%
  mutate(count = sample(10:100, size = n(), replace = TRUE))

daily_data <- daily_data %>%
  group_by(date) %>%
  mutate(location = fct_reorder2(location, date, count)) %>%
  ungroup()

p <- ggplot(daily_data, aes(x = factor(date), y = count, fill = location)) +
  geom_col(stat = "identity", position = "dodge") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

print(p)

What I've tried so far:

  • Manually setting factor levels with factor()
  • Using fct_reorder()and fct_reorder2() in the original mutate call as well as in the fill argument of aes()

I don't think it's defaulting to alphabetical ordering, but I could be wrong. Any changes I make to the structure or class of location has no effect on the resulting plot.

This post covers the same topic, but it doesn't look like there was a solution reached, at least not one that I could parse.

Apologies in advance for anything amateurish; this is my first stack post.

I'm trying to create a dodged bar plot in ggplot2, where the bars within each date bin are ordered by count. However, ggplot2 just seems to ignore the levels. I can't tell if it's defaulting to alphabetical ordering or something else.

Here's a reproducible example that demonstrates the issue. Any suggestions on how to order the bars within each date bin by count? Thanks in advance!

library(ggplot2)
library(dplyr)
library(forcats)

set.seed(42)
daily_data <- expand.grid(
  date = seq.Date(from = as.Date("2024-01-01"), to = as.Date("2024-01-10"), by = "1 day"),
  location = c("West", "East", "North")
) %>%
  mutate(count = sample(10:100, size = n(), replace = TRUE))

daily_data <- daily_data %>%
  group_by(date) %>%
  mutate(location = fct_reorder2(location, date, count)) %>%
  ungroup()

p <- ggplot(daily_data, aes(x = factor(date), y = count, fill = location)) +
  geom_col(stat = "identity", position = "dodge") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

print(p)

What I've tried so far:

  • Manually setting factor levels with factor()
  • Using fct_reorder()and fct_reorder2() in the original mutate call as well as in the fill argument of aes()

I don't think it's defaulting to alphabetical ordering, but I could be wrong. Any changes I make to the structure or class of location has no effect on the resulting plot.

This post covers the same topic, but it doesn't look like there was a solution reached, at least not one that I could parse.

Share Improve this question edited yesterday jpsmith 17.4k6 gold badges20 silver badges45 bronze badges asked yesterday Sam SwansonSam Swanson 333 bronze badges New contributor Sam Swanson is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 0
Add a comment  | 

1 Answer 1

Reset to default 2

Making location a factor will typically just give it one ordering; it looks like in this case it's the order for the first date, and using that order in every other date. To get what you want will probably take something like the approach used in tidytext::reorder_within(), where the data is ordered at a granularity that reflects both the location and the date (and mapped to group, which will drive the dodging), and then labeled to hide that. https://juliasilge/blog/reorder-within/

daily_data <- daily_data %>%
  mutate(location2 = tidytext::reorder_within(location, desc(count), date))

ggplot(daily_data, aes(x = factor(date), y = count, fill = location, group = location2)) +
  geom_col(position = "dodge") +
  # tidytext::scale_x_reordered() + # Not necessary in this case since we're
  #  using date for the x axis
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

发布评论

评论列表(0)

  1. 暂无评论