ggplot2 grammar

2023-11-14


Build a plot layer by layer

ggplot2绘图首先构建一幅图,该图有着默认的数据集以及参数映射。

p <- ggplot(mpg, aes(displ, hwy))

然后在这之上添加图层。

p + geom_point()

每一个图层都由5个组件构成

data: 数据来源,大多数时候每个图层的数据来源都是设置为NULL, 使用在ggplot中的数据,不过你也可以为每一个图层提供它自己的数据来源。 mapping: 数据到美学的映射,在aes函数中设置 geom: 用于绘制每个观测的几何对象,该几何对象接收额外的参数,可以通过参数...或者geom_params传递给该几何对象。 stat: 数据的统计变换名称,用于进行一些statistical summary, 尤其是在直方图以及一些平滑拟合方面。和geom参数一样,统计对象也可以接收一些额外的参数,用于控制统计变换的细节。可以通过参数...或者stat_params传递给它。 position: 提供用于调整重叠对象的方法,包括jitter, stacking or dodging.

Data

Aesthetic mappings

Geoms

各种几何对象可以根据其需要的变量数进行划分。每一个几何对象都有它自己理解的美学参数,可以在其帮助文档中查到。

同样的几何对象,可能有不同的定义方式,例如geom_tile用中心坐标x, y, 以及width, height定义矩形。geom_rect使用ymax, xmin, ymin, xmax定义矩形,而geom_polygon使用四个顶点的x,y坐标定义矩形。

Stats

每个geom背后都有一个默认的统计变换,统计变换接收输入的数据框,返回一个新的含有新的计算出的变量的数据框。一些几何图形,默认的使用这些新的变量作为美学的映射。为了显式的使用这些经过统计变换计算出的新的变量,在使用的时候,使用after_stat包裹住这些向量。通过stat_*函数的文档,你可以查询到统计变换后得到的向量名称。比如下面使用比例绘制直方图,而不是数目。

ggplot(diamonds, aes(price)) + 
  geom_histogram(aes(y = after_stat(density)), binwidth = 500)

Other stats can’t be created with a geom_ function:

ggplot(mpg, aes(trans, cty)) + 
  geom_point() + 
  geom_point(stat = "summary", fun = "mean", colour = "red", size = 4)

Position adjustments

用于bar的位置调整

用于点的位置调整

如果想要给位置对象传递参数只能通过位置对象传递

ggplot(mpg, aes(displ, hwy)) + 
  geom_point(position = position_jitter(width = 0.05, height = 0.5))

Scales and guides

每一种映射都对应这一种图例,对应映射图例地修改,可以通过对应地图例函数修改,对应关系如下

图例合并与分割

对于每一层的每一个变量的美学映射,都默认生成一个图例,ggplot会尽可能地合并这些图例,以展示这些映射地变量。合并同一个变量不同美学映射前提是这些映射有同样地名称。如果某一层对该几何对象设置了settings,而你也想为该settings生成图例,可以设置show.legend = TRUE生成图例,当然你也可以用该方式不生成某一层地映射变量地图例,设置show.legene = FALSE即可。

ggplot(toy, aes(up, up)) + 
  geom_point(size = 4, colour = "grey20", show.legend = TRUE) +
  geom_point(aes(colour = txt), size = 2) 

当多个变量映射到一个几何对象地同一个美学参数,就需要进行图例地分割,使用R包ggnewscale可以实现该功能

base <- ggplot(mpg, aes(displ, hwy)) + 
  geom_point(aes(colour = factor(year)), size = 5) + 
  scale_colour_brewer("year", type = "qual", palette = 5) 

base
base + 
  ggnewscale::new_scale_colour() + 
  geom_point(aes(colour = cyl == 4), size = 1, fill = NA) + 
  scale_colour_manual("4 cylinder", values = c("grey60", "black"))

Legend key glyphs

使用key_glyph参数可以改变图例中每一层地图例多边形

base <- ggplot(economics, aes(date, psavert, color = "savings"))

base + geom_line()
base + geom_line(key_glyph = "timeseries")

Legene position

legend.position 控制图例的位置,在四个角落top,bottom, left, right

如果panel内有多余空间,你可能会想把图例放在其中,你可以给legend.position设定一个相对位置来实现

Alternatively, if there’s a lot of blank space in your plot you might want to place the legend inside the plot. You can do this by setting legend.position to a numeric vector of length two. The numbers represent a relative location in the panel area: c(0, 1) is the top-left corner and c(1, 0) is the bottom-right corner. You control which corner of the legend the legend.position refers to with legend.justification, which is specified in a similar way. Unfortunately positioning the legend exactly where you want it requires a lot of trial and error.

base <- ggplot(toy, aes(up, up)) + 
  geom_point(aes(colour = txt), size = 3)

base + 
  theme(
    legend.position = c(0, 1), 
    legend.justification = c(0, 1)
  )

base + 
  theme(
    legend.position = c(0.5, 0.5), 
    legend.justification = c(0.5, 0.5)
  )