Is there a possibility to combine position_stack and nudge_x in a stacked bar chart in ggplot2? - r

I want to add labels to a stacked bar chart to achieve something like this:
The goal is simple: I need to show market shares and changes versus previous year in the same graph. In theory, I would just add "nudge_x=0.5," to geom_text in the code but I get the error: "Specify either position or nudge_x/nudge_y". Is it possible to use some workaround, maybe another package? Thanks a lot in advance!
Code:
DashboardCategoryText <- c("Total Market","Small Bites","Bars","Total Market","Small Bites","Bars","Total Market","Small Bites","Bars")
Manufacturer <- c("Ferrero","Ferrero","Ferrero","Rest","Rest","Rest","Kraft","Kraft","Kraft")
MAT <- c(-1,5,-7,6,8,10,-10,5,8)
Measure_MATCurrent <- c(500,700,200,1000,600,80,30,60,100)
data <- data.frame(DashboardCategoryText,Manufacturer,MAT,Measure_MATCurrent)
library(dplyr)
groupedresult <- group_by(data,DashboardCategoryText)
groupedresult <- summarize(groupedresult,SUM=sum(Measure_MATCurrent))
groupedresult <- as.data.frame(groupedresult)
data <- merge(data,groupedresult,by="DashboardCategoryText")
data$percent <- data$Measure_MATCurrent/data$SUM
library(ggplot2)
ggplot(data, aes(x=reorder(DashboardCategoryText, SUM), y=percent, fill=Manufacturer)) +
geom_bar(stat = "identity", width = .7, colour="black", lwd=0.1) +
geom_text(aes(label=ifelse(percent >= 0.005, paste0(sprintf("%.0f", percent*100),"%"),"")),
position=position_stack(vjust=0.5), colour="white") +
geom_text(aes(label=MAT,y=percent),
nudge_x=0.5,
position=position_stack(vjust=0.8),
colour="black") +
coord_flip() +
scale_y_continuous(labels = percent_format()) +
labs(y="", x="")

I have a somewhat 'hacky' solution where you essentially just change the geom_text data in the underlying ggplot object before you plot it.
p <- ggplot(data, aes(x=reorder(DashboardCategoryText, SUM), y=percent, fill=Manufacturer)) +
geom_bar(stat = "identity", width = .7, colour="black", lwd=0.1) +
geom_text(aes(label=ifelse(percent >= 0.005, paste0(sprintf("%.0f", percent*100),"%"),"")),
position=position_stack(vjust=0.5), colour="white") +
geom_text(aes(label=MAT,y=percent),
position=position_stack(vjust=.5),
colour="black") +
coord_flip() +
scale_y_continuous(labels = percent_format()) +
labs(y="", x="")
q <- ggplot_build(p) # get the ggplot data
q$data[[3]]$x <- q$data[[3]]$x + 0.5 # change it to adjust the x position of geom_text
plot(ggplot_gtable(q)) # plot everything

Related

How to show the part of the errorbar lines which are within the plot margins using `ggplot2`?

I have a grid of plots, all with the same y and x-axis scale. The plots represent time in the x-axe and mean values in the y-axe with their standard errors. My problem is that some errorbars are not entirely within the plot margins, and I wonder if there is some way to represent the part of the errorlines that are within the plot margins. Below I give a fake example and code to play with:
df <- data.frame(time=seq(-15,15,1),
mean=c(0.49,0.5,0.53,0.55,0.57,0.59,0.61,0.63,0.65,0.67,0.69,0.71,0.73,0.75,0.77,0.79,0.77,0.75,0.73,0.71,0.69,0.67,0.65,0.63,0.61,0.59,0.57,0.55,0.53,0.51,0.49),
sd=c(0.09,0.087,0.082,0.08,0.023,0.011,0.010,0.009,0.008,0.007,0.006,0.005,0.004,0.003,0.002,0.001,0.002,0.003,0.004,0.005,0.006,0.007,0.008,0.009,0.010,0.011,0.023,0.08,0.084,0.087,0.09))
Plot <- ggplot(df, aes(x=time, y=mean)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), width=.3) +
geom_point(size=1) +
geom_line () +
theme_bw() +
scale_y_continuous(limits = c(0.49, 0.85), breaks = c(0.5, 0.65,0.8))
Plot
You need to set coord_cartesian limits rather than scale_y_continuous limits:
ggplot(df, aes(x=time, y=mean)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), width=.3) +
geom_point(size=1) +
geom_line () +
theme_bw() +
scale_y_continuous(breaks = c(0.5, 0.65,0.8)) +
coord_cartesian(ylim = c(0.49, 0.85))

Change the scale of x axis in ggplot

I have a ggplot bar and don't know how to change the scale of the x axis. At the moment it looks like on the image below. However I'd like to reorder the scale of the x axis so that 21% bar is higher than the 7% bar. How could I get the % to the axis? Thanks in advance!
df= data.frame("number" = c(7,21), "name" = c("x","y"))
df
ggplot(df, aes(x=name, y=number)) +
geom_bar(stat="identity", fill = "blue") + xlab("Title") + ylab("Title") +
ggtitle("Title")
Use the prop.table function to in y variable in the geom plot.
ggplot(df, aes(x=name, y=100*prop.table(number))) +
geom_bar(stat="identity", fill = "blue") +
xlab("Stichprobe") + ylab("Paketmenge absolut") +
ggtitle("Menge total")
If you want to have the character, % in the y axis, you can add scale_y_continuous to the plot as below:
library(scales)
ggplot(df, aes(x=name, y=prop.table(number))) +
geom_bar(stat="identity", fill = "blue") +
xlab("Stichprobe") + ylab("Paketmenge absolut") +
ggtitle("Menge total") +
scale_y_continuous(labels=percent)
The only way I am able to duplicate the original plot is, as #sconfluentus noted, for the 7% and 21% to be character strings. As an aside the data frame column names need not be quoted.
df= data.frame(number = c('7%','21%'), name = c("x","y"))
df
ggplot(df, aes(x=name, y=number)) +
geom_bar(stat="identity", fill = "blue") + xlab("Title") + ylab("Title") +
ggtitle("Title")
Changing the numbers to c(0.07, 0.21) and adding, as #Mohanasundaram noted, scale_y_continuous(labels = scales::percent) corrects the situation:
To be pedantic using breaks = c(0.07, 0.21) creates nearly an exact duplicate. See also here.3
Hope this is helpful.
library(ggplot2)
library(scales)
df= data.frame(number = c(0.07,0.21), name = c("KG","MS"))
df
ggplot(df, aes(x=name, y=number)) +
geom_bar(stat="identity", fill = "blue") + xlab("Title") + ylab("Title") +
ggtitle("Title") + scale_y_continuous(labels = scales::percent, breaks = c(.07, .21)))

How to fit a lot of x labels or space out x labels in ggplot2

Is there a way to space out so that each x label is more distinguishable?
I feel like this question has been asked before but I can't seem to find an answer. I believe the graph needs to be bigger for this to work, is their a way to make the graph bigger within Rstudio? or make the text smaller
My code so far :
bar_plt = ggplot(data, aes(fct_infreq(Event))) + geom_bar(fill = "dodgerblue", width = .4) +
xlab("Event Names") + ylab("Number of Observations") + coord_flip()
TIA
what about working with labels in this way (sorry for the fake data, but I have not got a sample of your):
library(ggplot2)
# numbers
set.seed(1)
y<-sample(1:30, 500, TRUE)
# very long and numerous labels
x <- paste(sample(letters[1:22], 500, TRUE),sample(letters[1:2], 500, TRUE),'abcdefghijklmnopqrstuvwxyz')
data <- data.frame(x,y)
# simple ggplot barplot
p <- ggplot(data, aes(x = x, y = y)) + geom_bar(stat = "identity") + coord_flip()
# play with the size to have a fitting dimension
p <- p + theme(axis.text.y = element_text(face="bold", color="black", size=8))
# you can also abbreviate the labels if necessary
p <- p + scale_x_discrete(labels = abbreviate)
p
Your plot could be something like:
library(forcats)
library(ggplot2)
# data
set.seed(1)
Events <- paste(sample(letters[1:22], 500, TRUE),sample(letters[1:2], 500, TRUE),'abcdefghijklmnopqrstuvwxyz')
data <- data.frame(Events)
bar_plt <- ggplot(data, aes(fct_infreq(Events))) + geom_bar(fill = "dodgerblue", width = .4) + coord_flip()
bar_plt <- bar_plt + xlab("Event Names") + ylab("Number of Observations")
bar_plt <- bar_plt + theme(axis.text.y = element_text(face="bold", color="black", size=8))
bar_plt <- bar_plt + scale_x_discrete(labels = abbreviate)
bar_plt

In ggplot2, how to add text by group in facet_wrap?

Here is an example:
library(ggplot2)
set.seed(112)
df<-data.frame(g=sample(c("A", "B"), 100, T),
x=rnorm(100),
y=rnorm(100,2,3),
f=sample(c("i","ii"), 100, T))
ggplot(df, aes(x=x,y=y, colour=factor(g)))+
geom_point()+geom_smooth(method="lm", fill="NA")+facet_wrap(~f)
My question is how to add text like the second plot by group into the plot.
You can manually create another data.frame for your text and add the layer on the original plot.
df_text <- data.frame(g=rep(c("A", "B")), x=-2, y=c(9, 8, 9, 8),
f=rep(c("i", "ii"), each=2),
text=c("R=0.2", "R=-0.3", "R=-0.05", "R=0.2"))
ggplot(df, aes(x=x,y=y, colour=factor(g))) +
geom_point() + geom_smooth(method="lm", fill="NA") +
geom_text(data=df_text, aes(x=x, y=y, color=factor(g), label=text),
fontface="bold", hjust=0, size=5, show.legend=FALSE) +
facet_wrap(~f)
Another option is to calculate the correlations on the fly and use the underlying numeric values of the factor variable g to place the text so that the red and blue labels don't overlap. This reduces the amount of code needed and makes label placement a bit easier.
library(dplyr)
ggplot(df, aes(x=x, y=y, colour=g)) +
geom_point() +
geom_smooth(method="lm", fill=NA) + # Guessing you meant fill=NA here
#geom_smooth(method="lm", se=FALSE) # Better way to remove confidence bands
facet_wrap(~f) +
geom_text(data=df %>% group_by(g, f) %>% summarise(corr = cor(x,y)),
aes(label=paste0("R = ", round(corr,2)), y = 10 - as.numeric(g)),
x=-2, hjust=0, fontface="bold", size=5, show.legend=FALSE)

R - Shading part of a ggplot2 histogram

So I have this data:
dataset = rbinom(1000, 16, 0.5)
mean = mean(dataset)
sd = sd(dataset)
data_subset = subset(dataset, dataset >= (mean - 2*sd) & dataset <= (mean + 2*sd))
dataset = data.frame(X=dataset)
data_subset = data.frame(X=data_subset)
And here's how I'm drawing my histogram for dataset:
ggplot(dataset, aes(x = X)) +
geom_histogram(aes(y=..density..), binwidth=1, colour="black", fill="white") +
theme_bw()
How can I shade the data_subset portion of the histogram, like so?
My solution is very similar to joran's -- I think they're both worth looking at for the slight differences:
ggplot(dataset,aes(x=X)) +
geom_histogram(binwidth=1,fill="white",color="black") +
geom_histogram(data=subset(dataset,X>6&X<10),binwidth=1,
colour="black", fill="grey")+theme_bw()
Just add another geom_histogram line using that data subset (although you may have to tinker with the binwidth a bit, I'm not sure):
ggplot(dataset, aes(x = X)) +
geom_histogram(aes(y=..density..), binwidth=1, colour="black", fill="white") +
geom_histogram(data = data_subset,aes(y=..density..), binwidth=1, colour="black",fill = "grey") +
theme_bw()

Resources