Extending plot window beyond x-axis labels in ggplot - r

In ggplot I have a graph whose x-axis labels extend beyond the plot window in RStudio even if I try to export the picture and no matter how wide I make the picture. Below is my current solution using limits in scale_x_continuous. Is it possible to have the picture extend so that I can capture my last x-axis label (i.e., 25021643) but without having the line segment extend?
Code to reproduce above:
library(ggplot2)
p <-
ggplot(NULL) +
xlab("x-axis") +
theme_bw() +
scale_x_continuous(breaks = as.integer(seq(0,25021643,(25021643/4))), limits=c(0,26021643),labels = as.integer(seq(0,25021643,(25021643/4))), expand = c(0,0)) +
scale_y_continuous(limits = c(-1, (nrow(chr5)+1)), expand = c(0,0)) +
geom_hline(yintercept = -1) +
geom_segment(aes(x = 0, y = -1, xend = 0, yend = -0.9)) +
geom_segment(aes(x = 25021643, y = -1, xend = 25021643, yend = -0.9)) +
theme(panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
panel.border=element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.x = element_line(size=1),
axis.title.x = element_text(size=20),
axis.text.x = element_text(size=20))
p

Adding plot.margin=unit(c(0,20,0,0),"mm") seemed to do the job.

You may also use:
plot.margin = margin(r = 20, unit = "mm")
Just another way of doing the same thing, but avoiding writing the values for all sides of the plot: 't' is top, 'r' is right, 'l' is left, and 'b' is bottom. You can write all or any sides you wish separated by a comma:
plot.margin = margin(r = 20, l = 30, b = 15, t = 40, unit = "mm")
or, if you wish to use standard units ('pt'):
plot.margin = margin(r = 20)

Related

Fixing margins in ggplot2

I have a plot whose margins are slightly askew and need to be removed. So there should be no empty grey along the bottom or at the left and right of the plot. The dots should go right against the axis's. I think part of the problems may be my last two annotation lines. I tried adding + theme(plot.margins = unit(c(0.1,0.1,0.1,0.1), "cm")) in the last line that defines my plot but this just returns an error:
Error: Theme element `plot.margins` is not defined in the element hierarchy.
`
pvalplot<-function(var, maintitle) {
pvalall<-as.data.frame(c(t(var)))
pvalall$Sample_Size<-c((1:(5*162)),(1:(11*162)),(1:(3*162)),(1:(5*162)),(1:(13*162)),(1:(3*162)),(1:(5*162)))
pvalall$Domain<-c(rep("Physical",5*162),rep("Perinatal",11*162),rep("Developmental",3*162),
rep("Lifestyle-Life Events",5*162),rep("Parental-Family",13*162),rep("School",3*162),
rep("Neighborhood",5*162))
pvalall$Domain <- factor(pvalall$Domain,
levels = c("Physical", "Perinatal", "Developmental",
"Lifestyle-Life Events", "Parental-Family",
"School","Neighborhood"))
pvalall[,1]<-ifelse(pvalall[,1]<1e-20,1e-20,pvalall[,1])
names(pvalall)[1]<-"P-Values"
pvalexp.labels= rep("",45*162)
for (i in c(1:45)){
j=i*162-81
pvalexp.labels[j]=rownames(var)[i]
} #makes list of empyt labels that w
p<-ggplot(pvalall,aes(x = 1:nrow(pvalall), y = -log10(pvalall[,1])))+
geom_point(aes(color = Domain,size=5),
alpha = 0.7, size=1)
p+ylab(expression(atop(" -log10(P-Values)")))+
ylim(0,20)+
xlab(element_blank())+
theme(legend.title=element_blank())+
scale_x_continuous( breaks=c(1:45)*162-81, labels = rownames(var))+
theme_classic()+
theme(axis.title.x = element_blank())+
theme(axis.ticks.x = element_blank())+
theme(axis.title.y = element_text(size = 25))+
theme(text = element_text(size=25))+
theme(legend.title=element_blank())+
theme(legend.position=c(0.8,0.7))+
geom_abline(slope=0,intercept=-log10(c(var)[astsa::FDR(c(var))]),linetype = "dashed")+
geom_abline(slope=0,intercept=5.2,linetype = "dashed")+
ggtitle(maintitle)+
theme(plot.title = element_text(hjust = 0.5))+
theme(
legend.box.background = element_rect(),
legend.box.margin = margin(6, 6, 6, 6))+
theme_update(axis.text.x = element_text(angle = 35, size = 6.5, vjust = 1, hjust=1, color = "black")) +
annotate("text", label = expression(paste("FDR P-value","=0.05")),size=5, x=1000,y=-log10(c(var)[astsa::FDR(c(var))])-0.5, color="black",parse=TRUE)+
annotate("text", label = expression(paste("Bonferroni P-value","=0.05")),size=5, x=1200,y=5.7, color="black",parse=TRUE)
}#end of plotting
You can insert a line
scale_y_continuous(expand = c(0, 0)) +
in your plot command chain.

Axes tick marks at extremes of axes do not align with panel border

I am aware ggplot by default puts 'padding' between the axes and the data. I wish for the origin of the axes to be an actual number, e.g. 0. I know this can be done using scale_y_continuous(expand = c(0, 0)) and scale_x_continuous(expand = c(0, 0)), however without the 'padding' the tick marks do not align correctly with the panel borders. It is as if they are not positioned correctly.
Consider this using mtcars data:
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
scale_y_continuous(expand = c(0, 0), breaks = seq(0, 5, by = 1), limits = c(0, 5)) +
scale_x_continuous(expand = c(0, 0), breaks = seq(10, 35, by = 5), limits = c(10, 35))
This returns a plot without padding, but you cannot really make out the misalignment yet because the panel border is white.
Now, plot this (panel border has been defined):
p +
theme(
panel.border = element_rect(size= 1, fill=NA),
axis.ticks = element_line(size = 1, colour ="black"))
The tick at the top of the y axis and the tick at the right of the x axis are not aligned. It is now clear because the panel border is black. I thought perhaps I could mess around with the thickness of the ticks but it does not help. I also thought it was something to do with the major and minor lines of the panel but the following doesn't make a difference:
p +
theme(
panel.border = element_rect(size= 1, fill=NA),
axis.ticks = element_line(size = 1, colour ="black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
Interestingly, if I remove the panel border and instead add in a defined x and y axis line it does look a bit better because it's harder to see the misalignment unless you really zoom in:
p +
theme(
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"),
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black"),
axis.ticks = element_line(size = 0.5, colour ="black"),
panel.border = element_blank())
I am not satisfied with the answer given in Tick marks misaligned with panel in ggplot2 [R] and think there must be a way around this?
Any thoughts? I am missing something here...
The accepted answer to the question you've linked to is correct, this visual misalignment is caused by the panel clipping that occurs. What that answer doesn't tell you is that you can disable the clipping in coord_cartesian(clip = "off"), and instead that answer goes to this roundabout way of adjusting the clipping in the gtable.
Below is an example of turning the clipping off.
library(ggplot2)
ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
scale_y_continuous(expand = c(0, 0), breaks = seq(0, 5, by = 1), limits = c(0, 5)) +
scale_x_continuous(expand = c(0, 0), breaks = seq(10, 35, by = 5), limits = c(10, 35)) +
coord_cartesian(clip = "off") +
theme(panel.border = element_rect(size = 1, fill = NA),
axis.ticks = element_line(size = 1))
#> Warning: Removed 3 rows containing missing values (geom_point).
I'll notify the answer to that other question of the coord_cartesian() option.

R annotate greek letter with apostrophe and text

I am trying to annotate text in a ggplot2 plot combining greek letter with apostrophe and text. Till now I am not able to achieve the probem.
For now, I can write the following label, combining annotate and geom_text, here is the code:
ggplot(Lab_all_direct_shear)+
geom_rect(aes(xmin = 0, xmax = 20, ymin = 0, ymax = 120), color = NA, fill="grey", alpha = 0.05)+
geom_segment(linetype = 8,color="#666666",aes(x = 0, y = 0, xend = 55, yend = 88.649))+
geom_point(size=3,shape=21,fill ="#F8766D",aes(x=constitutive_normal_stress_15_kPa,y=constant_volume_shear_strenght_15_kPa))+
geom_point(size=3,shape=21,fill ="#00BA38",aes(x=constitutive_normal_stress_19_kPa,y=constant_volume_shear_strenght_19_kPa))+
geom_point(size=3,shape=21,fill ="#619CFF",aes(x=constitutive_normal_stress_25_kPa,y=constant_volume_shear_strenght_25_kPa))+
scale_x_continuous(limits = c(0,60),breaks=c(0,10,20,30,40,50,60),expand = c(0, 0)) +
scale_y_continuous(limits = c(0,120), breaks=c(0,10,20,30,40,50,60,70,80,90,100,110,120),expand = c(0, 0)) +
labs(x=expression(~sigma[n]~+~s~S[r]~(kPa)),y = "",title="") +
annotate("text", x = 54, y = 70, label = "= 58.2°",size=4)+
geom_text(x=50,y=70,label="phi",parse=TRUE)+
theme_bw() +
theme(plot.title = element_text(size=10, face="bold", hjust=0.5),
axis.title = element_text(size=10),
axis.title.x = element_text(angle=0, hjust=0.5),
axis.title.y = element_blank(),
axis.text = element_text(size=10,color="black"),
axis.text.x = element_text(size=10),
axis.text.y = element_blank(),
panel.grid.major = element_line(color= NA),
panel.grid.minor = element_line(color= NA),
plot.margin=unit(c(0.1,0.2,0.1,0.4), "cm"), #The four numbers are c(top,right,bottom,left)
legend.text = element_text(size=10),
legend.title = element_text(size=10),
legend.position = "none")
And the result in R ggplot2 package:
greek letter annotate without apostrophe
I have tried different combinations (declaring it as expression, paste, etc, but I am not able to solve it).
I would like to obtain a plot like this in excel, with the following annotation (phi with superscript apostrophe in combination with text):
excel plot with desired annotation
Any help will be highly appreciated!
Thanks in advance,
Raül
Here's a sample image:
data <- data.frame(x = 1:10, y = 1:10)
ggplot(data, aes(x, y))+
geom_point(color = "blue")+
geom_line(linetype = "dashed", color = "blue")+
annotate("text", x = 6, y = 7, label = "phi*' \\''==58^o",
parse = TRUE)+
theme_bw()

Grid Lines Are too Wide in Density Plot

I have implemented a density plot in R using ggplot2 (updated version):
library(ggplot2)
densityplot <- function(values, pointsInTime, title) {
df <- data.frame(x = 1:length(pointsInTime), y = values)
p <-
ggplot(df, aes(x = x, y = y)) +
geom_area(alpha = 0.5, fill = '#42a5ed') +
geom_line(color = '#42a5ed') +
geom_point(
color = '#42a5ed',
fill = 'white',
shape = 21,
size = 3
) +
scale_x_continuous(labels = pointsInTime, breaks = 1:length(df$x)) +
theme(
panel.background = element_blank(),
panel.grid.major.y = element_line(color = '#dddddd'),
panel.grid.major.x = element_blank(),
axis.text.x = element_text(margin = margin(10, 0, 0, 0)),
axis.text.y = element_text(margin = margin(0, 10, 0, 0)),
plot.title = element_text(size = 18),
axis.title = element_blank(),
axis.ticks = element_blank()
) +
coord_cartesian(expand = FALSE, xlim=min(df$x):max(df$x), ylim=0:max(df$y)+1) +
labs(title = title)
p
}
densityplot(sample(10:25, size = s),
format(ISOdate(2017, 1:12, 1), "%b"),
"Number of Fatal Accidents")
Update: Now the 'Dec' label on the bottom right is cut off. Is there a way to add margin or spacing?
Initial Problem: The horizontal grid lines in the background are too wide. I want them to just begin where the 'Jan' tick resp. to end where the 'Dec' tick would be; just covering the actual plot area, not the whole panel. However, I want to have the space around the panel to stay the same, i.e. the axis labels should not move towards the data.

ggplot2 x - y axis intersect while keeping axis labels

I posted my original question yesterday which got solved perfectly here
Original post
I made a few addition to my code
library(lubridate)
library(ggplot2)
library(grid)
### Set up dummy data.
dayVec <- seq(ymd('2016-01-01'), ymd('2016-01-10'), by = '1 day')
dayCount <- length(dayVec)
dayValVec1 <- c(0,-0.22,0.15,0.3,0.4,0.10,0.17,0.22,0.50,0.89)
dayValVec2 <- c(0,0.2,-0.17,0.6,0.16,0.41,0.55,0.80,0.90,1.00)
dayValVec3 <- dayValVec2
dayDF <- data.frame(Date = rep(dayVec, 3),
DataType = factor(c(rep('A', dayCount), rep('B', dayCount), rep('C', dayCount))),
Value = c(dayValVec1, dayValVec2, dayValVec3))
ggplot(dayDF, aes(Date, Value, colour = DataType)) +
theme_bw() +
ggtitle("Cumulative Returns \n") +
scale_color_manual("",values = c("#033563", "#E1E2D2", "#4C633C"),
labels = c("Portfolio ", "Index ", "In-Sample ")) +
geom_rect(aes(xmin = ymd('2016-01-01'),
xmax = ymd('2016-01-06'),
ymin = -Inf,
ymax = Inf
), fill = "#E1E2D2", alpha = 0.03, colour = "#E1E2D2") +
geom_line(size = 2) +
scale_x_datetime(labels = date_format('%b-%d'),
breaks = date_breaks('1 day'),
expand = c(0,0)) +
scale_y_continuous( expand = c(0,0), labels = percent) +
theme(axis.text.x = element_text(angle = 90),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
axis.text = element_text(size = 20, colour = "#033563"),
axis.title.x = element_text(hjust = 2),
plot.title = element_text(size = 40, face = "bold", colour = "#033563"),
legend.position = 'bottom',
legend.text = element_text(colour = "#033563", size = 20),
legend.key = element_blank()
)
which produces this output
The only thing that I still cannot get working is the position of the x axis. I want the x axis to be at y = 0 but still keep the x axis labels under the chart, exactly as in the excel version of it. I know the data sets are not the same but I didn't have the original data at hand so I produced some dummy data. Hope this was worth a new question, thanks.
> grid.ls(grid.force())
GRID.gTableParent.12660
background.1-5-7-1
spacer.4-3-4-3
panel.3-4-3-4
grill.gTree.12619
panel.background.rect.12613
panel.grid.minor.y.zeroGrob.12614
panel.grid.minor.x.zeroGrob.12615
panel.grid.major.y.polyline.12617
panel.grid.major.x.zeroGrob.12618
geom_rect.rect.12607
GRID.polyline.12608
panel.border.rect.12610
axis-l.3-3-3-3
axis.line.y.polyline.12631
axis
axis-b.4-4-4-4
axis.line.x.polyline.12624
axis
xlab.5-4-5-4
ylab.3-2-3-2
guide-box.6-4-6-4
title.2-4-2-4
> grid.gget("axis.1-1-1-1", grep=T)
NULL
ggplot2 doesn't make this easy. Below is one-way to approach this interactively. Basically, you just grab the relevant part of the plot (the axis line and ticks) and reposition them.
If p is your plot
p
grid.force()
# grab the relevant parts - have a look at grid.ls()
tck <- grid.gget("axis.1-1-1-1", grep=T)[[2]] # tick marks
ax <- grid.gget("axis.line.x", grep=T) # x-axis line
# add them to the plot, this time suppressing the x-axis at its default position
p + lapply(list(ax, tck), annotation_custom, ymax=0) +
theme(axis.line.x=element_blank(),
axis.ticks.x=element_blank())
Which produces
A quick note: the more recent versions of ggplot2 have the design decision to not show the axis. Also changes to axis.line are not automatically passed down to the x and y axis. Therefore, I tweaked your theme to define axis.line.x and axis.line.y separately.
That siad, perhaps its easier (and more robust??) to use geom_hline as suggested in the comments, and geom_segment for the ticks.

Resources