R: Как мне использовать coord_cartesian на facet_grid со свободной осью


person cboettig    schedule 31.08.2012    source источник
comment
mt + facet_grid(vs ~ am, scales = "free") + coord_cartesian(ylim = c(3,4)) кажется, работает для меня, или, возможно, я не понимаю вопроса.   -  person mnel    schedule 31.08.2012
comment
Вы также можете использовать facet_wrap, и в этом случае ось X также соответствующим образом усечена mt + facet_wrap(vs ~ am, scales = "free") + coord_cartesian(ylim = c(3,4))   -  person mnel    schedule 31.08.2012
comment
Извините, я должен был быть более ясным, проблема в том, что я хочу масштабировать только верхний набор графиков, а не нижний набор.   -  person cboettig    schedule 31.08.2012
comment
Ааа... Только верхний ряд. Я вижу сейчас.   -  person mnel    schedule 31.08.2012
comment
Как насчет использования параметра shrink в facet_grid и какой-то сводной функции, зависящей от y и переменных фасетирования   -  person mnel    schedule 31.08.2012
comment
Хммм, я бы просто добавил их все вручную, я полагаю, и установил ось Y на каждом графике. Я не думаю, что это возможно, если только вы не захотите изменить код Хэдли.   -  person emhart    schedule 03.09.2012
comment
неловко, что в 2020 году до сих пор не существует элегантного решения этой проблемы.   -  person Ömer An    schedule 07.09.2020


Ответы (3)


Старый пост, но я искал то же самое и ничего не мог найти - [возможно, это способ установить ограничения по оси Y для двух зависимых переменных с помощью facet_grid()

Решение не очень элегантное/эффективное, но я думаю, что оно работает - в основном создайте два графика с разными вызовами coord_cartesian и поменяйте местами grobs.

# library(ggplot2)
# library(gtable)

# Plot
mt <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + geom_point() 

# --------------------------------------------------------------------------------


p1 <- mt + facet_grid(vs ~ am, scales = "free") + coord_cartesian(ylim = c(1,6))
g1 <- ggplotGrob(p1)

p2 <- mt + facet_grid(vs ~ am, scales = "free") + coord_cartesian(ylim = c(3,5))
g2 <- ggplotGrob(p2)

# ----------------------------------------------------------
# Replace the upper panels and upper axis of p1 with that of p2
# Tweak panels of second plot - the upper panels
g1[["grobs"]][[6]] <- g2[["grobs"]][[6]]
g1[["grobs"]][[8]] <- g2[["grobs"]][[8]]

#Tweak axis
g1[["grobs"]][[4]] <- g2[["grobs"]][[4]]

grid.newpage()
grid.draw(g1)
person user20650    schedule 31.03.2014
comment
В последней версии 2.2.1 ggplot2 количество grobs в списке было изменено, и в примере его необходимо изменить. - person Uwe; 09.01.2017
comment
Для ggplot2 v3.3.0 код необходимо изменить следующим образом: # Настроить панели второго графика - верхние панели g1[[grobs]][[2]] ‹- g2[[grobs]][[2]] g1[ [grobs]][[4]] ‹- g2[[grobs]][[4]] #Tweak axis g1[[grobs]][[10]] ‹- g2[[grobs]][[10]] - person masher; 30.05.2020

Итак, это старый вопрос, но я хотел поделиться найденным способом. Самым простым кажется добавление искусственных точек к вашим данным, например. в нижнем левом и верхнем правом углу ваших данных для каждого графика. Поместите эту информацию в отдельный фрейм данных, затем добавьте ее на график с помощью geom_point, используя параметр alpha=0, чтобы сделать точки невидимыми. Установите масштабирование оси в facet_wrap на «free_x» или «free_y», в зависимости от того, что вам нужно.

Теперь ggplot масштабирует каждую грань отдельно, чтобы учесть невидимые точки, которые вы добавили. Немного хакерский, но работает хорошо.

person Holger Hoefling    schedule 25.05.2015

Мое предлагаемое решение основано на ответе, предоставленном @user20650. Он отличается тем, что использует полуавтоматическую процедуру поиска индексов элементов гроба g1, которые необходимо заменить элементами из g2.

# library(ggplot2)
# library(grid)

p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 
  geom_point() +
  facet_grid(vs ~ am)

# modify p1 by zooming as desired
p2 <- p1 + coord_cartesian(ylim = c(3,4)) + 
  theme_bw() + 
  theme(axis.text  = element_text(color="blue"),
        strip.text = element_text(color="blue"))

p1
p2

Теперь мы изменим пределы оси Y верхнего ряда граней. Мы создаем два гроба g1 и g2 и заменяем панели и ось Y в g1 соответствующими элементами из g2.

Приведенный ниже код находит индексы элементов grob для замены на основе имен элементов.

g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)

# Replace the upper panels and upper axis of p1 with that of p2
# i.e. replace the corresponding grobs in g1 with the versions of g2
# Panel numbering goes row-wise from top left to bottom right
panels_to_replace_with_g2 <- c(1,2)

# To get names of grobs run: lapply(g1[["grobs"]],function(x) x$name)
# Use names of grobs to find out indices of g1[["grobs"]] of the panels we want to replace
# as well as for the axis ticks.
pattern_for_specific_panels <- 
  paste0("^panel-((",paste0(panels_to_replace_with_g2, collapse = ")|("),"))")
pattern_for_axes_ticks <- 
  "^GRID.absoluteGrob"

idx_panels_to_replace_from_g2 <- which(unlist(
  lapply(g1[["grobs"]], function(x) grepl(pattern_for_specific_panels, x$name))))
# > idx_panels_to_replace_from_g2
# [1] 2 4

idx_axesTicks <- which(unlist(
  lapply(g1[["grobs"]], function(x) grepl(pattern_for_axes_ticks, x$name))))

# Find out manually which of the defined axesTicks it is:
g_test <- g1
for (itr in idx_axesTicks) {
  g_test[["grobs"]][[itr]] <- g2[["grobs"]][[itr]]
  grid.newpage();grid.draw(g_test); grid.draw(textGrob(itr, just = "top"))
  Sys.sleep(1)
}
# We found out it is itr=10
idx_axesTicks_to_replace <- 10

Узнав индексы заменяемых панелей idx_panels_to_replace_from_g2, а также индекс элемента оси Y idx_axesTicks_to_replace. Мы можем заменить их в следующем.

# Replace panels
grid.newpage();grid.draw(g1)
for (iter in idx_panels_to_replace_from_g2) {
  g1[["grobs"]][[iter]] <- g2[["grobs"]][[iter]]
  grid.newpage();grid.draw(g1)
  Sys.sleep(1)
}

# Replace y-axis
g1[["grobs"]][[idx_axesTicks_to_replace]] <- g2[["grobs"]][[idx_axesTicks_to_replace]]

# Render plot
grid.newpage()
grid.draw(g1)

Если график успешно изменен, теперь вы можете удалить изменения темы и цвет текста, которые мы применили к p2, чтобы сделать изменения более заметными.

измененный сюжет

Будущее TODO: Чего сейчас не хватает, так это увеличить ширину оси Y, чтобы учесть измененные метки оси.

person fabern    schedule 27.08.2018