Ggplot Side by Side Geom_Bar()

ggplot side by side geom_bar()

You will need to melt your data first over value. It will create another variable called value by default, so you will need to renames it (I called it percent). Then, plot the new data set using fill in order to separate the data into groups, and position = "dodge" in order put the bars side by side (instead of on top of each other)

library(reshape2)
library(ggplot2)
dfp1 <- melt(dfp1)
names(dfp1)[3] <- "percent"
ggplot(dfp1, aes(x = value, y= percent, fill = variable), xlab="Age Group") +
geom_bar(stat="identity", width=.5, position = "dodge")

Sample Image

ggplot bar plot side by side using two variables

You have the right idea, I think the melt() function from the reshape2 package is what you're looking for.

library(ggplot2)
library(reshape2)

x <- c(5,17,31,9,17,10,30,28,16,29,14,34)
y <- c(1,2,3,4,5,6,7,8,9,10,11,12)
day <- c(1,2,3,4,5,6,7,8,9,10,11,12)


df1 <- data.frame(x, y, day)
df2 <- melt(df1, id.vars='day')
head(df2)

ggplot(df2, aes(x=day, y=value, fill=variable)) +
geom_bar(stat='identity', position='dodge')

Sample Image

EDIT
I think the pivot_longer() function from the tidyverse tidyr package might now be the better way to handle these types of data manipulations. It gives quite a bit more control than melt() and there's also a pivot_wider() function as well to do the opposite.

library(ggplot2)
library(tidyr)

x <- c(5,17,31,9,17,10,30,28,16,29,14,34)
y <- c(1,2,3,4,5,6,7,8,9,10,11,12)
day <- c(1,2,3,4,5,6,7,8,9,10,11,12)


df1 <- data.frame(x, y, day)
df2 <- tidyr::pivot_longer(df1, cols=c('x', 'y'), names_to='variable',
values_to="value")
head(df2)

ggplot(df2, aes(x=day, y=value, fill=variable)) +
geom_bar(stat='identity', position='dodge')

Plotting two bar charts next to each other in R

urate_data %>% 
tidyr::pivot_longer(-regions) %>%
ggplot(aes(x=regions, y=value)) +
geom_bar(stat='identity') +
facet_wrap(~name)

Sample Image

Plot two variables in bar plot side by side using ggplot2

To "melt" your data use reshape2::melt:

library(ggplot2)
library(reshape2)

# Subset your data
d <- subset(bikesharedailydata, !is.na(mnth))
# Select columns that you will plot
d <- d[, c("mnth", "registered", "casual")]
# Melt according to month
d <- melt(d, "mnth")

# Set fill by variable (registered or casual)
ggplot(d, aes(mnth, value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge") +
coord_flip() +
labs(title="My Bar Chart", subtitle = "Total Renters per Month",
caption = "Caption",
x = "Month", y = "Total Renters")

two bars next to each other using geom_bar

Sharing a sample here, in case other folks want to improve on it...

df <- data.frame(c("1970-1979", "1980-1989", "1990-1999"), c(3009, 3468, 3420), c(393, 469, 657))
colnames(df) <- c("decades", "marxftext", "durkftext")

require(ggplot2)
require(reshape2)

df <- melt(df, id = "decades")

ggplot() + geom_bar(data = df, aes(x = decades, y = value, fill = variable), position = "dodge", stat = "identity")

Something like this?

Modification requests? Leave a comment and I'll post edits

How to center labels over side-by-side bar chart in ggplot2

Hm. Unfortuantely I can't tell you what's the reason for this issue. Also, I'm not aware of any update of ggplot2 or ... Probably I miss something basic (maybe I need another cup of coffee). Anyway. I had a look at the layer_data and your text labels are simply dodged by only half the width of the bars. Hence, you could achieve your desired result by doubling the width, i.e. use position = position_dodge(width = 1.8) in geom_text

library(ggplot2)

ggplot(df, aes(x = Cycle, y = Count_Percentage_Mean, fill = Donor_Location)) +
geom_col(position = "dodge") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
geom_text(aes(label = scales::percent(Count_Percentage_Mean, accuracy = 1)), position = position_dodge(width = 1.8), vjust = -0.5)

Sample Image

Two Variable side by side bar plot ggplot

In order to be treated as a categorical variable, your column Year needs to be converted to type factor. Also note that variable selection with $ should never be used inside of the aes() function.

library(ggplot2)

p <- ggplot(afg, aes(x=FG, y=biomass, fill=factor(Year))) +
geom_bar(stat="identity", position="dodge")

ggsave("dodged_barplot.png", plot=p, height=4, width=6, dpi=150)


# Note that 'Year' is type integer.

str(afg)
# 'data.frame': 6 obs. of 4 variables:
# $ FG : int 1 1 2 2 3 3
# $ biomass: num 288 254 310 308 340 ...
# $ stdev : num 238 221 126 140 176 ...
# $ Year : int 2015 2016 2015 2016 2015 2016

Sample Image

Side by side geom_bar plots of 2 different columns

You need to reshape your dataframe into a longer format. You can use pivot_longer function for example:

library(tidyr)
library(dplyr)

survey %>% pivot_longer(everything(), names_to = "var", values_to = "val")

# A tibble: 20 x 2
var val
<chr> <fct>
1 Past.FoodExp "101-200\x80"
2 Current.FoodExp "101-200\x80"
3 Past.FoodExp "0-100\x80"
4 Current.FoodExp "101-200\x80"
5 Past.FoodExp "201-300\x80"
6 Current.FoodExp "300\x80+"
7 Past.FoodExp "300\x80+"
8 Current.FoodExp "300\x80+"
9 Past.FoodExp "201-300\x80"
10 Current.FoodExp "201-300\x80"
11 Past.FoodExp "300\x80+"
12 Current.FoodExp "201-300\x80"
13 Past.FoodExp "201-300\x80"
14 Current.FoodExp "300\x80+"
15 Past.FoodExp "300\x80+"
16 Current.FoodExp "300\x80+"
17 Past.FoodExp "201-300\x80"
18 Current.FoodExp "300\x80+"
19 Past.FoodExp "201-300\x80"
20 Current.FoodExp "300\x80+"

So, with this structure, you can now pass it easily in ggplot2 as follow:

library(tidyr)
library(dplyr)
library(ggplot2)

survey %>% pivot_longer(everything(), names_to = "var", values_to = "val") %>%
ggplot(aes(x = val, fill = var))+
geom_bar(position = position_dodge())+
geom_text(stat = "count", aes(label = ..count..), vjust = -0.2, position = position_dodge(0.9))

Sample Image

Does it answer your question ?

How to do a side-by-side bar plot in ggplot2?

If you need a side-by-side bar chart without facet, try this:

library(tidyverse)

df %>%
pivot_longer(-1, names_to = "year", values_to = "count") %>%
ggplot(aes(Council, count, fill = year)) +
geom_col(position = "dodge2") +
scale_x_continuous(breaks = 1:10)


Data

df <- structure(list(Council = 1:10, `2019` = c(260L, 130L, 42L, 38L, 
45L, 34L, 13L, 30L, 16L, 15L), `2020` = c(206L, 157L, 48L, 42L,
126L, 26L, 21L, 13L, 15L, 43L)), row.names = c(NA, -10L), class = c("tbl_df",
"tbl", "data.frame"))


Related Topics



Leave a reply



Submit