如何在同一张图中绘制“计数”和“身份”

时间:2020-01-05 19:17:19

标签: r ggplot2

我有一个从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"))

我设法分别创建了两个图,但是它们似乎互相覆盖。

using <code>stat="identity"</code>

using <code>stat="count"</code>

1 个答案:

答案 0 :(得分:1)

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

首先,ggplot2的语法要求x值的一列,y值的一列和组的一列或几列(我对我对如何ggplot2有效)。

在这里,想法是将“中断”作为x变量,将第二列包含所有y值进行绘制,并指定一组y值是否属于“ Count”或“ amount”组。您可以使用dplyrtidyr软件包来实现此目的:

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

但是,如果您试图绘制此笔直的直线,则会得到一个不好的图,其中“ Count”的条形比“ amount”的条形小:

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())

enter image description here

因此,您可以尝试使用sec.axis中的scale_y_continuous参数传递辅助y轴。但是,这不会改变您的图,它只会创建一个“伪”右轴,并通过您在参数sec.axis上传递的值来修改比例尺:
enter image description here

因此,如果要使两组值在图形上可见,则需要按比例缩小“数量”或按比例放大“计数”,以使两组都具有相似的值范围。

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

在图形上,您可以看到“数量”值达到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"))

enter image description here

因此,您有一种幻想,可以在两个不同的比例尺上绘制两组不同的值。

希望这个详尽的说明对您有所帮助。