Как удлинить определенные отметки в ggplot с фасетной сеткой? - PullRequest
0 голосов
/ 07 декабря 2018

Я хочу более длинные отметки для тех, у кого есть метки в сетке фасетов.Итак, я проработал эту попытку и попытался адаптировать ее к диаграммам с гранями с сеткой, например:

Определение разрывов и меток, минорных и мажорных:

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

Нормальный участок:

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

Управляющий участок:

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

Рисование участка:

library(grid)
grid.newpage()
grid.draw(g.f)

Выход:

enter image description here

Я выполнил все шаги связанного ответа, только что адаптированныйэто к ситуации, что есть списки в гроб.Но более длинные отметки не будут отображаться.

Кто-нибудь видит, что я сделал не так?

Или, может быть, есть другой способ удлинить отметки осей тех отметок осей, которые имеют метки?

Ожидаемый результат:

В конце отметки всех трех графиков должны выглядеть следующим образом:

enter image description here


Данные:

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

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

А вот пересмотренный код, который я начал, с несколькими меньшими циклами for.

# 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
0 голосов
/ 07 декабря 2018

Я уверен, что вы могли бы улучшить это.Я просто поработал над этим, правильно вытащил вещи и вставил обратно. В основном, сравнивая его с одним сюжетом, а затем заставляя его зацикливаться на списке гробов.

Диапазон и разрывы могут понадобитьсяизменить, так как здесь они все одинаковые, но с разными x-axes вы можете настроить разрывы соответствующим образом.

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

# breaks and labels, minor and major
range.f <- 1:(max(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(min(range.f), max(range.f), minor.f)

every_nth.lt <- function (x, nth) {x[1:nth != 1] <- ""; x}
# (lite version of https://stackoverflow.com/a/34533473/6574038)

labels.f <- every_nth.lt(range.f, major.f)

n_minor.f <- major.f / minor.f - 1

# plot
library(ggplot2)
library(grid)
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 <- c()
for(i in seq_along(xaxis.f)) {
  ticks.f[[i]] <- xaxis.f[[i]]$children[[2]]
}


marks.f <- c()
for(i in seq_along(ticks.f)) {
  marks.f[[i]] <- ticks.f[[i]][1]$grobs
}



# editing y-positions of tick marks
for(i in seq_along(marks.f)) {
  marks.f[[i]][[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)))
}
# 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

# plot
grid.newpage()
grid.draw(g.f)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...