Таблица сопоставленияGrob с осью y ggplot2

Есть ли элегантный способ выровнять строки tableGrob с разрывами оси?

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

совмещенная диаграмма tableGrob и ggplot

Этот пост меня очень дал - tableGrob находится в той же таблице gtable строка как тело диаграммы; однако для того, чтобы строки в tableGrob совпали с метками осей, требуется много ручной работы.

Я также нашел этот пост. Поскольку я публикую публичный отчет, я бы предпочел не использовать код, который не всегда доступен в пакете на CRAN. При этом экспериментальная версия tableGrob, похоже, принимает высоту в качестве аргумента. Если этот код сработает, а я решу использовать эту экспериментальную версию, как мне рассчитать соответствующую высоту строк?

Если нет элегантного способа сделать это, я счел полезными следующие приемы:

  • установите размер шрифта и cex в tableGrob, чтобы он соответствовал ggplot2
  • установите padding.v для размещения строк таблицы в tableGrob
  • изменить пределы координат, чтобы разместить метки столбцов и выровнять их по нижней части последней строки

Мой код MRE:

library(ggplot2)
library(gridExtra)
library(gtable)

theme_set(theme_bw(base_size = 8))
df <- head(mtcars,10)
df$cars <- row.names(df)
df$cars <- factor(df$cars, levels=df$cars[order(df$disp, decreasing=TRUE)], ordered=TRUE)
p <- ggplot(data=df, aes(x=hp, y=cars)) +
  geom_point(aes(x=hp, y=cars)) +
  scale_y_discrete(limits=levels(df$cars))+
  theme(axis.title.y = element_blank()) +
  coord_cartesian(ylim=c(0.5,length(df$cars)+1.5))
t <- tableGrob(df[,c("mpg","cyl","disp","cars")],
               cols=c("mpg","cyl","disp","cars"),
               gpar.coretext = gpar(fontsize = 8, lineheight = 1, cex = 0.8),
               gpar.coltext = gpar(fontsize = 8, lineheight = 1, cex = 0.8),
               show.rownames = FALSE,
               show.colnames = TRUE,
               equal.height = TRUE,
               padding.v = unit(1.65, "mm"))
g <- NULL
g <- ggplotGrob(p)
g <- gtable_add_cols(g, unit(2,"in"), 0)
g <- gtable_add_grob(g, t, t=3, b=3, l=1, r=1)

png('./a.png', width = 5, height = 2, units = "in", res = 100)
grid.draw(g)
dev.off()

Я оставил названия автомобилей на разрывах оси Y для устранения неполадок, но в конечном итоге я их уберу.


person penguinv22    schedule 27.01.2014    source источник
comment
вычислить высоту строк: выяснить, сколько строк (n), и использовать unit(1/n, "npc") в ячейке, соответствующей панели графика из макета gtable.   -  person baptiste    schedule 28.01.2014
comment
@baptiste Спасибо. Используя ваш экспериментальный пакет, я смог заставить кое-что работать. Я немного разбирался в этом, поэтому оставлю вопрос открытым, чтобы получить более правильный ответ, чем я могу предложить. Некоторые советы для других: ggplot2 :: theme () кажется конфликтующим с экспериментальной темой tableGrob (), но я действительно не понимаю темы (или пространства имен), поэтому YRMV; Мне нужно было изменить шрифты темы; также эксп. tableGrob, кажется, обрабатывает порядок факторов иначе, чем gridExtra :: tableGrob; не уверен, что обоснование выполнено; где n = количество разрывов, нет необходимости вводить координаты по оси y.   -  person penguinv22    schedule 28.01.2014


Ответы (2)


Теперь есть экспериментальная версия gtable_table.

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

table <- gtable_table(df[,c("mpg","cyl","disp","cars")], 
                      heights = unit(rep(1,nrow(df)), "null"))

g <- ggplotGrob(p)
g <- gtable_add_cols(g, sum(table$widths), 0)
g <- gtable_add_grob(g, table, t=3, b=3, l=1, r=1)

grid.newpage()
grid.draw(g)
person baptiste    schedule 21.06.2014
comment
Как бы вы добавили заголовки столбцов? Я пробовал ваш пример кода на github в файле table.R. С colhead <- gtable_table(t(colnames(d))) я получаю следующую ошибку: Error in mmm < each : comparison of these types is not implemented - person penguinv22; 16.09.2014
comment
вы не можете использовать этот файл с исходной таблицей gtable, вам нужно установить мой разветвленный пакет, чтобы это работало - person baptiste; 17.09.2014
comment
Спасибо за разъяснения. Мне удалось скачать вашу вилку и установить ее; однако я заметил, что в настоящее время требуется R ›= 3.2.0. Это было намеренно? Я хотел бы включить в свой исходный код инструкции по использованию devtools для загрузки и установки пакета; однако он не будет установлен без ручного редактирования требований к версии R. - person penguinv22; 17.09.2014
comment
причина в недавнем изменении в сетке, IIRC ggplot2 не будет работать с моя вилка gtable и более старая версия R - person baptiste; 17.09.2014

Ответ @Baptiste расширен, чтобы продемонстрировать метки столбцов и параметры ячеек:

library(ggplot2)
library(gridExtra)
## I manually changed the dependency on 
install.packages(".//gtable_0.2.tar.gz", repos = NULL, type="source")

## The forked version of gtable requires R version 3.2.0 
## which is currently in development (as of 9/17/2014) due to change in grid 
## (https://github.com/wch/r-source/commit/850a82c30e91feb47a0b6385adcbd82988d90413)
## I have not installed the development version.
## However, I was able, in limited testing, to get this to work with R 3.1.0
## and ggplot2_1.0.0
## YRMV
## The following code, commented out, may be more useful with release of R 3.2.0
## library(devtools)
## devtools::install_github("baptiste/gtable")
library(gtable)

theme_set(theme_bw(base_size = 10))

df <- mtcars
df$cars <- row.names(df)
df <- head(df[,c("mpg","cyl","disp","cars")],10)
df$cars <- factor(df$cars, levels=df$cars[order(df$disp, decreasing=TRUE)], ordered=TRUE)

p <- ggplot(data=df, aes(x=disp, y=cars)) +
     geom_point(aes(x=disp, y=cars)) +
     scale_y_discrete(limits=levels(df$cars))+
     theme(axis.title.y = element_blank()) +
     coord_cartesian(ylim = c(0.5,nrow(df)+1))

core <- gtable_table(df[order(df$disp, decreasing=FALSE),],
                   fg.par = list(fontsize=c(8)),
                   bg.par = list(fill=c(rep("lightblue",4),rep("white",4)), alpha=0.5),
                   heights = unit(rep(1,nrow(df)), "null"))

colHead <- gtable_table(t(colnames(df)),
                    fg.par = list(fontsize=c(8)),
                    bg.par = list(fill=c(1), alpha=0.2),
                    heights = unit(0.5, "null"))
table1 <- rbind(colHead, core)

g <- ggplotGrob(p)
g <- gtable_add_cols(g, sum(table1$widths), 0)
g <- gtable_add_grob(g, table1, t=3, b=3, l=1, r=1)

grid.newpage()
grid.draw(g)

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

person penguinv22    schedule 17.09.2014