我遇到了ggplot
问题,我试图以非常小的外观制作线条图。我已经摆脱了传说,转而支持每行右侧的文字标签。如果标签不长,可能不会那么明显,但如果网格线停在最大x值(在这种情况下,在2015年),我会更好。
library(tidyverse)
df <- structure(list(industry = c("Accommodation & Food Services", "Construction", "Health Care & Social Asst.", "Retail Trade",
"Accommodation & Food Services", "Construction", "Health Care & Social Asst.", "Retail Trade"),
year = c(2002L, 2002L, 2002L, 2002L, 2015L, 2015L, 2015L, 2015L),
value = c(6.977, 5.264, 17.065, 14.528, 8.032, 4.648, 20.547, 12.568)),
class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -8L),
.Names = c("industry", "year", "value"))
ggplot(df, aes(x = year, y = value, color = industry)) +
geom_line() +
geom_text(aes(label = industry), data = . %>% filter(year == max(year)), size = 3, hjust = 0, nudge_x = 0.1) +
scale_x_continuous(expand = expand_scale(mult = c(0.05, 0.85)), breaks = c(min(df$year), max(df$year)), name = NULL) +
scale_y_continuous(limits = c(0, NA), name = "Value (thousands)") +
theme_minimal() +
theme(legend.position = "none",
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank())
我想避免完成整个事情in this answer,因为我有几个情节,想要快速将它们组合在一起。
我到目前为止提出的解决方案是创建一个伪网格线,方法是创建一个geom_segment
虚拟数据,其中常规y值从最早的年份开始,到最后一年结束。这样做没问题,因为我知道我想要什么样的休息,并且可以设置scale_y_continuous
以匹配geom_segment
。
break_df <- tibble(x1 = 2002, x2 = 2015, y = seq(0, 20, by = 5))
ggplot(df, aes(x = year, y = value, color = industry)) +
geom_segment(aes(x = x1, xend = x2, y = y, yend = y), data = break_df, inherit.aes = F, size = 0.4, color = "gray85") +
geom_line() +
geom_text(aes(label = industry), data = . %>% filter(year == max(year)), size = 3, hjust = 0, nudge_x = 0.1) +
scale_x_continuous(expand = expand_scale(mult = c(0.05, 0.85)), breaks = c(min(df$year), max(df$year)), name = NULL) +
scale_y_continuous(limits = c(0, NA), name = "Value (thousands)", breaks = break_df$y) +
theme_minimal() +
theme(legend.position = "none",
panel.grid = element_blank())
由reprex package(v0.2.0)创建于2018-05-24。
我想知道ggplot
如何计算休息时间,以及它是否使用了我可以利用的功能?就像我可以提供给geom_segment
和scale_y_continuous
这些中断的内部计算一样,所以如果我没有设置单独的中断信息数据框,它们就会匹配。
或者,也许这是一种愚蠢的方法,并且有更好的方法来获得我想要的网格线。我认为也可能有一种方法可以使用trans
function进行此操作,例如构建trans_new()
,但我不知道该怎么做。
提前致谢!
答案 0 :(得分:5)
我想提出一种使用annotation_custom()
的替代方法,它实现了类似的外观,至少在这种情况下:
ggplot(df, aes(x = year, y = value, color = industry)) +
geom_line() +
annotation_custom(
grob = grid::rectGrob(gp = grid::gpar(col = NA, fill = "white")),
xmin = max(df$year)
) +
geom_text(aes(label = industry), data = . %>% filter(year == max(year)),
size = 3, hjust = 0, nudge_x = 0.1) +
# note: my version of ggplot2 doesn't have the expand_scale function, but I suppose
# it isn't critical to the question here
scale_x_continuous(expand = c(0.2, 0), breaks = c(min(df$year), max(df$year)),
name = NULL) +
scale_y_continuous(limits = c(0, NA), name = "Value (thousands)") +
theme_minimal() +
theme(legend.position = "none",
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank())
annotation_custom
的默认位置参数为Inf
/ -Inf
,将显示的grob拉伸到绘图面板的所有四个边缘,因此指定xmin = max(df$year)
为足以让它覆盖max(df$year)
右边所有内容的网格线。
此技巧最适用于没有可见panel.border
组件的ggplot主题,例如theme_minimal
,theme_grey
或theme_dark
。如果您使用的是theme_bw
/ theme_linedraw
/ theme_light
,那么幻觉会变得不那么有效。 (至于theme_classic
/ theme_void
,它们没有网格线,因此无论哪种方式都无关紧要。)