I want to generate a simple bar plot with ggplot2 with the bars ordered by the y-value and the colours manually defined. Here is what I tried:
df <- data.frame(c("a", "b", "c"), c(2, 3, 1))
colnames(df) <- c("shop", "revenue")
ggplot(data = df, aes(x = reorder(shop, revenue), y = revenue, fill = shop)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = c("blue", "yellow", "black")) +
theme_minimal()
The problem is: the colours are wrongly ordered (black, blue and yellow instead of blue, yellow and black as stated in scale_fill_manual). How to fix this?
With scale_fill_manual you assign colors to levels in your data.
At the same time, you use reorder(shop, revenue) in the definition of aes, which orders the data from left to right in ascending order. The third and last definition of the color "blue" was assigned to c which is now at the left hand side as it is the smallest.
You could time this to circumvent this:
ggplot(data = df, aes(x = reorder(shop, revenue), y = revenue, fill = shop)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = c("yellow", "black", "blue")) + # CHANGED
theme_minimal()
Or as #JeroenBoeye suggested:
ggplot(data = df, aes(x = reorder(shop, revenue), y = revenue, fill = shop)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = c("c" = "blue", "a" = "yellow", "b" = "black")) + # Jeroen Boeye's suggestion
theme_minimal()
Please let me know whether this solves your problem.
Related
The geom Texts labels are automatically in decreasing order instead of the data frame.
The question is concerning this part of the snippet "geom_text(aes(label = Freq)..."
Here you can clearly see the that the order is not followed by geom_text. But Frequency descreasing in all categories.
ggplot(df_beine_clan, aes(x = Var2, y = Freq, fill = Var1)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Freq), vjust = 0, size = 5, nudge_y = 2, nudge_x = -0.5)
See Freq Order
How to command that the order should not be changed when rendered on the bar chart?
You could add position_stack like this:
library(ggplot2)
ggplot(df_beine_clan, aes(x = Var2, y = Freq, fill = Var1)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Freq), position = position_stack(vjust = 0.5), size = 5)
Created on 2022-09-03 with reprex v2.0.2
Answering your question without having a MWE is a bit tricky. Hence, as Julien mentioned, an output of dput(df_beine_clan) would be helpful.
I tried to recreate an example, but this might not be applicable to the structure of your data. It might give you an example, however how to tackle the problem. I have created a column in the data table, that contains the label I think you want to add to your plot. Having a separate column gives you more flexibility inside ggplot.
library(tidyverse)
Group <- c("A", "A", "A", "B", "B", "B")
Value <- c(2,4,6,8,10,12)
Response <- c("Yes","No","Maybe","Yes","No","Maybe")
label <- Value
df <- data.frame(Group, Value, Response, label)
ggplot(df, aes(x = Group, y = Value, fill = Response)) + geom_bar(stat = "identity") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5))
Changing the variable label to label <- sort(Value, decreasing = T) or label <- c("Blue", "Green", "Red", "Blue", "Green", "Red") gives you the two figures below.
I have a df where I have made a nice line plot using stat_count, but when I try to add geom_point it won't work.
Without the last part (geom_point(size=2)) it produces a line plot, but with it I get error:
Don't know how to automatically pick scale for object of type
function. Defaulting to continuous. Error: Column y must be a 1d
atomic vector or a list
df <- data.frame("id" = c(1, 1, 1, 2, 2, 3, 3, 3, 4, 4),
"bowl" = c("red", "red", "red","green", "green", "green",
"green", "green", "red", "red"),
"year"=c(2001:2003, 2002:2003, 2001:2003, 2001:2002))
library(dplyr)
library(ggplot2)
df %>%
ggplot(aes(x=year, y=count, colour=bowl)) +
stat_count(geom = "line",
aes(y=..count..))+
geom_point(size=2)
I suspect there's just a small adjustment to be made, but I can't seem to find it on my own.
There are two possible approaches:
Using stat_count() and specifying geom
Using geom_line() and geom_point(), resp., and specifying stat
There is a difference in the default value for position which will create different plots.
1. Stacked plot of counts (total counts)
As already mentioned by Z.Lin,
library(ggplot2)
ggplot(df, aes(x = year, y = stat(count), colour = bowl)) +
stat_count(geom = "line") +
stat_count(geom = "point")
will create a stacked line and point plot of counts, i.e., the total number of records per year (regardless of bowl):
As of version 3.0.0 of gplot2 it is possible to use the new stat() function for calculated-aesthetic variables. So, stat(count) replaces ..count...
The same plot is created by
ggplot(df, aes(x = year, y = stat(count), colour = bowl)) +
geom_line(stat = "count", position = "stack") +
geom_point(stat = "count", position = "stack")
but we have to specify explicitely that the counts have to be stacked.
2. Line and point plot of counts by colour
If we want to show the counts per year for each value of bowl separately, we can use
ggplot(df, aes(x = year, y = stat(count), colour = bowl)) +
geom_line(stat = "count") +
geom_point(stat = "count")
which produces a line and point plot for each colour.
This can also be achieved by
ggplot(df, aes(x = year, y = stat(count), colour = bowl)) +
stat_count(geom = "line", position = "identity") +
stat_count(geom = "point", position = "identity")
but know we have to specify explicitely not to stack.
I'm trying to get a legend to show up in a left chart I've developed. It's not showing up. I've checked ggplot legend not working with scale_colour_manual as well as How to add a legend in ggplot (not showing up) to no avail.
Here is some sample data:
#x axis values
deciles <- c(1:10)
#model_1
decile_act_pp <- c(393.6773, 243.0795, 250.2033, 220.0076, 180.7292,
187.3803,208.8504,162.9708,140.9405,107.7656)
#model_2
model2_pp_norm <- c(537.9617, 306.0807, 244.6228, 207.8051, 181.8801,
161.3744,142.8224,125.3262,107.5905, 80.13438)
#model_3
model1_pp_norm <- c(515.9927,297.8425, 240.8723, 206.6129, 183.6805,
164.3337, 148.4509,134.1227, 115.0055, 88.68549)
#combine to make a chart
df <- as.data.frame(cbind(deciles, decile_act_pp, model2_pp_norm,
model1_pp_norm))
#develop the chart
ggplot(data = df, aes(x = as.factor(deciles), group = 1)) +
geom_point(aes(y = decile_act_pp), color = "blue") +
geom_line(aes(y = decile_act_pp), color = "blue") +
geom_point(aes(y = model2_pp_norm), color = "red") +
geom_line(aes(y = model2_pp_norm), color = "red") +
geom_point(aes(y = model1_pp_norm), color = "green") +
geom_line(aes(y = model1_pp_norm), color = "green") +
xlab("Deciles") +
labs(colour="Datasets",x="Deciles",y="Pure Premium") +
scale_color_manual('', limits = c('decile_act_pp', 'model2_pp_norm',
'model1_pp_norm'), values = c("blue", "red", "green"))
The chart look exactly as I want it minus missing the legend. Can anyone tell me what I'm doing wrong?
library(reshape2)
df2 <- melt(data = df, id.vars = 1)
ggplot(data = df2, aes(x = as.factor(deciles), group = 1)) + geom_point(aes( y=value, color = variable)) + geom_line(aes(y = value, group = variable, color = variable))
How do I change fill pattern or color group by group? My current code only changes the outline; I want to change the fill pattern or fill color group (not outline) by sex but also keep my fill gradient which is by Eye.
colors <- c("Green", "Blue", "Hazel", "Brown")
data <- data.frame(HairEyeColor)
data$Eye <- as.numeric(factor(data$Eye, labels = 1:4))
data <- data[c(5,6,12,15,17,22,27,28), ]
ggplot(data, aes(x = Hair, y = Freq, fill = Eye, group = Sex)) +
geom_bar(stat = "identity", position = position_dodge(), aes(colour = Sex)) +
scale_fill_continuous(low = "blue", high = "green")
Bar plot from ggplot2 package does not support fill pattern at the moment (and as far as i know it is not possible with other packages neither).
However there are few solution that are going to help spot the difference in sex and eye easily which you can consider:
1.Using different (lighter) fill colours,thicker bar boundaries and theme_bw():
ggplot(data, aes(x = Hair, y = Freq, fill = Eye, group = Sex)) +
geom_bar(stat = "identity", position = position_dodge(), aes(colour = Sex), size=2) +
scale_fill_continuous(low = "white", high = "grey") + theme_bw()
Merging two columns: Sex and Eye to get the new factor column which is going to be used as a fill argument:
data$Sex_Eye <- paste(data$Sex, data$Eye, sep="_")
ggplot(data, aes(x = Hair, y = Freq, fill = Sex_Eye)) +
geom_bar(stat = "identity", position = position_dodge()) + theme_bw()
Using geom_jitter() instead of geom_bar() and setting up shape argument as Sex:
ggplot(data, aes(x = Hair, y = Freq, colour = Eye, shape = Sex)) +
geom_jitter(size=5) + scale_colour_continuous(low = "blue", high = "green") + theme_bw()
This is related to : HairEyeColor bar chart in R
I am using following code to produce a similar plot:
mm = melt(HairEyeColor)
ggplot(mm)+geom_bar(aes(x=Hair, y=value, fill=Eye), stat='identity',position='dodge')+facet_grid(Sex~.)
I want to have each bar show hair color in upper part and eye color in lower part. How can this be done? I tried to modify the code in previous question but could not manage. Thanks for your help.
Here it is, I don't think this is a good visualization though...
mm2 <- mm
mm2$value <- mm2$value/4
ggplot(mm)+geom_bar(aes(x=Hair, y=value, fill=Eye), stat='identity',position='dodge')+facet_grid(Sex~.) +
geom_bar(data = mm2, mapping = aes(x=Hair, y=value, fill=Hair, group=Eye), stat = "identity", position = "dodge", colour = "white") +
scale_fill_manual(values = sub("blond", "yellow", sub("hazel", "gold", tolower(sort(unique(c(levels(mm$Eye), levels(mm$Hair))))))))
UPDATE
mm2 <- mm
mm2$value <- mm2$value/2
ggplot(mm)+geom_bar(aes(x=Hair, y=value, fill=Hair, group = Eye), stat='identity',position='dodge', colour = "white")+facet_grid(Sex~.) +
geom_bar(data = mm2, mapping = aes(x=Hair, y=value, fill=Eye, group=Eye), stat = "identity", position = "dodge", colour = "white") +
scale_fill_manual(values = sub("blond", "yellow", sub("hazel", "gold", tolower(sort(unique(c(levels(mm$Eye), levels(mm$Hair))))))))