简体   繁体   English

在ggplot2中的栏之间放置刻度线

[英]Placing tick marks between bars in ggplot2

Using the diamonds data set in the ggplot2 package, I can generate the following chart. 使用ggplot2包中设置的diamonds数据,我可以生成以下图表。

library(ggplot2)
library(dplyr)

diamond.summary <- 
  diamonds %>%
  mutate(carat = ifelse(runif(nrow(.)) < 0.05, NA_real_, carat)) %>%
  group_by(carat_quintile = ntile(carat, 5)) %>%
  summarise(avg_price = mean(price))

diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

在此输入图像描述

So far, so easy. 到目前为止,这么容易。 However, I would also like to display the average price of the missing entries alongside the chart. 但是,我还想在图表旁边显示缺失条目的平均价格。 Similar to the following: 类似于以下内容: 在此输入图像描述

diamond.summary %>%
  mutate(Facet = is.na(carat_quintile),
         carat_quintile_noNA = ifelse(Facet, "Unknown", carat_quintile)) %>%
  ggplot(aes(x = carat_quintile_noNA, y = avg_price, fill = Facet)) + 
  geom_bar(stat = "identity") + 
  facet_grid(~Facet, scales = "free_x", space = "free_x") + 
  scale_x_discrete(breaks = (0:6) - 0.5)

However, when I try to perform the same trick using scale_x_continuous , I get the error Discrete value supplied to continuous scale . 但是,当我尝试使用scale_x_continuous执行相同的技巧时,我得到Discrete value supplied to continuous scale的错误Discrete value supplied to continuous scale When I try to use scale_x_discrete(breaks = c(0:6 + 0.5)) for example, the axis ticks and labels disappear. 例如,当我尝试使用scale_x_discrete(breaks = c(0:6 + 0.5)) ,轴刻度和标签消失。

My question is, how can I get the same faceted chart above with the tick marks in the first panel placed as in the first chart in this post? 我的问题是,如何将第一个面板中的刻度线放在上面的同一个刻面图表中,如同在这篇文章的第一个图表中一样? Advice about chart design could be an acceptable solution, but I don't think all problems like this are solvable with a redesign. 关于图表设计的建议可能是一个可接受的解决方案,但我不认为这样的所有问题都可以通过重新设计来解决。

The trick is to convert your factor to a numeric, assigning a magic number to the unknown quantity. 诀窍是将您的因子转换为数字,为未知数量指定幻数。 ( ggplot2 will not plot bars with true NA values.) Then use scale_x_continuous ggplot2不会绘制具有真实NA值的条形图。)然后使用scale_x_continuous

diamond.summary %>%
  mutate(Facet = is.na(carat_quintile),
         carat_quintile_noNA = ifelse(Facet, "Unknown", carat_quintile),
         ## 
         ## 99 is a magic number.  For our plot, it just has
         ## to be larger than 5. The value 6 would be a natural
         ## choice, but this means that the x tick marks would 
         ## overflow ino the 'unknown' facet.  You could choose
         ## choose 7 to avoid this, but any large number works.  
         ## I used 99 to make it clear that it's magic.
         numeric = ifelse(Facet, 99, carat_quintile)) %>%

  ggplot(aes(x = numeric, y = avg_price, fill = Facet)) + 
  geom_bar(stat = "identity", width = 1) + 
  facet_grid(~Facet, scales = "free_x", space = "free_x") + 
  scale_x_continuous(breaks = c(0:5 + 0.5, 99),
                     labels = c(paste0(c(0:5) * 20, "%"), "Unknown"))

在此输入图像描述

One solution is to approach a bit differently, and reposition the bars instead of the ticks, using position_nudge . 一种解决方案是稍微接近一点,并使用position_nudge重新定位条形而不是刻度。

library(ggplot2)
library(dplyr)

diamond.summary <- 
  diamonds %>%
  mutate(carat = ifelse(runif(nrow(.)) < 0.05, NA_real_, carat)) %>%
  group_by(carat_quintile = ntile(carat, 5)) %>%
  summarise(avg_price = mean(price))

# nudge bars to the left
diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1,
           position=position_nudge((x=-1))) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

轻推棒

# nudge bars to the right
diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1,
           position=position_nudge((x=1))) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

轻推吧

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM