用网格和gtable拆除ggplot [英] dismantling a ggplot with grid and gtable
问题描述
我正努力根据 想要这样做的原因在构建双轴图的过程中,我遇到了以下问题:来自一个grob的网格线会覆盖另一个grob的数据。 让我明确一点:我的解决方法是将线型添加到aes()和设置scale_linetype_manual(values = c(solid,blank)或者将数据从网格中发送出去,但是我想后处理一个没有被修饰太多 以下是一些代码和数字。 ggplot
对象构建双轴图。根据baptiste的建议,我已将问题分解成更小的部分。现在的问题是:如何从 grobs $ c>中删除所有数据。 $ c>,同时保留坐标轴,轴标签,坐标轴标记和网格线?'data'是指与
geom_line()$ c $相关的数据c>和
geom_points()
。
#数据
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:
- 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 withgeom_line()
andgeom_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屋!