Say I have the following data:
require(ggplot2)
set.seed(123)
data <- data.frame(x = sample(1:20, 100, replace = TRUE))
I want to create a dot plot of data$x, so this is what I do:
ggplot(data, aes(x)) +
geom_dotplot(binwidth = 1) +
scale_x_continuous(breaks = seq(1, 20, 1)) +
scale_y_continuous(breaks = NULL)
Which gives me this:
I would like to get rid of those vertical grid lines, so I add theme(line = element_blank()) to my ggplot statement. The problem is that command also eliminates the tick marks, which I would like to keep. How can I hide the grid lines whilst keeping their respective ticks?
I would also like to know how I can change the grid lines so they'll be drawn every 1:20, not at every 0.5 mark.
I've looked for those answers in ?title() and ?geom_dotplot, tried a couple of things, to no avail. Appreciate the help!
Use panel.grid
theme(panel.grid = element_blank())
If you want the grid lines to be drawn every 1:20, not at every 0.5 mark.
theme(panel.grid.minor = element_blank(),
panel.grid.major = element_line(colour = "white",size=0.75))
you might find answers here
opts has been changed to theme. but the thing about grid.major.x, grid.minor.y should set on the track
To get rid of the major grid line, for example
ggplot(data, aes(x)) +
geom_dotplot(binwidth = 1) +
scale_x_continuous(breaks = seq(1, 20, 1)) +
scale_y_continuous(breaks = NULL) + theme(panel.grid.major = element_blank())
What is the command for specifying the line colours in a ggplot using geom_step()?
The default colours are working fine, I just want to alter them to my preferred colours.
I have two groups, and my ggplot code starts:
ggplot(WomenAgeComparison, aes(x=IntegerAge, y=CumAgePercent, colour=DataSource)) +
geom_step()
The two groups plot fine. Everything works fine except for changing the line colours.
I have tried:
scale_color_manual(values=c("mediumorchid2",'blue'))
which gave the error
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
and didn't override the existing colours.
I also tried
scale_color_continuous(values=c("mediumorchid2",'blue'))
which gave the error
Error in continuous_scale(aesthetics, "gradient", seq_gradient_pal(low, :
unused argument (values = c("mediumorchid2", "blue"))
The example of two colours on this page used two separate geom_step() lines. Surely there is an easier way?
What is the command to use? Is there a scale_color command to use, or should it be specified in the aesthetics bracket? If the latter, how do I do that?
Updated to show full ggplot code:
ggplot(WomenAgeComparison, aes(x=IntegerAge, y=CumAgePercent, colour=DataSource)) +
geom_step() +
scale_color_manual(values=c("mediumorchid2",'blue')) +
xlab("Age (years)") + ylab("Cumulative proportion") +
scale_x_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 20), expand = c(0, 0)) +
scale_y_continuous(limits = c(0,1), breaks = seq(0, 1, by = .2), expand = c(0, 0)) +
scale_color_discrete(name = "Data source", labels = c("Synthetic data\nestimates", "Timaru Data\nrandom rounded\ncounts")) +
theme(legend.title = element_text(size = 15),
legend.text = element_text(size = 10),
legend.key.height=unit(1.5, "cm"),
axis.text = element_text(size = 10),
axis.title = element_text(size = 15))
I have the scale_color_discrete only to put in the text I want into the legend title and text. I tried to use the theme element_text options to do it instead, and couldn't get that to work.
I've been stuck on an issue and can't find a solution. I've tried many suggestions on Stack Overflow and elsewhere about manually ordering a stacked bar chart, since that should be a pretty simple fix, but those suggestions don't work with the huge complicated mess of code I plucked from many places. My only issue is y-axis item ordering.
I'm making a series of stacked bar charts, and ggplot2 changes the ordering of the items on the y-axis depending on which dataframe I am trying to plot. I'm trying to make 39 of these plots and want them to all have the same ordering. I think ggplot2 only wants to plot them in ascending order of their numeric mean or something, but I'd like all of the bar charts to first display the group "Bird Advocates" and then "Cat Advocates." (This is also the order they appear in my data frame, but that ordering is lost at the coord_flip() point in plotting.)
I think that taking the data frame through so many changes is why I can't just add something simple at the end or use the reorder() function. Adding things into aes() also doesn't work, since the stacked bar chart I'm creating seems to depend on those items being exactly a certain way.
Here's one of my data frames where ggplot2 is ordering my y-axis items incorrectly, plotting "Cat Advocates" before "Bird Advocates":
Group,Strongly Opposed,Opposed,Slightly Opposed,Neutral,Slightly Support,Support,Strongly Support
Bird Advocates,0.005473026,0.010946052,0.012509773,0.058639562,0.071149335,0.31118061,0.530101642
Cat Advocates,0.04491726,0.07013396,0.03624901,0.23719464,0.09141056,0.23404255,0.28605201
And here's all the code that takes that and turns it into a plot:
library(ggplot2)
library(reshape2)
library(plotly)
#Importing data from a .csv file
data <- read.csv("data.csv", header=TRUE)
data$s.Strongly.Opposed <- 0-data$Strongly.Opposed-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Opposed <- 0-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Slightly.Opposed <- 0-data$Slightly.Opposed-.5*data$Neutral
data$s.Neutral <- 0-.5*data$Neutral
data$s.Slightly.Support <- 0+.5*data$Neutral
data$s.Support <- 0+data$Slightly.Support+.5*data$Neutral
data$s.Strongly.Support <- 0+data$Support+data$Slightly.Support+.5*data$Neutral
#to percents
data[,2:15]<-data[,2:15]*100
#melting
mdfr <- melt(data, id=c("Group"))
mdfr<-cbind(mdfr[1:14,],mdfr[15:28,3])
colnames(mdfr)<-c("Group","variable","value","start")
#remove dot in level names
mylevels<-c("Strongly Opposed","Opposed","Slightly Opposed","Neutral","Slightly Support","Support","Strongly Support")
mdfr$variable<-droplevels(mdfr$variable)
levels(mdfr$variable)<-mylevels
pal<-c("#bd7523", "#e9aa61", "#f6d1a7", "#999999", "#c8cbc0", "#65806d", "#334e3b")
ggplot(data=mdfr) +
geom_segment(aes(x = Group, y = start, xend = Group, yend = start+value, colour = variable,
text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
geom_hline(yintercept = 0, color =c("#646464")) +
coord_flip() +
theme(legend.position="top") +
theme(legend.key.width=unit(0.5,"cm")) +
guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position
scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
theme(legend.title = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(axis.title.y = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.text.x = element_blank()) +
theme(legend.key = element_rect(fill = "white")) +
scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.grid.major = element_line(colour = "#CBCBCB"))
The plot:
I think this works, you may need to play around with the axis limits/breaks:
library(dplyr)
mdfr <- mdfr %>%
mutate(group_n = as.integer(case_when(Group == "Bird Advocates" ~ 2,
Group == "Cat Advocates" ~ 1)))
ggplot(data=mdfr) +
geom_segment(aes(x = group_n, y = start, xend = group_n, yend = start + value, colour = variable,
text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
scale_x_continuous(limits = c(0,3), breaks = c(1, 2), labels = c("Cat", "Bird")) +
geom_hline(yintercept = 0, color =c("#646464")) +
theme(legend.position="top") +
theme(legend.key.width=unit(0.5,"cm")) +
coord_flip() +
guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position
scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
theme(legend.title = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(axis.title.y = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.text.x = element_blank()) +
theme(legend.key = element_rect(fill = "white"))+
scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.grid.major = element_line(colour = "#CBCBCB"))
produces this plot:
You want to factor the 'Group' variable in the order by which you want the bars to appear.
mdfr$Group <- factor(mdfr$Group, levels = c("Bird Advocates", "Cat Advocates")
library(tidyverse)
library(grid)
df <- tibble(
date = as.Date(40100:40129, origin = "1899-12-30"),
value = rnorm(30, 8)
)
p1 <- ggplot(df, aes(date, value)) +
geom_line() +
scale_x_date(date_breaks = "1 day") +
theme(
axis.title.x = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5)
) +
coord_cartesian(xlim = c(min(df$date) + 0, max(df$date) - 0))
p2 <- ggplot(df, aes(date, value)) +
geom_bar(stat = "identity") +
scale_x_date(date_breaks = "1 day") +
theme(
axis.title.x = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5)
) +
coord_cartesian(xlim = c(min(df$date) + 0, max(df$date) - 0))
Let's create the plots p1 and p1 as shown above. I can plot these stacked on top of each other with widths that are exactly identical (zoom to full screen to make it obvious). Note that the dates line up perfectly. Code is directly below.
grid.newpage()
grid.draw(rbind(ggplotGrob(p1), ggplotGrob(p2), size = "last"))
Unfortunately I can't use ggsave() with this code chunk above so I go to the gridExtra package.
gridExtra::grid.arrange(p1, p2)
This almost works, but notice the dates don't quite line up perfectly, in a vertical fashion comparing the top graph to the bottom graph. So... what's the equivalent to rbind()s size = "last" to get me two grid.arrange'd objects with exactly identical widths (so the dates line up properly)?
As an alternative to grid, the new patchwork library might help here. It works with ggsave and does a good job of aligning plots.
https://github.com/thomasp85/patchwork
patchwork::plot_layout(p1 / p2)
I discovered a solution using the egg package which I think is included as part of ggplot2. I'm going to go this route to prevent having to install patchwork. It appears you need R 3.5+ to be able to install patchwork.
egg::ggarrange(p1, p2)
p <- egg::ggarrange(p1, p2)
ggsave(plot = p, "panel-plot.png")
I'm ploting a Hydrograph but I additionally use facet_grid in R because I have objects with common features.
But when I use facet_grid the plot gets distorted, as shown in the figure below. How can I randerize this?
Note that it is not aligned properly, the scale of the y axis is scrambled, etc.
Among the adjustments I tried, I realized that it is possible to greatly improve this plot. I've created an image based on the above plot, some other attempts on how I'm trying and making some adjustments to paint to demonstrate what I'm trying to do.
Here's my code:
library(ggplot2)
library(grid)
library(gridExtra)
g1 <- ggplot(data_cet,
aes(x = Periodo,
y = Ind_plu)) +
geom_bar(stat = 'identity',
fill = "blue",
position = position_dodge()) +
ylab("Precip.") +
scale_y_reverse(labels = scales::comma) +
theme_bw() +
theme(axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank())
g2 <- ggplot(data_cet,
aes(x = Periodo,
y = Nivel,
colour = Bomba)) +
geom_line(aes(group = 1)) +
scale_color_manual(values = c("#0B775E", "#35274A", "#F2300F")) +
labs(colour = "Status CMB") +
facet_grid(data_cet$arranjo + data_cet$Bacia ~.) +
scale_x_date(breaks = datebreaks_m,
labels = date_format("%b/%y")) +
xlab('Período') + ylab('% Nível') +
theme_bw() +
theme(axis.text.x = element_text(face = "plain",
color = "black",
angle = 90),
axis.text.y = element_text(face = "plain",
color = "black"),
legend.title = element_blank(),
strip.background = element_blank(),
legend.position = "bottom")
g1 <- ggplot_gtable(ggplot_build(g1))
g2 <- ggplot_gtable(ggplot_build(g2))
maxWidth = unit.pmax(g1$widths[2:3], g2$widths[2:3])
g1$widths[2:3] <- maxWidth
g2$widths[2:3] <- maxWidth
plot_hyd <- grid.arrange(g1, g2, ncol = 1, heights = c(1, 3))
ggsave(file = "plot_hyd4.pdf", plot_hyd)
My dataset is too large, my apologize for not showing the dataset and dput().
You could add a widths = c(0.9, 1) to grid.arrange (fiddle with the first number some) to get your graphs to line up along the right side.
Otherwise, ggsave your file to a larger pdf. Your element_text objects, such as the legend, are absolute sizes, so if you scale up the pdf dimensions your graphs will look larger by comparison.
The exact values of widths and ggsave(width, height) are going to depend on you data, and unfortunately will take some trial and error. If you're using something like RStudio, I suggest fiddling with the grid.arrange call and finding the widths argument you like before calling ggsave. When you are ready to experiment with different ggsave width and height arguments, run it at a lower dpi the first few times so it processes more quickly.
Note that since you haven't included your data, I haven't tried to recreate this problem - this is just how I've solved this kind of issue in the past. If these suggestions don't work for you, let me know and I can use some built-in datasets to find another solution
Following the logic of the #Pintintended tip for the code. I adopted the layout_matrix argument.
>
plot_hyd <- grid.arrange(g1, g2,
layout_matrix = rbind(c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,NA),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)))
#ggsave(file="plot_hyd4.jpeg",plot_hyd,width=13,height=16,dpi=200)