R - 具有 shared/same x 和 y 轴的直方图
R - Histograms with shared/same x and y axes
我想绘制两个直方图,其中 x 和 y 的范围都相同。阅读一些帖子后,我的解决方案是使用 ggplot2, geom_histogram 两次。我第一次创建绘图时没有为每个感兴趣的数据集绘图,目的是在所有感兴趣的绘图中获得最大 y/count 和 x 轴值。例如,有两个地块,如果第一个地块 ymax_1 = 10,另一个地块 ymax_2 = 15,那么两个地块的 y 轴范围至少从 0 到 15。同样适用于 x 轴。
在此图之后,我采用 ymax/xmax 值并像之前一样绘制直方图,同时添加 xlim( 0, xmax) 和 ylim( 0, ymax)。但是,当我这样做时,计数的数量会发生变化。更具体地说,在我没有指定任何 xlim/ylim 的第一个图中,我从 ggplot_build( ggplot(...) + geom_histogram(...)) ymax = 2000但是当我第二次使用 xlim 时,我得到 ymax = 4000。不过,从第一个图中我得到 ymax = 2000,因此第二次没有正确绘制直方图。当我删除 xlim 选项时,我得到了相同的结果。
xlim 选项如何以及为何影响计数值?我希望这很清楚。
df = read.table( paste( path, f, sep = "/"), header = TRUE, fill = TRUE, sep = ",", stringsAsFactors = TRUE)
measure = colnames( df)[ 7]
combs = unique( df[, c( 'A', 'B', 'C')])
# order combs in specific order to get a specific sequence of plots
combs = combs[ with( combs, order( B, C, A)), ]
bns = lst()
xmxs = lst()
ymxs = lst()
for( j in seq( 1, length( combs[ , 1]), 2)) {
if( combs[ j, 2] == combs[ j, 3]) {
next
}
tmp = subset( df, A == combs[ j, 1] & B == combs[ j, 2] & C == combs[ j, 3], select = c( measure))
# Freedman – Diaconis rule, "On the histogram as a density estimator: L2 theory"
bw = 2 * IQR( tmp[ , 1]) / ( length( tmp[ , 1])^(1/3))
bns[[ j]] = ceiling( ( max( tmp[ , 1]) - min( tmp[ , 1])) / bw)
plots[[ j]] = ggplot( tmp, aes_string( measure)) + geom_histogram( bins = bns[[ j]], aes( fill = ..count..))
histg = ggplot_build( plots[[ j]])$data[[ 1]]
ymxs[[ j]] = max( histg$count)
xmxs[[ j]] = max( histg$x)
tmp = subset( df, A == combs[ j + 1, 1] & B == combs[ j + 1, 2] & C == combs[ j + 1, 3], select = c( measure))
# Freedman – Diaconis rule, "On the histogram as a density estimator: L2 theory"
bw = 2 * IQR( tmp[ , 1]) / ( length( tmp[ , 1])^(1/3))
bns[[ j + 1]] = ceiling( ( max( tmp[ , 1]) - min( tmp[ , 1])) / bw)
plots[[ j + 1]] = ggplot( tmp, aes_string( measure)) + geom_histogram( bins = bns[[ j + 1]], aes( fill = ..count..))
histg = ggplot_build( plots[[ j + 1]])$data[[ 1]]
ymxs[[ j + 1]] = max( histg$count)
xmxs[[ j + 1]] = max( histg$x)
if( ymxs[[ j]] > ymxs[[ j + 1]]) {
ymxs[[ j + 1]] = ymxs[[ j]]
}
else {
ymxs[[ j]] = ymxs[[ j + 1]]
}
if( xmxs[[ j]] > xmxs[[ j + 1]]) {
xmxs[[ j + 1]] = xmxs[[ j]]
}
else {
xmxs[[ j]] = xmxs[[ j + 1]]
}
}
pplots = lst()
for( j in 1 : length( combs[ , 1])) {
if( combs[ j, 2] == combs[ j, 3]) {
next
}
tmp = subset( df, A == combs[ j, 1] & B == combs[ j, 2] & C == combs[ j, 3], select = c( measure))
avg = sprintf( "%.2f", mean( tmp[ , 1]))
stdv = sprintf( "%.2f", std( tmp[ , 1]))
count = length( tmp[ , 1])
entities[[ j]] = paste( combs[ j, 1], " ", combs[ j, 2], " vs ", combs[ j, 3])
pplots[[ j]] = ggplot( tmp, aes_string( measure)) +
geom_histogram( bins = bns[[ j]], aes( fill = ..count..)) +
# xlim( 0, 1.2*xmxs[[ j]]) +
# ylim( 0, 1.2*ymxs[[ j]]) +
ggtitle( bquote( atop( paste( .(entities[[ j]])), paste( mu, " = ", .( avg), ", ", sigma, " = ", .( stdv), ", #cells = ", .( count), sep = " ")))) +
theme( plot.title = element_text( size = 20), axis.text = element_text( size = 12), axis.title = element_text( size = 15))
}
# plot every two plots because the Reference.Population is the same
for( j in seq( 1, length( plots), 2)) {
fileext = str_remove_all( entities[[ j]], 'N')
filename_hi = paste( gsub( '.{4}$', '', f), "_distribution_", fileext, ".png", sep = "")
png( filename = paste( path, filename_hi, sep = "/"))
grid.draw( rbind( ggplotGrob( pplots[[ j]]), ggplotGrob( pplots[[ j + 1]]), size = "last"))
dev.off()
}
因此,在上面的代码中,plots
包含初始图,我从中获取 y、x 轴的最小值和最大值,pplots
包含我最终使用xlim/ylim
个选项。但是,例如,
max( plots[[ 8]]$data[[ 1]]$count) != max( plots[[ 8]]$data[[ 1]]$count)
当我使用 xlim
选项时。第一个给出 1947
,另一个给出 4529
我的数据。
谢谢
作为您阅读的其他帖子的替代方案,我建议将数据集合并为一个,然后对它们进行分类。为此,您需要 select 您想要直方图的列,并添加一个列来指示从中提取数据的数据集。
对于这个例子,我将组合 iris$Sepal.Length
和 mtcars$disp
。
range(mtcars$disp)
# [1] 71.1 472.0
range(iris$Sepal.Length)
# [1] 4.3 7.9
由于这些示例数据如此不同,我将缩放一个,以便绘图看起来更具可比性......但足够不同,以便您可以看到轴是共享的。
400 * (range(iris$Sepal.Length) - 4)
# [1] 120 1560
如果您需要这样的数据,请交给您。
从这里开始,合并相关字段:
combined_dat <- rbind(
cbind.data.frame(src = "iris Sepal.Length", val = 400 * (iris[, c("Sepal.Length")] - 4)),
cbind.data.frame(src = "mtcars disp*", val = mtcars[, c("disp")])
)
head(combined_dat)
# src val
# 1 iris Sepal.Length 440
# 2 iris Sepal.Length 360
# 3 iris Sepal.Length 280
# 4 iris Sepal.Length 240
# 5 iris Sepal.Length 400
# 6 iris Sepal.Length 560
tail(combined_dat)
# src val
# 177 mtcars disp* 120.3
# 178 mtcars disp* 95.1
# 179 mtcars disp* 351.0
# 180 mtcars disp* 145.0
# 181 mtcars disp* 301.0
# 182 mtcars disp* 121.0
然后剧情。
ggplot(combined_dat, aes(val)) +
geom_histogram() +
facet_wrap(~ src, ncol = 1)
# `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
我想绘制两个直方图,其中 x 和 y 的范围都相同。阅读一些帖子后,我的解决方案是使用 ggplot2, geom_histogram 两次。我第一次创建绘图时没有为每个感兴趣的数据集绘图,目的是在所有感兴趣的绘图中获得最大 y/count 和 x 轴值。例如,有两个地块,如果第一个地块 ymax_1 = 10,另一个地块 ymax_2 = 15,那么两个地块的 y 轴范围至少从 0 到 15。同样适用于 x 轴。
在此图之后,我采用 ymax/xmax 值并像之前一样绘制直方图,同时添加 xlim( 0, xmax) 和 ylim( 0, ymax)。但是,当我这样做时,计数的数量会发生变化。更具体地说,在我没有指定任何 xlim/ylim 的第一个图中,我从 ggplot_build( ggplot(...) + geom_histogram(...)) ymax = 2000但是当我第二次使用 xlim 时,我得到 ymax = 4000。不过,从第一个图中我得到 ymax = 2000,因此第二次没有正确绘制直方图。当我删除 xlim 选项时,我得到了相同的结果。
xlim 选项如何以及为何影响计数值?我希望这很清楚。
df = read.table( paste( path, f, sep = "/"), header = TRUE, fill = TRUE, sep = ",", stringsAsFactors = TRUE)
measure = colnames( df)[ 7]
combs = unique( df[, c( 'A', 'B', 'C')])
# order combs in specific order to get a specific sequence of plots
combs = combs[ with( combs, order( B, C, A)), ]
bns = lst()
xmxs = lst()
ymxs = lst()
for( j in seq( 1, length( combs[ , 1]), 2)) {
if( combs[ j, 2] == combs[ j, 3]) {
next
}
tmp = subset( df, A == combs[ j, 1] & B == combs[ j, 2] & C == combs[ j, 3], select = c( measure))
# Freedman – Diaconis rule, "On the histogram as a density estimator: L2 theory"
bw = 2 * IQR( tmp[ , 1]) / ( length( tmp[ , 1])^(1/3))
bns[[ j]] = ceiling( ( max( tmp[ , 1]) - min( tmp[ , 1])) / bw)
plots[[ j]] = ggplot( tmp, aes_string( measure)) + geom_histogram( bins = bns[[ j]], aes( fill = ..count..))
histg = ggplot_build( plots[[ j]])$data[[ 1]]
ymxs[[ j]] = max( histg$count)
xmxs[[ j]] = max( histg$x)
tmp = subset( df, A == combs[ j + 1, 1] & B == combs[ j + 1, 2] & C == combs[ j + 1, 3], select = c( measure))
# Freedman – Diaconis rule, "On the histogram as a density estimator: L2 theory"
bw = 2 * IQR( tmp[ , 1]) / ( length( tmp[ , 1])^(1/3))
bns[[ j + 1]] = ceiling( ( max( tmp[ , 1]) - min( tmp[ , 1])) / bw)
plots[[ j + 1]] = ggplot( tmp, aes_string( measure)) + geom_histogram( bins = bns[[ j + 1]], aes( fill = ..count..))
histg = ggplot_build( plots[[ j + 1]])$data[[ 1]]
ymxs[[ j + 1]] = max( histg$count)
xmxs[[ j + 1]] = max( histg$x)
if( ymxs[[ j]] > ymxs[[ j + 1]]) {
ymxs[[ j + 1]] = ymxs[[ j]]
}
else {
ymxs[[ j]] = ymxs[[ j + 1]]
}
if( xmxs[[ j]] > xmxs[[ j + 1]]) {
xmxs[[ j + 1]] = xmxs[[ j]]
}
else {
xmxs[[ j]] = xmxs[[ j + 1]]
}
}
pplots = lst()
for( j in 1 : length( combs[ , 1])) {
if( combs[ j, 2] == combs[ j, 3]) {
next
}
tmp = subset( df, A == combs[ j, 1] & B == combs[ j, 2] & C == combs[ j, 3], select = c( measure))
avg = sprintf( "%.2f", mean( tmp[ , 1]))
stdv = sprintf( "%.2f", std( tmp[ , 1]))
count = length( tmp[ , 1])
entities[[ j]] = paste( combs[ j, 1], " ", combs[ j, 2], " vs ", combs[ j, 3])
pplots[[ j]] = ggplot( tmp, aes_string( measure)) +
geom_histogram( bins = bns[[ j]], aes( fill = ..count..)) +
# xlim( 0, 1.2*xmxs[[ j]]) +
# ylim( 0, 1.2*ymxs[[ j]]) +
ggtitle( bquote( atop( paste( .(entities[[ j]])), paste( mu, " = ", .( avg), ", ", sigma, " = ", .( stdv), ", #cells = ", .( count), sep = " ")))) +
theme( plot.title = element_text( size = 20), axis.text = element_text( size = 12), axis.title = element_text( size = 15))
}
# plot every two plots because the Reference.Population is the same
for( j in seq( 1, length( plots), 2)) {
fileext = str_remove_all( entities[[ j]], 'N')
filename_hi = paste( gsub( '.{4}$', '', f), "_distribution_", fileext, ".png", sep = "")
png( filename = paste( path, filename_hi, sep = "/"))
grid.draw( rbind( ggplotGrob( pplots[[ j]]), ggplotGrob( pplots[[ j + 1]]), size = "last"))
dev.off()
}
因此,在上面的代码中,plots
包含初始图,我从中获取 y、x 轴的最小值和最大值,pplots
包含我最终使用xlim/ylim
个选项。但是,例如,
max( plots[[ 8]]$data[[ 1]]$count) != max( plots[[ 8]]$data[[ 1]]$count)
当我使用 xlim
选项时。第一个给出 1947
,另一个给出 4529
我的数据。
谢谢
作为您阅读的其他帖子的替代方案,我建议将数据集合并为一个,然后对它们进行分类。为此,您需要 select 您想要直方图的列,并添加一个列来指示从中提取数据的数据集。
对于这个例子,我将组合 iris$Sepal.Length
和 mtcars$disp
。
range(mtcars$disp)
# [1] 71.1 472.0
range(iris$Sepal.Length)
# [1] 4.3 7.9
由于这些示例数据如此不同,我将缩放一个,以便绘图看起来更具可比性......但足够不同,以便您可以看到轴是共享的。
400 * (range(iris$Sepal.Length) - 4)
# [1] 120 1560
如果您需要这样的数据,请交给您。
从这里开始,合并相关字段:
combined_dat <- rbind(
cbind.data.frame(src = "iris Sepal.Length", val = 400 * (iris[, c("Sepal.Length")] - 4)),
cbind.data.frame(src = "mtcars disp*", val = mtcars[, c("disp")])
)
head(combined_dat)
# src val
# 1 iris Sepal.Length 440
# 2 iris Sepal.Length 360
# 3 iris Sepal.Length 280
# 4 iris Sepal.Length 240
# 5 iris Sepal.Length 400
# 6 iris Sepal.Length 560
tail(combined_dat)
# src val
# 177 mtcars disp* 120.3
# 178 mtcars disp* 95.1
# 179 mtcars disp* 351.0
# 180 mtcars disp* 145.0
# 181 mtcars disp* 301.0
# 182 mtcars disp* 121.0
然后剧情。
ggplot(combined_dat, aes(val)) +
geom_histogram() +
facet_wrap(~ src, ncol = 1)
# `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.