使用ggplot2绘制多个数据集的直方图,并附带百分比。

4

我有四个数据集,想在同一图中绘制它们的直方图。我将所有的数据放入一个数据框中,也可以在同一张图上绘制这些直方图。但是,我希望绘制的是每个数据集的百分比而不是计数。当我使用下面的代码时,它会将所有计数的百分比作为总数来绘制,但我更希望百分比是相对于每个数据集的。这可能吗?

all <- rbind(data.frame(fill = "A", Events = A$Events), 
    data.frame(fill = "B", Events = B$Events), 
    data.frame(fill = "C", Events = C$Events), 
    data.frame(fill = "D", Events = D$Events)
ggplot(all,aes(x=Events, fill = fill)) + 
 geom_histogram(aes(y = ..count../sum(..count..)), position = 'dodge')

编辑

以下是一些示例数据:

fill Events  
1   A   1  
2   A   1  
3   A   3  
4   A   1  
5   A   1  
6   A   6  
7   A   2  
8   A   1  
9   A   1  
10  A   2  
11  A   1  
12  A   1  
13  A   1  
14  A   1  
15  A   5  
16  A   1  
17  A   2  
18  A   2  
19  A   1  
20  A   1  
21  A   1  
22  A   1  
23  A   2  
24  A   1  
25  A   2  
26  A   1  
27  B   2  
28  B   3  
29  B   1  
30  B   3  
31  B   2  
32  B   5  
33  B   1  
34  B   1  
35  B   1  
36  B   2  
37  B   1  
38  B   1  
39  B   1  
40  B   1  
41  B   1  
42  B   1  
43  B   1  
44  B   1  
45  B   1  
46  B   4  
47  B   3  
48  B   3  
49  B   5  
50  B   3  
51  C   1  
52  C   2  
53  C   2  
54  C   3  
55  C   3  
56  C   9  
57  C   8  
58  C   1  
59  C   1  
60  C   2  
61  C   2  
62  C   1  
63  C   2  
64  C  39  
65  C  43  
66  C 194  
67  C 129  
68  C 186  
69  C   1  
70  C   2  
71  C   7  
72  C   4  
73  C   1   
74  D  12  
75  D   3  
76  D   2  
77  D   3  
78  D   8  
79  D  20  
80  D   5  
81  D   1  
82  D   4  
83  D   9  
84  D  51  
85  D  12  
86  D   7  
87  D   6  
88  D   7  
89  D   7  
90  D   9  
91  D  17  
92  D  18  
93  D   8  
94  D   7  
95  D   6  
96  D  10  
97  D  27  
98  D  11  
99  D  21  
100 D  89  
101 D  47  
102 D   1  
2个回答

1
你离正确很近,但需要使用(..density..)*binwidth而不是..count../sum(..count..)
# Your data:
all <- data.frame(fill=rep(LETTERS[1:4],c(26,24,23,29)),
                  Events=c(1,1,3,1,1,6,2,1,1,2,1,1,1,1,5,1,2,2,1,1,1,1,2,1,2,1,2,3,1,3,2,5,1,1,1,2,1,1,1,1,1,1,1,1,1,4,3,3,5,3,1,2,2,3,3,9,8,1,1,2,2,1,2,39,43,194,129,186,1,2,7,4,1,12,3,2,3,8,20,5,1,4,9,51,12,7,6,7,7,9,17,18,8,7,6,10,27,11,21,89,47,1))

bw <- 20 # set the binwidth

# plot
p1<-ggplot(all,aes(x=Events, fill=fill)) + 
  geom_histogram(aes(y=(..density..)*bw), position='dodge', binwidth=bw)
p1

desired output

这是一个检查值是否相加为1的代码:

Here is a check to make sure the values add to 1:

aggregate(ymax ~ group, data = as.data.frame(print(p1)$data[[1]]), FUN = sum)
#  group ymax
#1     1    1
#2     2    1
#3     3    1
#4     4    1

“老的答案”
这是一个例子:
library(ggplot2)

ggplot(mtcars,aes(x=mpg, fill = as.factor(cyl))) +
  geom_histogram(aes(y = ..density..), position = 'dodge', binwidth=5)

作为检查,将binwidth调整为100,每个列的值将为0.01(100%/ 100 = 0.01)。

编辑)这里是另一个例子,使用过度简化的数据集来突出结果:

library(data.table)
# Calculate the average miles per gallon by number of cylinders
mtcars_avg <- as.data.table(mtcars)[,
                                    list(mpg_avg=mean(mpg)),
                                    by=list(cyl=as.factor(cyl))][order(cyl)][order(cyl)]
mtcars_avg
#   cyl  mpg_avg
#1:   4 26.66364
#2:   6 19.74286
#3:   8 15.10000

# OP version, with unwanted results of 33% per color (cyl)
ggplot(mtcars_avg, aes(x=mpg_avg, fill=cyl)) +
  geom_histogram(aes(y = ..count../sum(..count..)), position = 'dodge', binwidth=1)

original

# ..density.. version, which shows the desired results of 100% per color (cyl)
ggplot(mtcars_avg, aes(x=mpg_avg, fill=cyl)) +
  geom_histogram(aes(y = ..density..), position = 'dodge', binwidth=1)

solution

您也可以考虑使用geom_density

ggplot(mtcars,aes(x=mpg, fill = as.factor(cyl))) + geom_density(alpha=0.5)

也许我没有正确表达我的问题。我的想法是,将每个数据集的所有条形图相加应该等于100%,但是使用密度时,我得到了所有数据集的总和为100%。 - user2167681
1
是的,我想我明白了。我已经在解决方案中添加了另一个例子。这有帮助吗?也许你可以发布实际数据以突出你的确切关注点? - dnlbrky
我已经在顶部添加了一些示例数据。如果我将binwidth = 1保持不变,则使用..density..效果很好,但是当我更改binwidth = 10时,总数最终为10%(我猜是因为1.00/10 = .1)。如果您知道如何更改binwidth,但保持比例为100%,那将非常有帮助。此外,感谢有关geom_density的提示。也许我会使用它。 - user2167681
好的。看起来将密度乘以binwidth可以实现您想要的结果。请检查编辑后的答案。也许其他人可以解释为什么这是必要的。 - dnlbrky

-1

这个binwidth是必要的,因为根据定义,积分总和为1。

基本上,binwidth的增加导致y的变化为1/x - binwidth更大,所以高度必须更低才能获得相同的面积。

因此,为了恢复百分比,您必须通过将y乘以bw来进行纠正。

举个简单的例子,想象一下只有一个点:

  • 基本的"..density.."代码将给出百分比,因为bw * p = 1,即1*1=1
  • 如果您将bw更改为2,则"..density.."代码将在y轴上给出:bw * y = 1 => y = 1/bw = 0.5
  • 为了在y轴上获得百分比,您必须乘以bw

请正确格式化您的答案。目前它相当难以理解。 - Greenonline

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接