设置新的双轴 Y 轴限制

huangapple go评论78阅读模式
英文:

Setting New Y Limit Dual Axis

问题

我一直在尝试弄清楚如何调整双轴的y最小值。客户要求调整他当前的图表。我在这里找到了一个涉及此问题的帖子:https://stackoverflow.com/questions/59293809/adjust-y-axis-limits-in-dual-y-axis-g

尝试按照示例进行操作时,出现了两个问题:1)柱状图设置的位置与绘图边缘之间有间隙;2)图表数据本身发生了变化。

structure(stats)
# A tibble: 17 × 3
   `Snapshot Date` avg_asking_rate availability_rate
   <date>                    <dbl>             <dbl>
 1 2019-03-31                 6.27             10.1 
 2 2019-06-30                 6.30             11.2 
 3 2019-09-30                 6.54             11.0 
 4 2019-12-31                 7.33             11.0 
 5 2020-03-31                 7.00              8.56
 6 2020-06-30                 7.64              9.56
 7 2020-09-30                 6.98             10.1 
 8 2020-12-31                 7.16              9.46
 9 2021-03-31                 7.39              9.36
10 2021-06-30                 7.37              8.60
11 2021-09-30                 6.88              8.29
12 2021-12-31                 7.18              6.81
13 2022-03-31                 7.05              5.73
14 2022-06-30                 7.39              5.79
15 2022-09-30                 7.45              7.04
16 2022-12-31                 7.68              7.36
17 2023-03-31                 8.00              7.52

ymin = min(stats$avg_asking_rate)

stats %>%      
  ggplot(., aes(x = `Snapshot Date`))+
  ggtitle("Rent ($/SF NNN)       (%)") +                                                                                                                        
  geom_tile(aes(y = avg_asking_rate/2 + ymin, height = avg_asking_rate, width = 70, fill = "Avg. Asking Rate")) + 
  geom_line(aes(y = availability_rate, colour = "Availability Rate"),
            size = 1)+
  scale_x_date(name = NULL,
               breaks = quarter_labels[, "Snapshot Date", drop=T],
               labels = quarter_labels[, "qlabel", drop=T])+
  scale_y_continuous(name = NULL,
                     sec.axis = sec_axis(~.-ymin),
                                         breaks = scales::breaks_pretty(n = 5))) +
  scale_fill_manual(name = NULL, values = c("Avg. Asking Rate" = secondary_pal[5], "Availability Rate" = primary_pal[4]),guide = guide_legend(order = 1))+
  scale_colour_manual(name = NULL, values = c("Availability Rate" = primary_pal[4]), guide = guide_legend())

我只想让它看起来像我的原始图表,但是主要最小值从0开始。我已经束手无策了。如果你需要修改我的代码,请随意操作。

原始图表:

设置新的双轴 Y 轴限制

英文:

I've been trying to figure out how to adjust the y min of a dual axis. A client requested that his current chart be adjusted. I found a post that touches on this here https://stackoverflow.com/questions/59293809/adjust-y-axis-limits-in-dual-y-axis-g

Trying to follow the example two things are occurring, 1) the distance between where the bar is set and the edge of the plot have a gap 2) the chart data itself has changed.

&gt; structure(stats)
# A tibble: 17 &#215; 3
`Snapshot Date` avg_asking_rate availability_rate
&lt;date&gt;                    &lt;dbl&gt;             &lt;dbl&gt;
1 2019-03-31                 6.27             10.1 
2 2019-06-30                 6.30             11.2 
3 2019-09-30                 6.54             11.0 
4 2019-12-31                 7.33             11.0 
5 2020-03-31                 7.00              8.56
6 2020-06-30                 7.64              9.56
7 2020-09-30                 6.98             10.1 
8 2020-12-31                 7.16              9.46
9 2021-03-31                 7.39              9.36
10 2021-06-30                 7.37              8.60
11 2021-09-30                 6.88              8.29
12 2021-12-31                 7.18              6.81
13 2022-03-31                 7.05              5.73
14 2022-06-30                 7.39              5.79
15 2022-09-30                 7.45              7.04
16 2022-12-31                 7.68              7.36
17 2023-03-31                 8.00              7.52
ymin = min(stats$avg_asking_rate)
stats %&gt;%      
ggplot(., aes(x = `Snapshot Date`))+
ggtitle(&quot;Rent ($/SF NNN)       (%)&quot;) +                                                                                                                        
geom_tile(aes(y = avg_asking_rate/2 + ymin, height = avg_asking_rate, width = 70, fill = &quot;Avg. Asking Rate&quot;)) + 
geom_line(aes(y = availability_rate, colour = &quot;Availability Rate&quot;),
size = 1)+
scale_x_date(name = NULL,
breaks = quarter_labels[, &quot;Snapshot Date&quot;, drop=T],
labels = quarter_labels[, &quot;qlabel&quot;, drop=T])+
scale_y_continuous(name = NULL,
sec.axis = sec_axis(~.-ymin),
breaks = scales::breaks_pretty(n = 5))) +
scale_fill_manual(name = NULL, values = c(&quot;Avg. Asking Rate&quot; = secondary_pal[5], &quot;Availability Rate&quot; = primary_pal[4]),guide = guide_legend(order = 1))+
scale_colour_manual(name = NULL, values = c(&quot;Availability Rate&quot; = primary_pal[4]), guide = guide_legend())

I just want it to look like my original plot, but with the primary minimum starting at 0. At my wits end here. If you have to tear my code apart please feel free to do so.

The Original:

设置新的双轴 Y 轴限制

答案1

得分: 1

如果我理解问题正确,这是我会做的方法。首先,创建数据:

stats <- tibble::tribble(
  ~`Snapshot Date`, ~avg_asking_rate, ~availability_rate,
"2019-03-31",                 6.27,             10.1 ,
"2019-06-30",                 6.30,             11.2 ,
"2019-09-30",                 6.54,             11.0 ,
"2019-12-31",                 7.33,             11.0 ,
"2020-03-31",                 7.00,              8.56,
"2020-06-30",                 7.64,              9.56,
"2020-09-30",                 6.98,             10.1 ,
"2020-12-31",                 7.16,              9.46,
"2021-03-31",                 7.39,              9.36,
"2021-06-30",                 7.37,              8.60,
"2021-09-30",                 6.88,              8.29,
"2021-12-31",                 7.18,              6.81,
"2022-03-31",                 7.05,              5.73,
"2022-06-30",                 7.39,              5.79,
"2022-09-30",                 7.45,              7.04,
"2022-12-31",                 7.68,              7.36,
"2023-03-31",                 8.00,              7.52)
stats$`Snapshot Date` <- lubridate::ymd(stats$`Snapshot Date`)

quarter_labels 对象没有定义,所以我在数据中定义了它们。

stats$quarter_labels <- trimws(paste(c("2019", "", "","", "2020", "", "","", "2021", "","", "", "2022", "","", "", "2023"), 
                              c(rep(c("Q1", "Q2", "Q3", "Q4"), 3), "Q1"), sep=" "))

接下来,获取主轴和次轴变量的最大值:

aar_max <- max(stats$avg_asking_rate)
ar_max <- max(stats$availability_rate)

你可以在原始比例上绘制主轴,并且次轴需要线性变换 0 + y*(aar_max/ar_max),你可以通过在线条美学中将 availability_rate 变量乘以 aar_max/ar_max 来简单实现。我会使用 geom_bar() 而不是 geom_tile() 来绘制主轴变量 - 这似乎更容易一些,并且你将自动得到主轴从零开始。你可以使用线性变换 0 + .*(ar_max/aar_max) 来解开次轴上的变换。这将使次轴的值处于正确的比例上。最后,在 scale_y_manual() 中,你可以设置 limits = c(0,8.1)expand=c(0,0),以强制设置限制而不添加额外的上下填充。你可能需要稍微调整上限,以确保它在你想要的位置。

library(ggplot2)
ggplot(stats, aes(x = `Snapshot Date`))+
  ggtitle("Rent ($/SF NNN)       (%)") +   
  geom_bar(aes(y=avg_asking_rate, fill="Avg. Asking Rate"), stat="identity") +
  geom_line(aes(y = availability_rate*(aar_max/ar_max), colour = "Availability Rate"),
            size = 1)+
  scale_x_date(name = NULL,
               breaks = stats$`Snapshot Date`,
               labels = stats$quarter_labels)+
  scale_y_continuous(name = NULL,
                     limits = c(0,8.1), 
                     expand = c(0,0), 
                     sec.axis = sec_axis(~0 + .*(ar_max/aar_max)),
                     breaks = scales::breaks_pretty(n = 5)) +
  scale_fill_manual(name = NULL, values = c("Avg. Asking Rate" = "gray", "Availability Rate" = "black"),guide = guide_legend(order = 1))+
  scale_colour_manual(name = NULL, values = c("Availability Rate" = "black"), guide = guide_legend()) + 
  theme_minimal() + 
  theme(axis.text.x = element_text(angle=90, hjust=1), 
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())

设置新的双轴 Y 轴限制

Created on 2023-08-09 with reprex v2.0.2

英文:

If I'm understanding the problems, this is how I would do it. First, make the data:

stats &lt;- tibble::tribble(
  ~`Snapshot Date`, ~avg_asking_rate, ~availability_rate,
&quot;2019-03-31&quot;,                 6.27,             10.1 ,
&quot;2019-06-30&quot;,                 6.30,             11.2 ,
&quot;2019-09-30&quot;,                 6.54,             11.0 ,
&quot;2019-12-31&quot;,                 7.33,             11.0 ,
&quot;2020-03-31&quot;,                 7.00,              8.56,
&quot;2020-06-30&quot;,                 7.64,              9.56,
&quot;2020-09-30&quot;,                 6.98,             10.1 ,
&quot;2020-12-31&quot;,                 7.16,              9.46,
&quot;2021-03-31&quot;,                 7.39,              9.36,
&quot;2021-06-30&quot;,                 7.37,              8.60,
&quot;2021-09-30&quot;,                 6.88,              8.29,
&quot;2021-12-31&quot;,                 7.18,              6.81,
&quot;2022-03-31&quot;,                 7.05,              5.73,
&quot;2022-06-30&quot;,                 7.39,              5.79,
&quot;2022-09-30&quot;,                 7.45,              7.04,
&quot;2022-12-31&quot;,                 7.68,              7.36,
&quot;2023-03-31&quot;,                 8.00,              7.52)
stats$`Snapshot Date` &lt;- lubridate::ymd(stats$`Snapshot Date`)

The quarter_labels object wasn't defined, so I just defined them in the data.

stats$quarter_labels &lt;- trimws(paste(c(&quot;2019&quot;, &quot;&quot;,&quot;&quot;,&quot;&quot;, &quot;2020&quot;, &quot;&quot;, &quot;&quot;,&quot;&quot;, &quot;2021&quot;, &quot;&quot;,&quot;&quot;,&quot;&quot;, &quot;2022&quot;, &quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;2023&quot;), 
                              c(rep(c(&quot;Q1&quot;, &quot;Q2&quot;, &quot;Q3&quot;, &quot;Q4&quot;), 3), &quot;Q1&quot;), sep=&quot; &quot;))

Next, get the maximum values on the primary and secondary axis variables:

aar_max &lt;- max(stats$avg_asking_rate)
ar_max &lt;- max(stats$availability_rate)

You can plot the primary axis on its original scale and the secondary axis needs the linear transformation 0 + y*(aar_max/ar_max), which you can implement simply by multiplying the availability_rate variable by aar_max/ar_max in the line aesthetic. I would use geom_bar() instead of geom_tile() for the primary axis variable - it seems a bit easier and you'll automatically get the primary axis going to zero. You can unwind the transformation on the secondary axis by using the linear transformation 0 + .*(ar_max/aar_max). This will put the secondary axis values on the right scale. Finally, in scale_y_manual() you can set limits = c(0,8.1) and expand=c(0,0) to force the limits to be what you set without extra padding on the top and bottom. You may have to fiddle with the upper limit a bit to make sure it's where you want.

library(ggplot2)
ggplot(stats, aes(x = `Snapshot Date`))+
  ggtitle(&quot;Rent ($/SF NNN)       (%)&quot;) +   
  geom_bar(aes(y=avg_asking_rate, fill=&quot;Avg. Asking Rate&quot;), stat=&quot;identity&quot;) +
  geom_line(aes(y = availability_rate*(aar_max/ar_max), colour = &quot;Availability Rate&quot;),
            size = 1)+
  scale_x_date(name = NULL,
               breaks = stats$`Snapshot Date`,
               labels = stats$quarter_labels)+
  scale_y_continuous(name = NULL,
                     limits = c(0,8.1), 
                     expand = c(0,0), 
                     sec.axis = sec_axis(~0 + .*(ar_max/aar_max)),
                     breaks = scales::breaks_pretty(n = 5)) +
  scale_fill_manual(name = NULL, values = c(&quot;Avg. Asking Rate&quot; = &quot;gray&quot;, &quot;Availability Rate&quot; = &quot;black&quot;),guide = guide_legend(order = 1))+
  scale_colour_manual(name = NULL, values = c(&quot;Availability Rate&quot; = &quot;black&quot;), guide = guide_legend()) + 
  theme_minimal() + 
  theme(axis.text.x = element_text(angle=90, hjust=1), 
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())

设置新的双轴 Y 轴限制<!-- -->

<sup>Created on 2023-08-09 with reprex v2.0.2</sup>

huangapple
  • 本文由 发表于 2023年8月9日 06:45:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76863586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定