我想帮助着色从已经汇总的计数数据生成的ggplot2直方图。
这些数据类似于生活在许多不同领域的#males和#females。可以很容易地绘制直方图的总计数(即男性+女性):
set.seed(1)
N=100;
X=data.frame(C1=rnbinom(N,15,0.1), C2=rnbinom(N,15,0.1),C=rep(0,N));
X$C=X$C1+X$C2;
ggplot(X,aes(x=C)) + geom_histogram()
但是,我想根据C1和C2的相对贡献对每个条形图进行着色,这样我就可以得到与上例相同的直方图(即整体条形高度),加上我看到类型的比例“ C1“和”C2“个体,如堆积条形图。
建议使用ggplot2以干净的方式执行此操作,在示例中使用“X”这样的数据?
答案 0 :(得分:12)
很快,您可以使用stat="identity"
选项和plyr
包来执行OP想要的操作来手动计算直方图,如下所示:
library(plyr)
X$mid <- floor(X$C/20)*20+10
X_plot <- ddply(X, .(mid), summarize, total=length(C), split=sum(C1)/sum(C)*length(C))
ggplot(data=X_plot) + geom_histogram(aes(x=mid, y=total), fill="blue", stat="identity") + geom_histogram(aes(x=mid, y=split), fill="deeppink", stat="identity")
我们基本上只是制作一个'mids'列,用于如何定位列,然后制作两个图:一个用于计算总数(C),另一个用列调整到其中一个列的计数(C1 )。您应该可以从这里进行自定义。
更新1 :我意识到我在计算中的时候犯了一个小错误。现在修复了。另外,我不知道为什么我用'ddply'语句来计算中频。那太傻了。新代码更清晰,更简洁。
更新2 :我回来查看评论并注意到一些有些可怕的事情:我使用总和作为直方图频率。我已经清理了一些代码并添加了有关着色语法的注释中的建议。
答案 1 :(得分:7)
这是使用ggplot_build
的黑客攻击。我们的想法是首先得到您原来/原始的情节:
p <- ggplot(data = X, aes(x=C)) + geom_histogram()
存储在p
中。然后,使用ggplot_build(p)$data[[1]]
提取数据,特别是列xmin
和xmax
(以获得直方图的相同中断/ binwidth)和count
列(以规范化百分比count
。这是代码:
# get old plot
p <- ggplot(data = X, aes(x=C)) + geom_histogram()
# get data of old plot: cols = count, xmin and xmax
d <- ggplot_build(p)$data[[1]][c("count", "xmin", "xmax")]
# add a id colum for ddply
d$id <- seq(nrow(d))
现在如何生成数据?我从你的帖子中了解到的是这一点。以你的情节中的第一个条形为例。它的计数为2,从xmin = 147
延伸到xmax = 156.8
。当我们检查X
这些值时:
X[X$C >= 147 & X$C <= 156.8, ] # count = 2 as shown below
# C1 C2 C
# 19 91 63 154
# 75 86 70 156
在此,我计算(91+86)/(154+156)*(count=2) = 1.141935
和(63+70)/(154+156) * (count=2) = 0.8580645
作为我们将生成的每个条形的两个标准化值。
require(plyr)
dd <- ddply(d, .(id), function(x) {
t <- X[X$C >= x$xmin & X$C <= x$xmax, ]
if(nrow(t) == 0) return(c(0,0))
p <- colSums(t)[1:2]/colSums(t)[3] * x$count
})
# then, it just normal plotting
require(reshape2)
dd <- melt(dd, id.var="id")
ggplot(data = dd, aes(x=id, y=value)) +
geom_bar(aes(fill=variable), stat="identity", group=1)
这是最初的情节:
这就是我得到的:
编辑:如果您还想让休息时间正确,那么您可以从旧图中获取相应的x
坐标,并在此处使用,而不是id
:
p <- ggplot(data = X, aes(x=C)) + geom_histogram()
d <- ggplot_build(p)$data[[1]][c("count", "x", "xmin", "xmax")]
d$id <- seq(nrow(d))
require(plyr)
dd <- ddply(d, .(id), function(x) {
t <- X[X$C >= x$xmin & X$C <= x$xmax, ]
if(nrow(t) == 0) return(c(x$x,0,0))
p <- c(x=x$x, colSums(t)[1:2]/colSums(t)[3] * x$count)
})
require(reshape2)
dd.m <- melt(dd, id.var="V1", measure.var=c("V2", "V3"))
ggplot(data = dd.m, aes(x=V1, y=value)) +
geom_bar(aes(fill=variable), stat="identity", group=1)
答案 2 :(得分:1)
怎么样:
library("reshape2")
mm <- melt(X[,1:2])
ggplot(mm,aes(x=value,fill=variable))+geom_histogram(position="stack")