How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

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

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

问题

geom_violin()的上方正确叠加一个使用不同但相关数据集的geom_errorbar(),可以使用ggplot2库来实现。以下是您可以尝试的代码:

library(ggplot2)

# 创建一个基础图
base_plot <- ggplot(data = df_detail,
                    aes(x = item,
                        y = bid_price)) +
  geom_violin(fill = "gray90") +
  geom_jitter(color = "darkorchid2",
              size = 0.75,
              alpha = 1,
              width = 0.15) +
  geom_point(data = df_summary,
             aes(x = item,
                 y = award),
             color = "red") +
  theme_bw() +
  coord_cartesian(ylim = c(0, 7000))

# 创建一个包含geom_errorbar()的图
errorbar_plot <- ggplot(data = df_summary,
                       mapping = aes(x = item,
                                     ymin = mkt_low,
                                     ymax = mkt_high)) +
  geom_errorbar(width = 0.5) +
  theme_void()  # 使用一个空白的主题以避免覆盖基础图的外观

# 使用patchwork库来组合两个图
library(patchwork)
combined_plot <- base_plot / errorbar_plot

# 打印组合的图
print(combined_plot)

这段代码首先创建一个基础图,包括geom_violin()geom_jitter()geom_point(),然后创建一个仅包含geom_errorbar()的图,最后使用patchwork库将两个图组合在一起,以获得所需的效果。希望这可以帮助您解决问题。

英文:

Question:

How do you properly stack a geom_errorbar() that uses a different (but related!) dataset on top of geom_violin()?

Setup

I ran an auction receiving many individual bid prices for shipping lanes. Afterwards, I selected 2 or 3 bids to create a weighted average award price. Additionally, for each lane, I received an external benchmarking service's low and high market estimate for the lane. In a single plot, I want to show:

  • geom_violin() of the distribution of received bid prices.
  • geom_jitter() of the individual bid prices.
  • geom_point() of the single, weighted average/blended award.
  • geom_errorbar() (or related geom -- preferably shaded area using geom_rect()) that shows the market estimate between low and high for that item.

To minimize repetition, I am using 2 dataframes, one with the numerous bid prices for each item, and one that contains just the blended award and market estimates:

df_detail &lt;- data.frame(item = c(&quot;Item_1&quot;, &quot;Item_1&quot;, &quot;Item_1&quot;, &quot;Item_1&quot;, &quot;Item_1&quot;,
                                 &quot;Item_2&quot;, &quot;Item_2&quot;, &quot;Item_2&quot;, &quot;Item_2&quot;, &quot;Item_2&quot;, 
                                 &quot;Item_3&quot;, &quot;Item_3&quot;, &quot;Item_3&quot;, &quot;Item_3&quot;, &quot;Item_3&quot;), 
                        bid_price = c(6678, 3236, 4674, 5487, 5490, 
                                      5800, 6678, 3827, 4674, 5487, 
                                      2266, 1195, 1225, 3285, 1350))

df_summary &lt;- data.frame(item = c(&quot;Item_1&quot;, &quot;Item_2&quot;, &quot;Item_3&quot;), 
                         award = c(4278, 5844.32, 1244.31), 
                         mkt_low = c(4603, 4619, 833), 
                         mkt_high = c(5661, 5681, 1176))

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

Work So Far...

I know from other experience and reading that you can put the main dataset in the call to ggplot() and add geom_*s(), plus add separate datasets inside their own geom_*() calls. I have no trouble with getting everything except the geom_errorbar() in this call:

library(ggplot2)

ggplot(data = df_detail, # Primary dataset using all the bid prices
       aes(x=item,
           y = bid_price)) + 
  geom_violin(fill = &quot;gray90&quot;) +
  geom_jitter(color = &quot;darkorchid2&quot;, 
              size = 0.75, 
              alpha = 1, 
              width = 0.15) +
  geom_point(data = df_summary, # Add summary dataset with single award point.
             aes(x = item, 
                 y = award), 
             color = &quot;red&quot;) +
  theme_bw() +
  coord_cartesian(ylim = c(0,7000))

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

...and I can separately create the geom_errorbars() in their own plot containing the market lows and highs for each item:

ggplot(data = df_summary,
       mapping = aes(x = item,
                     ymin = mkt_low,
                     ymax = mkt_high)) +
geom_errorbar(width = 0.5) +
theme_bw() +
coord_cartesian(ylim = c(0,7000))

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

The Problem

I can't put them together in the same plot:

ggplot(data = df_detail, 
       aes(x=item,
           y = bid_price)) + 
  geom_violin(fill = &quot;gray90&quot;) +
  geom_jitter(color = &quot;darkorchid2&quot;, 
              size = 0.75, 
              alpha = 1, 
              width = 0.15) +
  geom_point(data = df_summary, 
             aes(x = item, 
                 y = award), 
             color = &quot;red&quot;) +
  geom_errorbar(data = df_summary,  # I am adding this geom_* call!!!!
                mapping = aes(x = item,
                              ymin = mkt_low,
                              ymax = mkt_high),
                width = 0.5) +
  theme_bw() +
  coord_cartesian(ylim = c(0,7000))

The above errors for me as seen below in the trace. However, I'm confused because I didn't have a problem with the geom_point() call which worked earlier. I don't understand the geom_errorbar() looking for the object bid_price which is part of df_detail. If I run rlang::last_trace(), my skills are not good enough to decipher this usefully:
How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

I feel I have some major misconception here, and I appreciate any help offered. Thank you in advance.

答案1

得分: 2

因为你在第1行的ggplot()调用中设置了data = df_detailaes(y = bid_price),它们将被继承为所有后续geom_*的默认值。这对于geom_errorbar()中的aes(y = )参数来说也是如此,不论你是否提供了自定义的dataaes(x)参数给误差条。

要获得你想要的效果,要么在每个geom中设置y参数而不是在ggplot(aes())调用中设置,要么简单地将geom_errorbar中的aes()映射中的y参数设置为NULL。

ggplot(data = df_detail,
       aes(x = item, y = bid_price)) + 
  geom_violin(fill = "gray90") +
  geom_jitter(color = "darkorchid2", 
              size = 0.75, 
              alpha = 1, 
              width = 0.15) +
  geom_point(data = df_summary, 
             aes(x = item, y = award), 
             color = "red") +
  geom_errorbar(data = df_summary,  
                mapping = aes(x = item, y = NULL, ymin = mkt_low, ymax = mkt_high),
                width = 0.5) +
  theme_bw() +
  coord_cartesian(ylim = c(0, 7000))

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?


[1]: https://i.stack.imgur.com/qI6db.png
英文:

Because you set data =df_detail and aes(y = bid_price) in the ggplot() call on line 1, they will be inherited as the default values for all subsequent geom_*.
This is true for the aes(y = ) parameter in your geom_errorbar(), regardless of the custom data and aes(x) parameter provided to the error bar.

To get what you want, either set the y parameter in each geom rather than in the ggplot(aes()) call, or simply set the y parameter of the aes() mapping in the geom_errorbar to NULL.

ggplot(data = df_detail,
       aes(x=item,
           y = bid_price)) + 
  geom_violin(fill = &quot;gray90&quot;) +
  geom_jitter(color = &quot;darkorchid2&quot;, 
              size = 0.75, 
              alpha = 1, 
              width = 0.15) +
  geom_point(data = df_summary, 
             aes(x = item, 
                 y = award), 
             color = &quot;red&quot;) +
  geom_errorbar(data = df_summary,  
                mapping = aes(x = item,
                              y = NULL, # Here!
                              ymin = mkt_low,
                              ymax = mkt_high),
                width = 0.5) +
  theme_bw() +
  coord_cartesian(ylim = c(0,7000))

How do I add geom_errorbars() using a separate dataset to an existing geom_violin() dataset in ggplot2?

huangapple
  • 本文由 发表于 2023年3月12日 11:12:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710864.html
匿名

发表评论

匿名网友

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

确定