How to replicate histograms from ggplot code - r

I have the following code using ggplot:
ggplot(sub9, aes(x=YR,y=Freq)) +
scale_y_continuous(limit=c(0,15),expand=c(0, 0)) +
geom_bar(stat='identity') +
xlab(" ") + ylab("No of papers") +
theme_bw(base_size = 16) +
theme(axis.text.x=element_text(angle=45,hjust=1,size=13)) +
annotate("text",x=3.5,y=14,label="Pollution",cex=7)
I have 25 plots like this, and need to plot many plots within the same graph page. This usually works well in R, using e.g. par(mfrow=c(4,4)) for a 4 x 4 plot. This code doesn't work with ggplot, where I have to use the function multiplot, which doesn't work that well as it doesn't scale all the text and legends accordingly.
Therefore I ask if some of you out there could help me replicate the exact same plot using hist.The x (YR) is a factor, and the y (Freq) is numerical.

Not sure if you're asking for putting multiple ggplots on the same page or asking for how to run histogram.
Anyway, here's an example of histogram with iris data.
library(ggplot2)
library(gridExtra)
g1 <- ggplot(iris, aes(x=Sepal.Length)) + geom_histogram(binwidth=0.5)
I'd used grid.arrange to create a 3x2 layout of 6 replicated plots:
grid.arrange (g1, g1, g1, g1, g1, g1, ncol=3)

Use facet_wrap and facet_grid
You might be looking for facet_wrap or facet_grid, which allow you to create multiple plots for different values of a factor or other categorical variable. Of course this also works for histograms.
Example from documentation
ggplot(mpg, aes(displ, cty)) + geom_point() + facet_grid(drv ~ cyl)

Related

Plotting multiple wordcloud (ggwordcloud) with other types of plots in ggplot2

I am trying to plot several wordclouds in a scatterplot and I wonder if one can control the position of a wordcloud in ggplot?
As an example the code below overlays both wordclouds around the origin of the plot.
Say I want to place the second wordcloud at x=4 and y =35. Is that possible?
library(ggplot2)
library(ggwordcloud)
ggplot() +
geom_point(mtcars,mapping=aes(wt,mpg)) +
geom_text_wordcloud(love_words_small,mapping=aes(label=word)) +
geom_text_wordcloud(mtcars,mapping=aes(label=rownames(mtcars))) +
theme_minimal()
I was looking for the exact same thing. Looks like you can simply add the x and y aesthetic arguments. Ie.
ggplot() +
geom_point(mtcars,mapping=aes(wt,mpg)) +
geom_text_wordcloud(love_words_small,mapping=aes(label=word)) +
geom_text_wordcloud(mtcars,mapping=aes(label=rownames(mtcars), x=4,y=35)) +
theme_minimal()
What I did may be more generally helpful for folks, which is to pass x and y vectors:
library(tidyverse)
library(ggwordcloud)
ggplot(data = mtcars %>% mutate(car_names = rownames(mtcars)) %>%
group_by(cyl),
mapping = aes(label=car_names, x=mpg, y=disp)) +
geom_text_wordcloud()
Perhaps you could save the wordclouds as separate plots, and then add them to one plot with cowplot or gridExtra or any of the packages that lets you combine plots?

R: fct_reorder() and making a grid of plots - not compatible?

I'm using fct_reorder() to order the levels of my factors in ggplot. That works fine for individual plots. But when I use plot_grid() from cowplot, there is some kind of problem. For contrast, to the left, I've used a plot that has fixed factor levels, not using fct_reorder.
Edited:
Here is the actual code I'm using:
#make the base
myplot <-filter(summary_by_intensity_reshaped, str_detect(feature, "binary"), Frequency == "2Hz") %>%
ggplot(., aes(fct_reorder(feature, mean),mean,fill=Intensity, ymax=mean+sem, ymin=mean-sem))
#add the layers
myplot + geom_bar(stat="identity", position=position_dodge()) +
geom_errorbar(aes(width=0.2),position=position_dodge(0.9)) +
labs(x="Behavior",y="Percent of Trials (%)") +
scale_x_discrete(breaks=c("binary_flutter", "binary_hold", "binary_lift", "binary_jump","binary_rear", "binary_lick", "binary_guard", "binary_vocalize"), labels=c("Flutter", "Holding", "Lifting", "Jumping", "Rearing", "Licking", "Guarding", "Vocalizing"))+
facet_grid(~Frequency)+
theme(axis.text.x=element_text(angle=-90))
And the output looks like this:
The problem arises when I try to use 'myplot' in plot_grid(). That's when it renders oddly as in the example below.
I suspect you're using fct_reorder() incorrectly. plot_grid() just takes whatever plot you make and puts it into a grid.
library(ggplot2)
library(cowplot)
library(forcats)
p1 <- ggplot(mpg, aes(class, displ, color = factor(cyl))) + geom_point()
p2 <- ggplot(mpg, aes(fct_reorder(class, displ, mean), displ, color = factor(cyl))) +
geom_point()
plot_grid(p1, p2)
From your x axis title in the plot on the right, it looks to me like you forgot to provide fct_reorder() with the vector to which it should apply the function.

scale_color_brewer (ggplot2) does not colour all the lines

When running this ggplot2 code:
ggplot(canine_lower, aes(x=x, y=y, colour=Teeth)) +
geom_smooth(method="lm", formula= y~poly(x,4), se=FALSE) +
scale_color_grey(start=0.9, end=0.1)
I get this plot thanks to the scale_color_grey function:
There is a gradual grey transition among all groups of teeth (from 1 to 16).
However, I would like to colourize it. For this reason I employed the scale_color_brewer, with partly success. The run code is:
ggplot(canine_lower, aes(x=x, y=y, colour=Teeth)) +
geom_smooth(method="lm", formula= y~poly(x,4), se=FALSE)+
scale_color_brewer(palette="Reds")
which offers this unfinished plot:
As seen above, from 10 to 16 there is no color.
How can I span the color range using this function? Is there any other alternative function?
I must say that I tried with scale_color_gradient with no success.
The maximum number of colors from brewer.pal (in the package RColorBrewer), the function scale_color_brewer uses to generate the colors, is 9 for sequential palettes. If you look at the help for brewer.pal you can check the maximum number of colors for each of the palette types.
You can generate larger palettes in many other ways, such as scale_color_viridis as shown by #NateDay, or with the two examples below, but it will be difficult to distinguish so many different colors in the graph.
mtcars$rowname=rownames(mtcars)
ggplot(mtcars[1:16, ], aes(mpg, hp, color=rowname)) +
geom_point() +
scale_colour_manual(values=hcl(seq(0,360,length=17)[1:16], 100,65))
ggplot(mtcars[1:16, ], aes(mpg, hp, color=rowname)) +
geom_point() +
scale_colour_manual(values=hcl(0,100,seq(40,100,length=16)))
you could use library(viridis) as an alternative:
# a reproducible example
mtcars <- add_rownames(mtcars)
ggplot(mtcars, aes(mpg, hp, color = rowname)) +
geom_point() +
viridis::scale_color_viridis(discrete = TRUE)
scale_color_gradient() is failing you because it is designed to be used to map to continuous values, not discrete ones.

How to use for function to construct a panel of ggplot2 plots in R

I am a beginner trying to build a multiple plots in ggplot2. Using the mtcars dataset in R
library(datasets)
data (mtcars)
library (ggplot2)
## convert to factor some variables to avoid problems
factors<-c(2,9,10,11)
mtcars[,factors]<-lapply(mtcars[,factors],factor)
I want to plot mpg vs all the other variables except the am variable that is plot in colour in each plot. Each plot looks like this:
g1<- ggplot(mtcars, aes(x=mpg, y=cyl, color=am)) + geom_point(shape=1)
g2<- ggplot(mtcars, aes(x=mpg, y=disp, color=am)) + geom_point(shape=1)
g3...
Only the y axis changes from one plot to the other. I have done the plots form g1 to g9, y axis being any of the following:
variables<- c ("cyl","disp","hp","drat","wt","qsec","vs","gear","carb")
I am sure there must be a more elegant way to generate all 9 plots, but cannot figure out
Any help?
If you want the plots in g1...g_n:
g <- lapply(variables, function(var) {
ggplot(mtcars, aes_string(x="mpg", y=var, color="am")) + geom_point(shape=1)
})
names(g) <- paste0("g", seq(g))
list2env(g, .GlobalEnv)

Plotting continuous and discrete series in ggplot with facet

I have data that plots over time with four different variables. I would like to combine them in one plot using facet_grid, where each variable gets its own sub-plot. The following code resembles my data and the way I'm presenting it:
require(ggplot2)
require(reshape2)
subm <- melt(economics, id='date', c('psavert','uempmed','unemploy'))
mcsm <- melt(data.frame(date=economics$date, q=quarters(economics$date)), id='date')
mcsm$value <- factor(mcsm$value)
ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line() +
facet_grid(variable~., scale='free_y') +
geom_step(data=mcsm, aes(date, value)) +
scale_y_discrete(breaks=levels(mcsm$value))
If I leave out scale_y_discrete, R complains that I'm trying to combine discrete value with continuous scale. If I include scale_y_discreate my continuous series miss their scale.
Is there any neat way of solving this issue ie. getting all scales correct ? I also see that the legend is alphabetically sorted, can I change that so the legend is ordered in the same order as the sub-plots ?
Problem with your data is that that for data frame subm value is numeric (continuous) but for the mcsm value is factor (discrete). You can't use the same scale for numeric and continuous values and you get y values only for the last facet (discrete). Also it is not possible to use two scale_y...() functions in one plot.
My approach would be to make mcsm value as numeric (saved as value2) and then use them - it will plot quarters as 1,2,3 and 4. To solve the problem with legend, use scale_color_discrete() and provide breaks= in order you need.
mcsm$value2<-as.numeric(mcsm$value)
ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
facet_grid(variable~., scale='free_y') + geom_step(data=mcsm, aes(date, value2)) +
scale_color_discrete(breaks=c('psavert','uempmed','unemploy','q'))
UPDATE - solution using grobs
Another approach is to use grobs and library gridExtra to plot your data as separate plots.
First, save plot with all legends and data (code as above) as object p. Then with functions ggplot_build() and ggplot_gtable() save plot as grob object gp. Extract from gp only part that plots legend (saved as object gp.leg) - in this case is list element number 17.
library(gridExtra)
p<-ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
facet_grid(variable~., scale='free_y') + geom_step(data=mcsm, aes(date, value2)) +
scale_color_discrete(breaks=c('psavert','uempmed','unemploy','q'))
gp<-ggplot_gtable(ggplot_build(p))
gp.leg<-gp$grobs[[17]]
Make two new plot p1 and p2 - first plots data of subm and second only data of mcsm. Use scale_color_manual() to set colors the same as used for plot p. For the first plot remove x axis title, texts and ticks and with plot.margin= set lower margin to negative number. For the second plot change upper margin to negative number. faced_grid() should be used for both plots to get faceted look.
p1 <- ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
facet_grid(variable~., scale='free_y')+
theme(plot.margin = unit(c(0.5,0.5,-0.25,0.5), "lines"),
axis.text.x=element_blank(),
axis.title.x=element_blank(),
axis.ticks.x=element_blank())+
scale_color_manual(values=c("#F8766D","#00BFC4","#C77CFF"),guide="none")
p2 <- ggplot(data=mcsm, aes(date, value,group=1,col=variable)) + geom_step() +
facet_grid(variable~., scale='free_y')+
theme(plot.margin = unit(c(-0.25,0.5,0.5,0.5), "lines"))+ylab("")+
scale_color_manual(values="#7CAE00",guide="none")
Save both plots p1 and p2 as grob objects and then set for both plots the same widths.
gp1 <- ggplot_gtable(ggplot_build(p1))
gp2 <- ggplot_gtable(ggplot_build(p2))
maxWidth = grid::unit.pmax(gp1$widths[2:3],gp2$widths[2:3])
gp1$widths[2:3] <- as.list(maxWidth)
gp2$widths[2:3] <- as.list(maxWidth)
With functions grid.arrange() and arrangeGrob() arrange both plots and legend in one plot.
grid.arrange(arrangeGrob(arrangeGrob(gp1,gp2,heights=c(3/4,1/4),ncol=1),
gp.leg,widths=c(7/8,1/8),ncol=2))

Resources