Добавление подтаблиц на каждую панель фасетного ggplot в r

Я пытаюсь создать полный набор графиков, используя facet_wrap из пакета ggplot2 в R.

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

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

myData = subset(mpg, manufacturer == "audi" | manufacturer == "chevrolet")
myData = droplevels(myData)

Вот мой код для построения данных:

p =  ggplot(myData, aes(x=hwy, y=cty, colour=model) )
p = p + facet_wrap( ~ manufacturer)#, scales="free") # sets panel division 
p = p + geom_point(size = 3) # sets points aspect
p = p + geom_smooth(stat="identity")
print(p)

Теперь самое сложное... У меня есть еще один кадр данных "indivParam" с дополнительной информацией, которую я хотел бы отобразить в виде таблицы на графике. Скажем глупость:

indivParam = ddply(myData, .(manufacturer  ,  model), summarize,
               var1 = unique(class),
               var2 = round(mean(displ)),
               var3 = round(mean(cyl)))

Что я пытаюсь сделать, так это добавить подтаблицу на каждую панель с информацией, извлеченной из indivParam. Например, добавьте следующую таблицу на первую панель графика:

tg = tableGrob(subset(indivParam, manufacturer == "audi"),
           show.rownames=FALSE, gp=gpar(fontsize=8, lwd=2), 
           xmin=15, xmax=30, ymin=10, ymax=20)
grid.newpage()
grid.draw(tg)

пробовал несколько вариантов...

  1. используя annotate(), но этот аргумент не передает кадры данных...

  2. используя annotation_custom(), как предлагается в этой теме: Добавление таблицы в области построения графика ggplot в r

    p1 = p + annotation_custom(tableGrob(indivParam,
                                show.rownames=FALSE,
                                gp=gpar(fontsize=8, lwd=2)), 
                      xmin=15, xmax=30, ymin=10, ymax=20)
    print(p1)
    

    Это также не работает, поскольку отображает всю таблицу на каждой панели вместо подтаблицы с данными, относящимися к каждой панели ()

  3. Наконец, после прочтения примеров на странице документации 'tableGrob', я попытался создать одну сетку со всеми гробами подтаблиц и просто наложить ее на график:

    lg <- lapply(as.character(unique(indivParam$manufacturer)),
         function(x) tableGrob( as.data.frame(dlply(indivParam, .(manufacturer))[x]),
                                name="test",show.rownames=FALSE,
                                gp=gpar(fontsize=8, lwd=2)))
    grid.newpage()
    print(p)
    grid.draw(do.call(arrangeGrob, lg))
    

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

Можно ли как-то улучшить эту последнюю попытку, выбрав положение подтаблиц? Или есть еще лучший способ решить эту проблему? Очевидным было бы использование geom_table(), но я не думаю, что эта геометрия существует (пока)...

Любая помощь/подсказка будет высоко оценена! :-)


person Aurelie Calabrese    schedule 28.08.2014    source источник
comment
Добро пожаловать в СО! Это отличный вопрос, правда. Это и естественно, и сложно; это показывает много усилий, приложенных к нему. Молодец!   -  person tonytonov    schedule 29.08.2014
comment
я согласен, что geom_table было бы наиболее естественным, но неясно, будет ли такая геометрия хорошо вписываться в панели графиков (обычно таблицы занимают много места и часто скрывают данные в других слоях). За исключением функции интеллектуального позиционирования (минимизация перекрытия), их обычно лучше всего размещать вручную, имхо.   -  person baptiste    schedule 29.08.2014
comment
Отличный вопрос, хорошо изученный и хорошо написанный, и точно такая же проблема, как у меня. Вы случайно не нашли решение, которым хотели бы поделиться?   -  person Edward    schedule 08.10.2015
comment
Спасибо @Эдвард! К сожалению, я не смог исправить эту проблему и был вынужден двигаться дальше... Вместо таблицы я использовал дурацкую функцию geom_text(), вызывающую список значений :-(   -  person Aurelie Calabrese    schedule 20.10.2015


Ответы (1)


Вот решение с потрясающим пакетом ggpmisc:

library(ggpmisc)
library(dplyr)
library(tibble)

myData <- filter(mpg, manufacturer == "audi" | manufacturer == "chevrolet")

gg <- ggplot(myData, aes(x=hwy, y=cty, colour=model)) + 
  facet_wrap(~ manufacturer) + 
  geom_point(size = 3) +
  geom_smooth(stat="identity")

tb <- myData %>%
  group_by(manufacturer, model) %>%
  summarize(var1 = round(mean(displ)), var2 = round(mean(cyl))) %>%
  ungroup() 

tbs <- lapply(split(tb, tb$manufacturer), "[", -1)
df <- tibble(x = rep(-Inf, length(tbs)), 
             y = rep(Inf, length(tbs)), 
             manufacturer = levels(as.factor(tb$manufacturer)), 
             tbl = tbs)

gg + geom_table(data = df, aes(x = x, y = y, label = tbl),
                hjust = 0, vjust = 1) 

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

person Stéphane Laurent    schedule 19.10.2019