I want longer tick marks for those with labels in a facet grid. So I worked through this attempt and tried to adapt it to facet gridded plots like so:
Defining breaks and labels, minor and major:
range.f <- range(unique(df1$weeks))
minor.f <- 1 # every 1 week, NOTE: range.f[2] should be divisible by minor.f!
major.f <- 5 # every 5 weeks
breaks.f <- seq(range.f[1], range.f[2], minor.f)
every_nth.lt <- function (x, nth) {x[1:nth != 1] <- ""; x}
# (lite version of https://stackoverflow.com/a/34533473/6574038
# works better for me than `insert_minor()`)
labels.f <- every_nth.lt(sequence(range.f[2]), major.f)
n_minor.f <- major.f / minor.f - 1
Normal plot:
library(ggplot2)
p.f <- ggplot(df1, aes(weeks, births)) +
geom_bar(stat="identity", fill="#F48024") + theme_bw() +
scale_x_continuous(breaks=breaks.f, labels=labels.f) +
coord_cartesian(xlim=range.f) +
facet_wrap(year ~ .) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(margin=margin(t=5, unit="pt")))
Manipulating plot:
g.f <- ggplotGrob(p.f)
xaxis.f <- g.f$grobs[grep("^axis-b", g.f$layout$name)] # get x-axes
ticks.f <- do.call(c, lapply(lapply(xaxis.f, "["),
function(x) x$children[[2]])) # get ticks
marks.f <- ticks.f$grobs[[1]] # get tick marks
# editing y-positions of tick marks
marks.f$y <- unit.c(unit.c(unit(1, "npc") - unit(6, "pt"),
unit(1, "npc"),
rep(unit.c(unit(1, "npc") - unit(3, "pt"),
unit(1, "npc")), n_minor.f)))
# putting tick marks back into plot
ticks.f$grobs[[1]] <- marks.f
for(i in seq_along(xaxis.f)) {
xaxis.f[[i]]$children[[2]]$grob <- ticks.f[[i]]
}
g.f$grobs[grep("^axis-b", g.f$layout$name)] <- xaxis.f
Drawing the plot:
library(grid)
grid.newpage()
grid.draw(g.f)
Yielding:
I followed all the steps of the linked answer, just adapted it to the situation that there are lists in the grob. But, the longer tick marks won't show up.
Does anybody see what I did wrong?
Or, maybe is there another way how to lengthen the axis ticks of those axis ticks which have labels?
Expected Output:
At the end the tick marks of all three plots should look like this:
Data:
tmp <- data.frame(date=as.Date(sample(1:1095, 10000, replace=TRUE),
origin="2014-01-01"),
births=sample(0:10, 10000, replace=TRUE))
tmp$year <- factor(substr(tmp$date, 1, 4))
df1 <- aggregate(births ~ date + year, tmp, sum)
rm(tmp) # remove tmp
df1$weeks <- as.integer(strftime(lubridate::floor_date(as.Date(df1$date,
format="%m/%d/%Y"),
unit="week"), "%W")) + 1
Adding minor ticks to graphs is very simple. There are two mains ways, using the continuous scale functions such as scale_x_continuous() or using the guides() function, both from ggplot2 . Note that guide_prism_minor() does not work with discrete axes as they do not have minor breaks.
To create a plot in base R with tick marks of larger size, we can make use of axis function tck argument. The tck argument value will decide the size of the tick mark but since the ticks lie below the plot area hence the value will have a negative associated with it. Therefore, it will be like -0.05.
The default value of Y-axis tick marks using ggplot2 are taken by R using the provided data but we can set it by using scale_y_continuous function of ggplot2 package. For example, if we want to have values starting from 1 to 10 with a gap of 1 then we can use scale_y_continuous(breaks=seq(1,10,by=1)).
The axes labels and ticks can be removed in ggplot using the theme() method. This method is basically used to modify the non-data components of the made plot.
And here's the revised code of the way I started, with a few less for
loops.
# Defining breaks and labels, minor and major:
range.f <- range(unique(df1$weeks))
minor.f <- 1 # every 1 week, NOTE: range.f[2] should be divisible by minor.f!
major.f <- 5 # every 5 weeks
breaks.f <- seq(range.f[1], range.f[2], minor.f)
every_nth.lt <- function (x, nth) {x[1:nth != 1] <- ""; x}
# (lite version of https://stackoverflow.com/a/34533473/6574038
# works better for me than `insert_minor()`)
labels.f <- every_nth.lt(sequence(range.f[2]), major.f)
n_minor.f <- major.f / minor.f - 1
# Normal plot:
library(ggplot2)
p.f <- ggplot(df1, aes(weeks, births)) +
geom_bar(stat="identity", fill="#F48024") + theme_bw() +
scale_x_continuous(breaks=breaks.f, labels=labels.f) +
coord_cartesian(xlim=range.f) +
facet_wrap(year ~ .) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(margin=margin(t=5, unit="pt")))
# Manipulating plot:
g.f <- ggplotGrob(p.f)
xaxis.f <- g.f$grobs[grep("^axis-b", g.f$layout$name)] # get x-axes
ticks.f <- lapply(lapply(xaxis.f, "["),
function(x) x$children[[2]]) # get ticks
marks.f <- lapply(lapply(ticks.f, "["),
function(x) x[1]$grobs) # get ticks
# editing y-positions of tick marks
library(grid)
marks.f <- lapply(marks.f, function(x) {
x[[1]]$y <- unit.c(unit.c(unit(1, "npc") - unit(6, "pt"),
unit(1, "npc"),
rep(unit.c(unit(1, "npc") - unit(3, "pt"),
unit(1, "npc")), n_minor.f)))
x
})
# putting tick marks back into plot
for(i in seq_along(ticks.f)) {
ticks.f[[i]]$grobs[[1]] <- marks.f[[i]][[1]]
}
for(i in seq_along(xaxis.f)) {
xaxis.f[[i]]$children[[2]] <- ticks.f[[i]]
}
g.f$grobs[grep("^axis-b", g.f$layout$name)] <- xaxis.f
# Drawing the plot:
grid.newpage()
grid.draw(g.f)
tmp <- data.frame(date=as.Date(sample(1:1095, 10000, replace=TRUE),
origin="2014-01-01"),
births=sample(0:10, 10000, replace=TRUE))
tmp$year <- factor(substr(tmp$date, 1, 4))
df1 <- aggregate(births ~ date + year, tmp, sum)
rm(tmp) # remove tmp
df1$weeks <- as.integer(strftime(lubridate::floor_date(as.Date(df1$date,
format="%m/%d/%Y"),
unit="week"), "%W")) + 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With