I have a dataframe with ~37000 rows that contains 'name' in string format and 'UTCDateTime' in posixct format and am using it to produce a facet wrapped density plot of time grouped by the names:
I also have a separate density plot of posixct datetime data from an entirely different dataframe:
I want to overlay this second density plot on each individual facet_wrapped plot in the first density plot. Is there a way to do that? In general, if I have plots of any kind that are facet wrapped and another plot of the same type but different data that I want to overlay on each facet of the facet wrap, how do I do so?
This should in theory be as simple as not having the column that you're facetting by in the second dataframe. Example below:
library(ggplot2)
ggplot(iris, aes(Sepal.Width)) +
geom_density(aes(fill = Species)) +
geom_density(data = faithful,
aes(x = eruptions)) +
facet_wrap(~ Species)
Created on 2020-08-12 by the reprex package (v0.3.0)
EDIT: To get the densities on the same scale for the two types of data, you can use the computed variables using after_stat()*:
ggplot(iris, aes(Sepal.Width)) +
geom_density(aes(y = after_stat(scaled),
fill = Species)) +
geom_density(data = faithful,
aes(x = eruptions,
y = after_stat(scaled))) +
facet_wrap(~ Species)
* Prior to ggplot2 v3.3.0 also stat(variable) or ...variable....
Related
I am trying to make a scatter plot with ggplot to show time watching TV on x axis and immigrant sentiment on y axis.
The code I am using is
ggplot(totalTV,
aes(x = dfnew.TV.watching..total.time.on.average.weekday,
y = dfnew.Immigrant.Sentiment)) +
geom_point()
I am getting this output
My table is so, with first variable being character, and subsequent two being numeric:
Any idea on how to produce a representative scatter of the outcome?
Cheers
Here are some examples using the mtcars dataset.
library(ggplot2)
# Original
ggplot(mtcars,aes(factor(cyl),mpg)) +
geom_point()
# Jitter
ggplot(mtcars,aes(factor(cyl),mpg)) +
geom_jitter(width = .2) # Control spread with width
# Violin plot
ggplot(mtcars,aes(factor(cyl),mpg)) +
geom_violin()
# Boxplot
ggplot(mtcars,aes(factor(cyl),mpg)) +
geom_boxplot()
# Remember that different geoms can be combined
ggplot(mtcars,aes(factor(cyl),mpg)) +
geom_violin() +
geom_jitter(width = .2)
# Or something more exotic ala Raincloud-plots
# https://micahallen.org/2018/03/15/introducing-raincloud-plots/
We are presenting outcome data using boxplots and group these for different approaches using facet_grid with ggplot2 and geom_boxplot.
We would like to add more space between the boxplots and the frame of the facet_grid as shown in the graphic below.
The code we used included ggplot_build and gglot_table.
Which parameter of ggplot_build needs to be set to get more space in the panels?
require(ggplot2)
require(grid)
dat <- rbind(data.frame(approach=1,product=1,value=seq(1,20,0.5)),
data.frame(approach=1,product=2,value=seq(5,15,0.3)),
data.frame(approach=1,product=3,value=seq(5,17,0.2)),
data.frame(approach=2,product=1,value=seq(1,13,0.3)),
data.frame(approach=2,product=2,value=seq(3,18,0.5)),
data.frame(approach=2,product=3,value=seq(4,25,0.7)),
data.frame(approach=3,product=1,value=seq(1,15,0.6)),
data.frame(approach=3,product=2,value=seq(3,16,0.5)),
data.frame(approach=3,product=3,value=seq(1,10,0.1)))
dat$product<-as.factor(dat$product)
gg1<-ggplot(dat, aes(x =product, y = value)) +
geom_boxplot() +
facet_grid(cols=vars(approach))
gt = ggplot_gtable(ggplot_build(gg1))
grid.draw(gt)
ggplot(dat, aes(x =product, y = value)) +
geom_boxplot() +
coord_cartesian(xlim = c(1.2, 2, 2.8)) +
facet_grid(cols=vars(approach))
I am trying to create a heat map, where each tile is a month. If I use the dates as a data date type, I get lines over my image that are not acceptable.
So my solution has been to to treat the date as a factor
The problem is that the axis is not presentable. Is there a way to merge the two plots with the x axis from the first plot, but the tiles from the second plot?
ggplot(df, aes(x = factor(Var2),
y = factor(desc(Var1)),
fill = value)) +
As a reproducible example:
df <- read.table("","Var1","Var2","value","Col"
"1",2001-01-31,2001-01-31,-0.0118511587908436,"blue"
"2",2001-02-28,2001-01-31,0,"white"
"3",2001-03-30,2001-01-31,0,"white"
"4",2001-04-30,2001-01-31,0,"white"
"5",2001-05-31,2001-01-31,0,"white"
"6",2001-06-29,2001-01-31,0,"white")
ggplot(dff, aes(x = factor(Var2),
y = factor(desc(Var1)),
fill = Col)) +
geom_tile() +
scale_x_discrete(breaks=pretty(p$Var2))
Output from example
Use dates but manually remove the grid. You can do it by adding + theme(panel.grid = element_blank()) to the plot.
I want to make nice boxplot with ggplot2.
NB: the airquality data from ggplot2 can illustrated what I want to do but in my own data I have an additional column for year(1900:2000).
I make simple boxplot with this command:
tapply(data$Temp, substr(data$Month, 1,3),na.rm=TRUE, summary) #data=airquality
boxplot(Temp~Month, data=data, na.action = NULL, main="1900-2000")
It have this graphic:
But I when try with ggplot2 with this command:
ggplot(data, aes(Month, Temp),facet= Month~.) + geom_boxplot()
It get this graphic
In the same plot I want to view the corresponding Value and boxplot for each month like graphic1
Because Month is a continuous variable you will need to 'factorize' this variable to have seperate boxplots:
ggplot(airquality, aes(factor(Month), Temp)) + geom_boxplot()
alternatively you can use the group aesthetic:
ggplot(airquality, aes(Month, Temp, group = Month)) + geom_boxplot()
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))