Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lengthen specific tick marks in facet gridded ggplot?

Tags:

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:

enter image description here

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:

enter image description here


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
like image 720
jay.sf Avatar asked Dec 06 '18 22:12

jay.sf


People also ask

How do I add a minor tick mark in ggplot2?

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.

How do you make a tick bigger in R?

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.

How do I change the number of ticks in ggplot2?

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)).

How to get rid of tick marks in ggplot?

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.


1 Answers

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)

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
like image 93
jay.sf Avatar answered Oct 13 '22 02:10

jay.sf