r - 如何在同一张图中绘制“计数”和“身份”
问题描述
我有一个十进制数字列表,范围从 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"))
我设法独立创建了两个图表,但它们似乎相互覆盖。
或者
解决方案
如果我理解正确,您尝试在条形图中绘制两个不同的变量(计数和总和)。由于它们的范围确实不同,因此您需要定义辅助 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.axis
in 中的参数传递辅助 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"))
因此,您有一种错觉,即在两个不同的尺度上绘制了两组不同的值。
希望这个冗长的解释对您有所帮助。
推荐阅读
- shell - awk:单引号和双引号正则表达式
- docker - GitLab 私有注册表 - 登录错误
- python - 试图在该等式中求解 B
- matlab - 将图像从矢状视图转换为横向视图matlab
- python - 将用户输入拆分为越来越大的列表 [python]
- sql-server - 无法在 SQL Select 中向 DATEOFFSET(2) 添加时间
- bash - 在 Docker 构建期间从文本文件中提取变量
- amazon-web-services - 在 terraform(aws 提供程序)中创建接口类型 vpc 端点时出错
- firebase - 如何告诉 Firestore 使用 Node Admin SDK 返回 Timestamp 对象?
- android - 将 firebase 库更新到 16.0.0 会引发 google play services 依赖问题