Johnny Oshika
Johnny Oshika

Reputation: 57502

Spacing between groups of bars in histogram

When I produce histograms in ggplot2 where the bar positions are dodge, I expect something like this where there is space between the groups of bars (i.e. notice the white space between each groups of red/green pairs):

enter image description here

I'm having a hard time producing the same effect when I build a histogram with continuous data. I can't seem to add space between the groups of bars, and instead, everything gets squashed together. As you can see, it makes it visually difficult to compare the red/green pairs:

enter image description here

To reproduce my problem, I created a sample data set here: https://www.dropbox.com/s/i9nxzo1cmbwwfsa/data.csv?dl=0

Code to reproduce:

data <- read.csv("https://www.dropbox.com/s/i9nxzo1cmbwwfsa/data.csv?dl=1")

ggplot(data, aes(x = soldPrice, fill = month)) +
    geom_histogram(binwidth=1e5, position=position_dodge()) +
    labs(x="Sold Price", y="Sales", fill="") +
    scale_x_continuous(labels=scales::comma, breaks=seq(0, 2e6, by = 1e5)) +
    theme_bw() +
    theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))

How can I add white space between the groups of red/green pairs?

Upvotes: 5

Views: 6023

Answers (1)

KoenV
KoenV

Reputation: 4283

Alternative 1: overlapping bars with geom_histogram()

From ?position_dodge():

Dodging preserves the vertical position of an geom while adjusting the horizontal position

This function accepts a width argument that determines the space to be created.

To get what I think you want, you need to supply a suitable value to position_dodge(). In your case, where binwidth=1e5, you might play with e.g. 20% of that value: position=position_dodge(1e5-20*(1e3)). (I left the rest of your code untouched.)

You could use the following code:

ggplot(data, aes(x = soldPrice, fill = month)) +
  geom_histogram(binwidth=1e5, position=position_dodge(1e5-20*(1e3))) + ### <-----
  labs(x="Sold Price", y="Sales", fill="") +
  scale_x_continuous(labels=scales::comma, breaks=seq(0, 2e6, by = 1e5)) +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))

yielding this plot:

enter image description here

Alternative 2: use ggplot-object and render with geom_bar

geom_histogram() was not designed to produce what you want. geom_bar() on the other hand provides the flexibility you need.

You can generate the histogram with geom_histogram and save it in an ggplot-object. Then, you generate the plotting information with ggplot_build(). Now, you may use the histogram plotting information in the object to generate a bar plot with geom_bar()

## save ggplot object to h
h <- ggplot(data, aes(x = soldPrice, fill = month)) + 
  geom_histogram(binwidth=1e5, position=position_dodge(1e5-20*(1e3)))

## get plotting information as data.frame
h_plotdata <- ggplot_build(h)$data[[1]]
h_plotdata$group <- as.factor(h_plotdata$group)
levels(h_plotdata$group) <- c("May 2018", "May 2019")

## plot with geom_bar
ggplot(h_plotdata, aes(x=x, y=y, fill = group)) +
  geom_bar(stat = "identity") +
  labs(x="Sold Price", y="Sales", fill="") +
  scale_x_continuous(labels=scales::comma, breaks=seq(0, 2e6, by = 1e5)) +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))

yielding this graph:

enter image description here

Please, let me know whether this is what you want.

Upvotes: 6

Related Questions