用网格和gtable拆除ggplot [英] dismantling a ggplot with grid and gtable

查看:122
本文介绍了用网格和gtable拆除ggplot的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正努力根据 ggplot 对象构建双轴图。根据baptiste的建议,我已将问题分解成更小的部分。现在的问题是:如何从 grobs 中删除​​所有数据。 $ c>,同时保留坐标轴,轴标签,坐标轴标记和网格线?'data'是指与 geom_line() geom_points()

想要这样做的原因在构建双轴图的过程中,我遇到了以下问题:来自一个grob的网格线会覆盖另一个grob的数据。



让我明确一点:我的解决方法是将线型添加到aes()和设置scale_linetype_manual(values = c(solid,blank)或者将数据从网格中发送出去,但是我想后处理一个没有被修饰太多

以下是一些代码和数字。

 #数据
df < - 结构(列表(年份= c(1950,2013,1950,2013),国家=结构(c(1L,
1L,2L,2L),。标签= c 小时最低工资,小时最低工资,
小时最低工资,小时最低工资,小时最低工资 (2013年欧元),美国(2013年),b美元(2013美元)
),单位= c(2013年欧元,2013年欧元,2013美元, 2013美元
)),.Names = c(Year,Country,Category,value,variable,
Unit),row.names = c (数据框架)(b)数据框架(b)数据框架(ggplot2)
p < - ggplot(data = df,aes(NA,4L),class =data.frame)

# x = Year,y = value,group = variable,color = variable,shape = variable))+
geom_line(size = 2)+
geom_point(size = 4)+
theme panel.grid.major = element_line(size = 1,color =darkgreen),
panel.grid.minor = element_line(size = 1,color =darkgreen,linetype =dotted))

#使用gtable操作grobs
library(gtable)
g< - ggplot_gtable(ggplot_build(p))
##这里删除geom_line()和geom_point()
## g < - stripdata(g)#伪代码!
grid.newpage()
grid.draw(g)

在下面的阴谋,我想线去!





编辑:按照baptiste的建议,我尝试删除数据图层。但是,BondedDust在注释部分指出,这会打破ggplot对象:

 #删除两层数据
p $ layers [[1]]< - NULL
p $ layers [[1]]< - NULL
g< - ggplot_gtable(ggplot_build(p))
##错误:图中没有图层

从ggplot对象中删除数据会破坏它。我在应用程序中使用的一种解决方法是将数据从网格发送,例如将每个单元乘以-999999并用 + scale_y_continuous(limits = c(1,10))切断显示,但是我想避免这种丑陋的黑客行为,如果可行。我希望如果我用NA或NULL替换每个数据点,关联的gtable不会被销毁,所以我正在寻找一种从g对象内部而不是p对象中删除数据的方法。



在操作grobs(而不是直接对ggplot对象进行攻击)之后, grid.draw(g)的结果会be:





仅供参考,第二个图是通过以下解决方法获得的。

  p < ;  -  ggplot(data = within(df,value <-999999),aes(x = Year,y = value,group = variable,color = variable,shape = variable))+ 
geom_line()+
geom_point()+
主题(panel.grid.major = element_line(size = 1,color =darkgreen),
panel.grid.minor = element_line(size = 1,color =darkgreen,linetype =dotted))+
scale_y_continuous(limits = c(1,10))


解决方案

更自然的策略是使用隐藏的 geom_blank 图层,以便ggplot2仍然训练刻度等来建立情节,但没有显示数据。但是,由于您要处理已格式化的图块,因此可能必须手动从图形gTree中删除这些图块。这是一个尝试,

  library(gtable)
g < - ggplotGrob(p)

stripdata< - function(g){
keep< - grepl(border | grill,
names(g [[grobs]] [[4]] [[ ]]))
g [[grobs]] [[4]] [[children]] [!keep]< - NULL
g
}

grid.newpage()
grid.draw(stripdata(g))


I'm struggling to build a dual-axis plot based on ggplot objects. At baptiste's suggestion, I have broken down the problem into smaller parts. The present issue is:

  1. how to remove all of the data from the grobs, while keeping the axis, the axis labels, the axis tickmarks, and the grid lines? By 'data' I mean the data associated with geom_line() and geom_points().

The reason for wanting to do this is that in the process of building a dual-axis plot, I ran into the following problem: the grid lines from one grob would overwrite the data from the other grob. By removing the data lines and points, there would be no overwriting.

Let me be clear: I do have workarounds that consist in adding a linetype to the aes() and setting scale_linetype_manual(values = c("solid", "blank") or, alternatively, sending the data 'off the grid', but I would like to post-process a plot object that has not been 'groomed' too much for the purpose at hand.

Below some code and figures.

# Data
df <- structure(list(Year = c(1950, 2013, 1950, 2013), Country = structure(c(1L, 
1L, 2L, 2L), .Label = c("France", "United States"), class = "factor"), 
Category = c("Hourly minimum wage", "Hourly minimum wage", 
"Hourly minimum wage", "Hourly minimum wage"), value = c(2.14, 
9.43, 3.84, 7.25), variable = c("France (2013 euros)", 
"France (2013 euros)", "United States (2013 dollars)", "United States (2013 dollars)"
), Unit = c("2013 euros", "2013 euros", "2013 dollars", "2013 dollars"
)), .Names = c("Year", "Country", "Category", "value", "variable", 
"Unit"), row.names = c(NA, 4L), class = "data.frame")

# Plot data with ggplot
library(ggplot2)
p <- ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
geom_line(size = 2) + 
geom_point(size = 4) +
theme(panel.grid.major = element_line(size = 1, colour = "darkgreen"), 
      panel.grid.minor = element_line(size = 1, colour = "darkgreen", linetype = "dotted"))

# Manipulate grobs with gtable
library(gtable)
g <- ggplot_gtable(ggplot_build(p))
## Here remove the geom_line() and geom_point()
## g <- stripdata(g)  # pseudo-code!
grid.newpage()
grid.draw(g)

In the plot below, I would like the lines gone!

Edit: Following baptiste's suggestion, I attempt to remove the data layers. However, as BondedDust points out in the comments section, this breaks the ggplot object:

# Remove the two layers of data
p$layers[[1]] <- NULL
p$layers[[1]] <- NULL
g <- ggplot_gtable(ggplot_build(p))
## Error: No layers in plot

Removing the data from the ggplot object destroys it. One workaround I have used in applications is to 'send the data off the grid', e.g. multiplying each cell by -999999 and cuting off the display with + scale_y_continuous(limits = c(1, 10)), but I'd like to avoid this ugly hack, if feasible. I was hoping that the associated gtable would not be destroyed if I replaced every data point with NA or NULL, so that's why I was looking for a way to remove the data from inside the g object, rather than the p object.

After manipulation of the grobs (rather than hacking directly the ggplot object), the result of grid.draw(g) would be:

FYI, the second plot was obtained with the following workaround.

p <- ggplot(data = within(df, value <- -999999), aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
geom_line() + 
geom_point() +
theme(panel.grid.major = element_line(size = 1, colour = "darkgreen"), 
      panel.grid.minor = element_line(size = 1, colour = "darkgreen", linetype = "dotted")) +
scale_y_continuous(limits = c(1, 10))

解决方案

A more natural strategy would be to use invisible geom_blank layers, so that ggplot2 still trains the scales etc to build the plot but shows no data. Since you want to process already-formatted plots, however, you probably have to remove manually those grobs from the plot gTree. Here's an attempt,

library(gtable)
g <- ggplotGrob(p)

stripdata <- function(g){
  keep <- grepl("border|grill", 
                names(g[["grobs"]][[4]][["children"]]))
  g[["grobs"]][[4]][["children"]][!keep] <- NULL
  g
}

grid.newpage()
grid.draw(stripdata(g))

这篇关于用网格和gtable拆除ggplot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆