首页 > 解决方案 > 如何在同一张图中绘制“计数”和“身份”

问题描述

我有一个十进制数字列表,范围从 1 到 40K,我试图将频率直方图与给定的总和一起绘制bin。我正在尝试使用ggplot2但迷失了如何使用直方图中相同的 x 轴箱:

sales <- data.frame(amount = runif(100, min=0, max=40000))
h <- hist(sales$amount, breaks=b)
sales$groups <- cut(sales$amount, breaks=h$breaks)
ggplot(sales,aes(x=groups)) + 
  geom_bar(stat="count")+
  geom_bar(aes(x=groups, y=amount), stat="identity") +
  scale_y_continuous(sec.axis = sec_axis(~.*5, name = "sum"))

我设法独立创建了两个图表,但它们似乎相互覆盖。

使用 <code>stat=

或者

使用 <code>stat=

标签: rggplot2

解决方案


如果我理解正确,您尝试在条形图中绘制两个不同的变量(计数和总和)。由于它们的范围确实不同,因此您需要定义辅助 y 轴。

首先,语法ggplot2要求一列表示 x 值,一列表示 y 值,一列或几列表示组(我正在对我对ggplot2工作原理的理解做一个非常简短而肮脏的总结)。

在这里,我们的想法是将您的“中断”作为 x 变量,第二列将绘制所有 y 值,而组列则规定y 值是否属于“计数”或“数量”组。dplyr您可以使用和tidyr包来实现此目的:

set.seed(123)
sales <- data.frame(amount = runif(100, min=0, max=40000))
b = 4
h <- hist(sales$amount, breaks=b)
sales$groups <- cut(sales$amount, breaks=h$breaks)

library(tidyr)
library(dplyr)
sales %>% group_by(groups) %>% mutate(Count = n()) %>% 
  pivot_longer(.,cols = c(Count, amount), names_to = "Variable", values_to = "Value")

# A tibble: 200 x 3
# Groups:   groups [4]
   groups        Variable  Value
   <fct>         <chr>     <dbl>
 1 (1e+04,2e+04] Count       27 
 2 (1e+04,2e+04] amount   11503.
 3 (3e+04,4e+04] Count       27 
 4 (3e+04,4e+04] amount   31532.
 5 (1e+04,2e+04] Count       27 
 6 (1e+04,2e+04] amount   16359.
 7 (3e+04,4e+04] Count       27 
 8 (3e+04,4e+04] amount   35321.
 9 (3e+04,4e+04] Count       27 
10 (3e+04,4e+04] amount   37619.
# … with 190 more rows

但是,如果您尝试直接绘制此图,您将得到一个糟糕的图,其中“计数”的条形与“数量”相比非常小:

library(ggplot2)
library(tidyr)
library(dplyr)
sales %>% group_by(groups) %>% mutate(Count = n()) %>% 
  pivot_longer(.,cols = c(Count, amount), names_to = "Variable", values_to = "Value")%>%
  ggplot(aes(x=groups, y = Value, fill = Variable)) + 
  geom_bar(stat="identity", position = position_dodge())

在此处输入图像描述

因此,您可以尝试使用sec.axisin 中的参数传递辅助 y 轴scale_y_continuous。但是,这不会改变您的绘图,它只会创建一个“假”右轴,其比例由您传递给参数的值修改sec.axis
在此处输入图像描述

因此,如果您想在图表上显示两组值,您需要缩小“数量”或放大“计数”,以便两组具有相似的值范围。

在这里,由于您希望在右轴上获得总和,我们将按比例缩小“总和”,以便它获得与“计数”值相同范围内的值。

在图表上,您可以看到“数量”值达到 40000 左右,而“计数”的最大值为 30。因此,您可以选择以下比例因子:40000 / 30 = 1333.333。

因此,现在,如果您创建名为“金额”的第二列,它是“金额”除以 1300 的结果,您将在同一范围内拥有“金额”和“计数”。因此,您的数据现在看起来像这样:

library(dplyr)
library(tidyr)

sales %>% group_by(groups) %>% mutate(Count = n()) %>% 
  mutate(Amount = amount /1300) %>%
  pivot_longer(.,cols = c(Count, Amount), names_to = "Variable", values_to = "Value")

# A tibble: 200 x 4
# Groups:   groups [4]
   amount groups        Variable Value
    <dbl> <fct>         <chr>    <dbl>
 1 24000. (2e+04,3e+04] Count     30  
 2 24000. (2e+04,3e+04] Amount    18.5
 3 13313. (1e+04,2e+04] Count     30  
 4 13313. (1e+04,2e+04] Amount    10.2
 5 19545. (1e+04,2e+04] Count     30  
 6 19545. (1e+04,2e+04] Amount    15.0
 7 38179. (3e+04,4e+04] Count     20  
 8 38179. (3e+04,4e+04] Amount    29.4
 9 19316. (1e+04,2e+04] Count     30  
10 19316. (1e+04,2e+04] Amount    14.9
# … with 190 more rows

为了第二个 y 轴反映“数量”值的真实性,您可以传递相反的比例因子并将其乘以 1300。

总之,您将获得以下代码:

library(ggplot2)
library(dplyr)
library(tidyr)
sales %>% group_by(groups) %>% mutate(Count = n()) %>% 
  mutate(Amount = amount /1300) %>%
  pivot_longer(.,cols = c(Count, Amount), names_to = "Variable", values_to = "Value") %>%
  ggplot(aes(x=groups, y = Value, fill = Variable)) + 
  geom_bar(stat="identity", position = position_dodge()) +
  scale_y_continuous(name = "Count",sec.axis = sec_axis(~.*1300, name = "Sum"))

在此处输入图像描述

因此,您有一种错觉,即在两个不同的尺度上绘制了两组不同的值。

希望这个冗长的解释对您有所帮助。


推荐阅读