You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加次Y轴后ggplot2中geom_col柱状图消失的问题

问题

我有以下两个数据框ct2和dt2:

ct2<-structure(list(Year = c(1975, 1985, 1990, 2000, 2000, 2000, 2000, 
2000, 2000, 2000, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 
2005, 2005, 2005, 2005, 2010, 2015, 2015), name = c("Association of Southeast Asian Nations (ASEAN) Preferential Trading Arrangements (PTA)", 
"Global System of Trade Preferences (GSTP)", "Association of Southeast Asian Nations (ASEAN) FTA", 
"Association of Southeast Asian Nations (ASEAN) China", "Australia Singapore", 
"EFTA Singapore", "Japan Singapore", "Jordan Singapore", "New Zealand Singapore", 
"Singapore US", "Association of Southeast Asian Nations (ASEAN) Australia New Zealand FTA (AANZFTA)", 
"Association of Southeast Asian Nations (ASEAN) Goods", "Association of Southeast Asian Nations (ASEAN) India", 
"Association of Southeast Asian Nations (ASEAN) Japan", "Association of Southeast Asian Nations (ASEAN) Korea", 
"China Singapore", "Gulf Cooperation Council (GCC) Singapore", 
"India Singapore", "Korea Singapore", "Panama Singapore", "Peru Singapore", 
"Trans Pacific Strategic EPA", "Costa Rica Singapore", "EC Singapore", 
"Transpacific Partnership (TPP)"), number = c("65", "461", "64", 
"67", "82", "396", "520", "534", "631", "658", "66", "69", "70", 
"71", "72", "228", "475", "493", "550", "641", "644", "679", 
"814", "874", "899"), year = c(1977, 1988, 1992, 2004, 2003, 
2002, 2002, 2004, 2000, 2003, 2009, 2009, 2009, 2008, 2006, 2008, 
2008, 2005, 2005, 2006, 2008, 2005, 2010, 2018, 2016), scope_ntis = c(23, 
3, 7, 23, 23, 28, 6, 23, 8, 33, 33, 23, 23, 24, 23, 23, 5, 6, 
4, 8, 6, 11, 18, 32, 41), count = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), country = c("Singapore", 
"Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", 
"Singapore", "Singapore", "Singapore", "Singapore", "Singapore", 
"Singapore", "Singapore", "Singapore", "Singapore", "Singapore", "Singapore", 
"Singapore", "Singapore", "Singapore"), pta_count = c(1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1)), row.names = c(NA, 25L), class = "data.frame")

dt2<-structure(list(Year = c(1950, 1955, 1960, 1965, 1970, 1975, 1980, 
1985, 1990, 1995, 2000, 2005, 2010, 2015), pta_count = c(2, 4, 
10, 14, 24, 18, 13, 19, 84, 100, 105, 96, 47, 15), scope_ntis_mean = c(3.5, 
9.5, 5, 9.57, 4.54, 11.72, 6.23, 7.05, 17.11, 15.16, 15.28, 17.64, 
22.96, 26.87), scope_ntis_sd = c(0.707106781186548, 11.7046999107196, 
6.25388767976457, 8.72409824049971, 4.56812364359683, 9.2278705436976, 
5.11784209333462, 10.7779284971676, 13.2864799994027, 12.9643801053175, 
12.1295056958191, 12.7964796077233, 12.4375963125981, 14.5791762782532
), scope_ntis_se = c(0.822426813475736, 9.62625905026287, 3.25294959458435, 
3.83516264302846, 1.53376734188638, 3.57760589505535, 2.33476117415722, 
4.06710846230115, 2.38450123589789, 2.13245076374089, 1.94704374916827, 
2.14823678655809, 2.98410970181292, 6.19176713030084), scope_ntis_cil = c(2.68, 
-0.13, 1.75, 5.74, 3.01, 8.14, 3.9, 2.99, 14.72, 13.03, 13.33, 
15.49, 19.97, 20.67), scope_ntis_ciu = c(4.32, 19.13, 8.25, 13.41, 
6.08, 15.3, 8.57, 11.12, 19.49, 17.29, 17.22, 19.78, 25.94, 33.06
)), row.names = c(NA, -14L), class = c("tbl_df", "tbl", "data.frame")

用以下代码可以生成包含geom_jitter散点和绿色geom_col柱状图的图表:

p<-ct2 %>% filter(country=="Singapore") %>%
  ggplot(aes(Year,scope_ntis))+geom_jitter(
    aes(text = paste0("Name of PTA: ", name, "\nYear of Signature: ", Year,
                      "\nNTI-Scope: ", scope_ntis))
  )+
  geom_col(
    aes(y=pta_count/(max(pta_count)/max(dt2$scope_ntis_ciu)),
        text = paste0("Year of Signature: ", Year, "\nNTI Scope (mean): ",
                      format(round(pta_count/(max(pta_count)/max(dt2$scope_ntis_ciu)), 2), nsmall = 2)
        )),
    fill="darkolivegreen",alpha=0.3,width=3
    
  )+
  xlim(c(1950,2020))

但添加scale_y_continuous配置次Y轴后,绿色柱状图消失了,相关代码如下:

p<-ct2 %>% filter(country=="Singapore") %>%
  ggplot(aes(Year,scope_ntis))+geom_jitter(
    aes(text = paste0("Name of PTA: ", name, "\nYear of Signature: ", Year,
                      "\nNTI-Scope: ", scope_ntis))
  )+
  geom_col(
    aes(y=pta_count/(max(pta_count)/max(dt2$scope_ntis_ciu)),
        text = paste0("Year of Signature: ", Year, "\nNTI Scope (mean): ",
                      format(round(pta_count/(max(pta_count)/max(dt2$scope_ntis_ciu)), 2), nsmall = 2)
        )),
    fill="darkolivegreen",alpha=0.3,width=3
    
  )+
  xlim(c(1950,2020))+
  scale_y_continuous(
    limits=c(0,33),
    # Features of the first axis
    name = "NTI Scope\n(scope measures the sum of all NTIs mentioned in a PTA,\ndot indicated one PTA)",
    
    # Add a second axis and specify its features
    sec.axis = sec_axis( ~ . * max(dt2$pta_count)/max(dt2$scope_ntis_ciu), name="PTA Count\n(green columns indicate number of PTAs\n signed in given 5-year intervall)")
  )

请问该如何解决这个问题?


解决方案

问题原因

  1. Y轴截断:在geom_col的y值计算中,你使用了max(pta_count),但此时数据框是过滤后的ct2,其中pta_count全部为1,因此计算后的y值为1/(1/max(dt2$scope_ntis_ciu)) = max(dt2$scope_ntis_ciu) ≈33.06,而你设置的Y轴上限是33,导致柱状图刚好超出范围被截断,无法显示。
  2. 数据来源错误:ct2是单个PTA的明细数据,每个行的pta_count都是1,用它画柱状图会在同一Year下堆叠多个高度相同的柱子,不符合你“展示5年区间内PTA数量”的需求,应该使用汇总后的dt2数据。

修正后的代码

# 计算转换因子(统一两个Y轴的刻度比例)
scale_factor <- max(dt2$pta_count) / max(dt2$scope_ntis_ciu)

p <- ggplot() +
  # 用ct2画散点
  geom_jitter(data = ct2 %>% filter(country == "Singapore"),
              aes(x = Year, y = scope_ntis,
                  text = paste0("Name of PTA: ", name, "\nYear of Signature: ", Year,
                                "\nNTI-Scope: ", scope_ntis))) +
  # 用dt2画柱状图,将pta_count转换到主Y轴的刻度范围
  geom_col(data = dt2,
           aes(x = Year, y = pta_count / scale_factor,
               text = paste0("Year of Signature: ", Year, "\nPTA Count: ", pta_count)),
           fill = "darkolivegreen", alpha = 0.3, width = 3) +
  xlim(c(1950, 2020)) +
  scale_y_continuous(
    limits = c(0, 33),
    name = "NTI Scope\n(scope measures the sum of all NTIs mentioned in a PTA,\ndot indicates one PTA)",
    sec.axis = sec_axis(~ . * scale_factor, 
                        name = "PTA Count\n(green columns indicate number of PTAs\nsigned in given 5-year interval)")
  )

关键修改点

  • 单独定义scale_factor,避免重复计算且更清晰;
  • 分开指定geom_jitter和geom_col的数据来源,用dt2绘制汇总的PTA数量柱状图;
  • 修正了柱状图的tooltip文本,显示实际的PTA数量而非错误的“NTI Scope (mean)”;
  • 确保转换后的柱状图y值在0-33的范围内,不会被Y轴截断。

内容的提问来源于stack exchange,提问作者firmo23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:27:35