ggplot2: удаление граней неиспользуемых комбинаций уровней факторов с графика (facet_grid)

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

добавление пустых графиков в facet_wrap в ggplot2

Вот минимальный пример. Я хотел бы удалить пустую грань справа внизу (b, 2).

library('ggplot2')
d <- data.frame('factor_1' = factor(c('a', 'a', 'b')),
                'factor_2' =    factor(c('1', '2', '1')),
                x = 1:3, y = 1:3)

ggplot(data = d, mapping = aes(x = x, y = y)) +
  geom_point() +
  facet_grid(facets = factor_1 ~ factor_2, drop = TRUE)

введите здесь описание изображения

Очевидно, что drop = TRUE здесь не действует, потому что нет неиспользованных уровней факторов, а есть только их неиспользованные комбинации.


person NoBackingDown    schedule 25.11.2016    source источник


Ответы (2)


В ggplot2 2.2.0 имена grobs в сюжете изменились.

library(ggplot2)
library(grid)
d <- data.frame('factor_1' = factor(c('a', 'a', 'b')),
                'factor_2' =    factor(c('1', '2', '1')),
                x = 1:3, y = 1:3)

p = ggplot(data = d, mapping = aes(x = x, y = y)) +
  geom_point() +
  facet_grid(facets = factor_1 ~ factor_2, drop = TRUE)

# Get ggplot grob
g = ggplotGrob(p)

# Get the layout dataframe. 
# Note the names.
# You want to remove "panel-2-2"
g$layout

# gtable::gtable_show_layout(g) # Might also be useful

# Remove the grobs
# The grob needs to be remove,
#  and the relevant row in the layout data frame needs to be removed
pos <- grepl(pattern = "panel-2-2", g$layout$name)
g$grobs <- g$grobs[!pos]
g$layout <- g$layout[!pos, ]


# Alternatively, replace the grobs with the nullGrob
g = ggplotGrob(p)
pos <- grep(pattern = "panel-2-2", g$layout$name)
g$grobs[[pos]] <- nullGrob()

# If you want, move the axis
# g$layout[g$layout$name == "axis-b-2", c("t", "b")] = c(8, 8)

# Draw the plot
grid.newpage()
grid.draw(g)

введите здесь описание изображения

Ответ в вашей ссылке нужно будет изменить примерно так:

n <- 1000
df <- data.frame(x = runif(n), y=rnorm(n), label = sample(letters[1:7], 
                 size = n, replace = TRUE), stringsAsFactors=TRUE)
df$label.new <- factor(df$label, levels=sort(c(""," ",levels(df$label))))


p <- ggplot(df, aes(x=x, y=y)) + geom_point() + 
         facet_wrap(~ label.new, ncol=3,drop=FALSE)

g = ggplotGrob(p)

g$layout # Note the names and their positions (t, b, l, r)
# gtable::gtable_show_layout(g) # Might also be useful

pos <- g$layout$name %in% c("panel-1-1", "panel-1-2", "strip-t-1-1", "strip-t-2-1")
g$grobs <- g$grobs[!pos]
g$layout <- g$layout[!pos, ]

# Or replace the grobs with the nullGrob
g = ggplotGrob(p)
pos <- g$layout$name %in% c("panel-1-1", "panel-1-2", "strip-t-1-1", "strip-t-2-1")
g$grobs[pos] <- list(nullGrob())

# Move the axis
g$layout[g$layout$name == "axis-l-1-1", c("l", "r")] = c(10,10)

grid.newpage()
grid.draw(g)
person Sandy Muspratt    schedule 30.11.2016
comment
Это отличный ответ, и он мне очень помогает. Однако, применяя его к моей не игрушечной задаче, я заметил, что (i) наименование панелей (т. е. панель-5-3 и т. д.), по-видимому, относится не к координатам панелей на графике, а к по крайней мере, они упорядочены по столбцам в panel$layout и (ii) при настройке положения осей/полос (где именование просто), я не совсем понимаю, что такое позиционная информация (t (op), b (ottom) , r(справа), l(слева)) в panel$layout на самом деле подразумевает. Не могли бы вы объяснить это или указать мне на какой-нибудь полезный ресурс по этому поводу? В любом случае, спасибо БОЛЬШОЕ. - person NoBackingDown; 30.11.2016
comment
(i) t(op), b(ottom), r(right), l(eft) задают экстент grob по отношению к лежащей в его основе gtable — см. фрейм данных компоновки. Вы также получаете изображение базовой gtable, используя gtable_show_layout(). Цифры в именах grobs, приведенных в столбце names во фрейме данных компоновки, не являются t, l, b, r. В версии 2.2.0 панель-5-3 будет означать 5 панелей вниз, 3 панели в ширину. Для полос первая цифра поперек, вторая цифра внизу. Используйте gtable_show_layout() и/или фрейм данных макета, чтобы сопоставить grobs с именем grobs и tlbr. - person Sandy Muspratt; 01.12.2016
comment
(ii) В gtable_show_layout() обратите внимание на ряд (t и b) панели, к которой вы хотите прикрепить ось. В вашем примере это строка 7. Ось расположена на одну строку ниже, т. Е. Строка 8. Следовательно, t и b равны 8. Номер столбца (r и l) остается неизменным. Надеюсь это поможет. - person Sandy Muspratt; 01.12.2016
comment
Я пытаюсь удалить целых два ряда фасетов, созданных из facet_grid(var1+var2 ~ var3). К сожалению, при использовании g$layout я вижу только панель фраз без цифр. Всего у меня 4х6 граней. Любые подсказки о том, как я могу работать в этой ситуации? - person zoneparser; 20.12.2016

Не лучшее решение, но оно дает несколько удовлетворительный результат:

    d$fInter <- interaction(d$factor_2, d$factor_1, sep = ' V ')

    ggplot(data = d, mapping = aes(x = x, y = y)) +
      geom_point() +
      facet_wrap(~ fInter, drop = TRUE, 
                 ncol = nlevels(d$factor_1))

И сюжет:

Сюжет

person Andrey Kolyadin    schedule 25.11.2016
comment
Боюсь, мне определенно нужно использовать facet_grid, а не facet_wrap. - person NoBackingDown; 25.11.2016
comment
Могу я спросить, есть ли какие-то особые причины? Вместо нового значения взаимодействия можно использовать просто ~factor_1 + factor_2, но это будет менее приятно для глаз. - person Andrey Kolyadin; 25.11.2016
comment
Это только минимальный пример, на самом деле у меня уже есть вложенные факторы для столбцов. - person NoBackingDown; 27.11.2016