Подтвердить что ты не робот

R, добавляя datatable к графу ggplot, используя viewPorts: Масштабирование Grob

Я пытаюсь добавить таблицу данных к графику, сделанному в ggplot (аналогично функциональности excel, но с возможностью изменения оси)

У меня было несколько проблем с этим и продолжаю сталкиваться с проблемой масштабирования, поэтому попытка 1) была

library(grid)
library(gridExtra)
library(ggplot2)
xta=data.frame(f=rnorm(37,mean=400,sd=50))
xta$n=0
for(i in 1:37){xta$n[i]<-paste(sample(letters,4),collapse='')}
xta$c=0
for(i in 1:37){xta$c[i]<-sample((1:6),1)}
rect=data.frame(xmi=seq(0.5,36.5,1),xma=seq(1.5,37.5,1),ymi=0,yma=10)
xta=cbind(xta,rect)
a = ggplot(data=xta,aes(x=n,y=f,fill=c)) + geom_bar(stat='identity')
b = ggplot(data=xta,aes(x=n,y=5,label=round(f,1))) + geom_text(size=4) + geom_rect(aes(xmin=xmi,xmax=xma,ymin=ymi,ymax=yma),alpha=0,color='black')
z = theme(axis.text=element_blank(),panel.background=element_rect(fill='white'),axis.ticks=element_blank(),axis.title=element_blank())
b=b+z
la=grid.layout(nrow=2,ncol=1,heights=c(0.15,2),default.units=c('null','null'))
grid.show.layout(la)
grid.newpage()
pushViewport(viewport(layout=la))
print(a,vp=viewport(layout.pos.row=2,layout.pos.col=1))
print(b,vp=viewport(layout.pos.row=1,layout.pos.col=1))

который произвел

2 ggplots

вторая попытка 2) была

xta1=data.frame(t(round(xta$f,1)))
xtb=tableGrob(xta1,show.rownames=F,show.colnames=F,show.vlines=T,gpar.corefill=gpar(fill='white',col='black'),gp=gpar(fontsize=12),vp=viewport(layout.pos.row=1,layout.pos.col=1))
grid.newpage()
la=grid.layout(nrow=2,ncol=1,heights=c(0.15,2),default.units=c('null','null'))
grid.show.layout(la)
grid.newpage()
pushViewport(viewport(layout=la))
print(a,vp=viewport(layout.pos.row=2,layout.pos.col=1))
grid.draw(xtb)

который произвел

using a straight table grob and grid.draw

и, наконец, 3) было

grid.newpage()
print(a + annotation_custom(grob=xtb,xmin=0,xmax=37,ymin=450,ymax=460))

который произвел

using annotate_custom

Из них вариант 2 был бы лучшим, если бы я мог масштабировать таблицуGrob до того же размера, что и сюжет, но я не знаю, как это сделать. Любые указатели на то, как это сделать дальше? - Спасибо

4b9b3361

Ответ 1

Вы можете попробовать новую версию tableGrob; полученная ширина/высота gtable может быть установлена ​​на определенный размер (здесь равнораспределенные единицы npc)

library(ggplot2)
library(gridExtra)
library(grid)
tg <- tableGrob(head(iris), rows=NULL)
tg$widths <- unit(rep(1/ncol(tg),ncol(tg)),"npc")
tg$heights <- unit(rep(1/nrow(tg),nrow(tg)),"npc")

qplot(colnames(iris), geom="bar")+ theme_bw() +
  scale_x_discrete(expand=c(0,0)) +
  scale_y_continuous(lim=c(0,2), expand=c(0,0)) +
  annotation_custom(ymin=1, ymax=2, xmin=-Inf, xmax=Inf, tg)

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

Ответ 2

Вы можете использовать, например, таблицу, созданную ggplot, и объединить их с этим в в блоге. Здесь я сделал упрощенный и рабочий пример:

Сначала создайте свой сюжет:

library(ggplot2)
library(reshape2)
library(grid)

 df <- structure(list(City = structure(c(2L,
     3L, 1L), .Label = c("Minneapolis", "Phoenix",
     "Raleigh"), class = "factor"), January = c(52.1,
     40.5, 12.2), February = c(55.1, 42.2, 16.5),
     March = c(59.7, 49.2, 28.3), April = c(67.7,
         59.5, 45.1), May = c(76.3, 67.4, 57.1),
     June = c(84.6, 74.4, 66.9), July = c(91.2,
         77.5, 71.9), August = c(89.1, 76.5,
         70.2), September = c(83.8, 70.6, 60),
     October = c(72.2, 60.2, 50), November = c(59.8,
         50, 32.4), December = c(52.5, 41.2,
         18.6)), .Names = c("City", "January",
     "February", "March", "April", "May", "June",
     "July", "August", "September", "October",
     "November", "December"), class = "data.frame",
     row.names = c(NA, -3L))

dfm <- melt(df, variable = "month")

 levels(dfm$month) <- month.abb
 p <- ggplot(dfm, aes(month, value, group = City,
     colour = City))
 p1 <- p + geom_line(size = 1) + theme(legend.position = "top") + xlab("")

Затем создайте таблицу данных в ggplot. Используйте ту же ось x, что и график:

none <- element_blank()
data_table <- ggplot(dfm, aes(x = month, y = factor(City),
     label = format(value, nsmall = 1), colour = City)) +
     geom_text(size = 3.5) +
  scale_y_discrete(labels = abbreviate)+ theme_bw()  +
     theme(panel.grid.major = none, legend.position = "none",
         panel.border = none, axis.text.x = none,
         axis.ticks = none) + theme(plot.margin = unit(c(-0.5,
     1, 0, 0.5), "lines")) + xlab(NULL) + ylab(NULL)

Объедините два с видовым окном:

Layout <- grid.layout(nrow = 2, ncol = 1, heights = unit(c(2,
     0.25), c("null", "null")))
grid.show.layout(Layout)
vplayout <- function(...) {
     grid.newpage()
     pushViewport(viewport(layout = Layout))
 }

subplot <- function(x, y) viewport(layout.pos.row = x,
     layout.pos.col = y)

mmplot <- function(a, b) {
     vplayout()
     print(a, vp = subplot(1, 1))
     print(b, vp = subplot(2, 1))
 }

mmplot(p1, data_table)

Обратите внимание, что требуется некоторая настройка, например, положение легенды о сюжете и сокращение имен городов в таблице, но результат выглядит неплохо: enter image description here

Применяется к вашему примеру:

library(grid)
library(gridExtra)
library(ggplot2)
xta=data.frame(f=rnorm(37,mean=400,sd=50))
xta$n=0
for(i in 1:37){xta$n[i]<-paste(sample(letters,4),collapse='')}
xta$c=0
for(i in 1:37){xta$c[i]<-sample((1:6),1)}
rect=data.frame(xmi=seq(0.5,36.5,1),xma=seq(1.5,37.5,1),ymi=0,yma=10)
xta=cbind(xta,rect)
a = ggplot(data=xta,aes(x=n,y=f,fill=c)) + geom_bar(stat='identity')+ theme(legend.position = "top")+xlab("")

none <- element_blank()
z=ggplot(xta, aes(x = n, y = "fvalues",
     label = round(f,1)) )+
     geom_text(size = 3)+ theme_bw()  +
     theme(panel.grid.major = none, legend.position = "none",
         panel.border = none, axis.text.x = none,
         axis.ticks = none) + theme(plot.margin = unit(c(-0.5,
     1, 0, 0.5), "lines")) + xlab(NULL) + ylab(NULL)

Layout <- grid.layout(nrow = 2, ncol = 1, heights = unit(c(2,
     0.25), c("null", "null")))
grid.show.layout(Layout)
vplayout <- function(...) {
     grid.newpage()
     pushViewport(viewport(layout = Layout))
 }

subplot <- function(x, y) viewport(layout.pos.row = x,
     layout.pos.col = y)

mmplot <- function(a, b) {
     vplayout()
     print(a, vp = subplot(1, 1))
     print(b, vp = subplot(2, 1))
 }

mmplot(a, z)

enter image description here

EDIT:

похож на Денниса на его решение, но не на баррель и + coord_flip(). Вы можете удалить последнюю, если вы не хотите ее переворачивать, но она повышает читаемость:

ggplot(xta, aes(x=n,y=f,fill=c)) +
   geom_bar() +
   labs(color = "c") +
   geom_text(aes(y = max(f)+30, label = round(f, 1)), size = 3, color = "black") + coord_flip()

Ответ 3

ИМХО, это не хорошо продуманная графика. Во-первых, я не понимаю, почему вам нужно нулевое происхождение, когда значения варьируются от 300 до 500, что является замаскированным способом сказать, что мне не нравится метафора диаграммы. Вы также пытаетесь использовать заливку бара, чтобы представлять различия в значениях c, из которых всего шесть. Здесь я считаю, что это более простой подход к проблеме. Учитывая ваши данные xta,

# Convert the categories to a factor
xta$N <- factor(xta$n, levels = xta$n)

# Simple approach:
ggplot(xta, aes(x = f, y = N, color = factor(c))) +
   geom_point() +
   labs(color = "c") +
   geom_text(aes(x = 575, label = round(f, 1)), size = 4, color = "black")

Это не интересная графика для меня. Что может добавить немного понимания, в зависимости от контекста проблемы, было бы сортировать ответы в порядке возрастания и добавлять эстетику размера, чтобы подчеркнуть различия между уровнями c. (Вы также можете использовать размер без цвета.) Наконец, поскольку мы ставим уровни факторов на вертикальной оси, чтобы их ярлыки были хорошо видны, мы также можем вставить значения f в виде текста, немного увеличив горизонтальную ось.

ggplot(xta, aes(x = f, y = reorder(N, f), color = factor(c), size = c)) + 
   geom_point() +
   labs(color = "c") +
   geom_text(aes(x = 575, label = round(f, 1)), size = 4, color = "black")

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