ggplot stat_summary_bin 故障?
ggplot stat_summary_bin glitch?
我很高兴 discover ggplot 具有分箱散点图,这对于探索和可视化大数据中的关系很有用。然而,最上面的垃圾箱似乎行为不端。这是一个示例:所有 bin 平均值都大致线性对齐,正如它们应该的那样,但顶部的平均值在两个维度上都关闭:
代码:
library(ggplot2)
# simulate an example of linear data
set.seed(1)
N <- 10^4
x <- runif(N)
y <- x + rnorm(N)
dt <- data.frame(x=x, y=y)
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point')
是否有简单的解决方法(以及应该在哪里发布)?
stat_summary_bin
实际上是从 bin 中排除具有最大 x 值的两行,这两个值以 bin = NA
结尾。这两个排除值的平均值绘制为常规 bin 右侧的单独 bin。首先,我展示了您的原始情节中出了什么问题,然后我提供了一种解决方法以获得所需的行为。
原剧情哪里出了问题
要查看原始图中出了什么问题,请创建一个包含两次调用 stat_summary_bin
的图,我们会在其中计算每个 bin 的平均值和每个 bin 中的值数。然后使用 ggplot_build
捕获 ggplot 生成的所有内部数据以创建绘图。
p1 = ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y=mean, bins=10, size=5, geom='text',
aes(label=..y..)) +
stat_summary_bin(fun.y=length, bins=10, size=5, geom='text',
aes(label=..y.., y=0))
p1b = ggplot_build(p1)
现在让我们分别查看 mean
和 length
层的数据。为简洁起见,我只打印了 9 到 11 号箱(最右边的三个箱)。 Bin 11 是 "extra" bin,您可以看到它仅包含 2 个值(它的 label
在下面的第二个 table 中是 2
),并且这些值的平均值两个值是-0.1309998
,如下面的第一个table。
p1b$data[[2]][9:11,c(1,2,4,6,7)]
label bin y x width
9 0.8158320 9 0.8158320 0.8498505 0.09998242
10 0.9235531 10 0.9235531 0.9498329 0.09998242
11 -0.1309998 11 -0.1309998 1.0498154 0.09998244
p1b$data[[3]][9:11,c(1,2,4,6,7)]
label bin y x width
9 1025 9 1025 0.8498505 0.09998242
10 1042 10 1042 0.9498329 0.09998242
11 2 11 2 1.0498154 0.09998244
那是哪两个值?看起来它们来自原始数据框中 x 值最高的两行:
mean(dt[order(-dt$x), "y"][1:2])
[1] -0.1309998
我不确定 stat_summary_bin
如何对数据进行分箱以排除两个最高的 x 值。
获得所需行为的解决方法
解决方法是自己汇总数据,这样您就可以完全控制 bin 的创建方式。下面的示例使用您的原始代码,然后以蓝色绘制预汇总值,以便您可以比较行为。我包含了 dplyr
包,这样我就可以使用链接运算符 (%>%
) 动态汇总数据:
library(dplyr)
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point') +
geom_point(data=dt %>%
group_by(bins=cut(x,breaks=seq(min(x),max(x),length.out=11), include.lowest=TRUE)) %>%
summarise(x=mean(x), y=mean(y)),
aes(x,y), size=3, color="blue") +
theme_bw()
@eipi10 ,为什么会这样。
也许最简单的解决方案是在您的绘图中添加一个带有限制的 scale_x_continuous
,以便从绘图中排除额外的 "NA" bin。
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point') +
scale_x_continuous(limits = range(x))
这对于大数据应该是可以接受的,例如在示例中,从 bin 中排除的少量数据点不会显着影响统计数据。但是,如果处理摘要统计中缺少几个数据点的情况很重要,那么@eipi 提供的解决方案会更好。
我很高兴 discover ggplot 具有分箱散点图,这对于探索和可视化大数据中的关系很有用。然而,最上面的垃圾箱似乎行为不端。这是一个示例:所有 bin 平均值都大致线性对齐,正如它们应该的那样,但顶部的平均值在两个维度上都关闭:
代码:
library(ggplot2)
# simulate an example of linear data
set.seed(1)
N <- 10^4
x <- runif(N)
y <- x + rnorm(N)
dt <- data.frame(x=x, y=y)
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point')
是否有简单的解决方法(以及应该在哪里发布)?
stat_summary_bin
实际上是从 bin 中排除具有最大 x 值的两行,这两个值以 bin = NA
结尾。这两个排除值的平均值绘制为常规 bin 右侧的单独 bin。首先,我展示了您的原始情节中出了什么问题,然后我提供了一种解决方法以获得所需的行为。
原剧情哪里出了问题
要查看原始图中出了什么问题,请创建一个包含两次调用 stat_summary_bin
的图,我们会在其中计算每个 bin 的平均值和每个 bin 中的值数。然后使用 ggplot_build
捕获 ggplot 生成的所有内部数据以创建绘图。
p1 = ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y=mean, bins=10, size=5, geom='text',
aes(label=..y..)) +
stat_summary_bin(fun.y=length, bins=10, size=5, geom='text',
aes(label=..y.., y=0))
p1b = ggplot_build(p1)
现在让我们分别查看 mean
和 length
层的数据。为简洁起见,我只打印了 9 到 11 号箱(最右边的三个箱)。 Bin 11 是 "extra" bin,您可以看到它仅包含 2 个值(它的 label
在下面的第二个 table 中是 2
),并且这些值的平均值两个值是-0.1309998
,如下面的第一个table。
p1b$data[[2]][9:11,c(1,2,4,6,7)]
label bin y x width 9 0.8158320 9 0.8158320 0.8498505 0.09998242 10 0.9235531 10 0.9235531 0.9498329 0.09998242 11 -0.1309998 11 -0.1309998 1.0498154 0.09998244
p1b$data[[3]][9:11,c(1,2,4,6,7)]
label bin y x width 9 1025 9 1025 0.8498505 0.09998242 10 1042 10 1042 0.9498329 0.09998242 11 2 11 2 1.0498154 0.09998244
那是哪两个值?看起来它们来自原始数据框中 x 值最高的两行:
mean(dt[order(-dt$x), "y"][1:2])
[1] -0.1309998
我不确定 stat_summary_bin
如何对数据进行分箱以排除两个最高的 x 值。
获得所需行为的解决方法
解决方法是自己汇总数据,这样您就可以完全控制 bin 的创建方式。下面的示例使用您的原始代码,然后以蓝色绘制预汇总值,以便您可以比较行为。我包含了 dplyr
包,这样我就可以使用链接运算符 (%>%
) 动态汇总数据:
library(dplyr)
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point') +
geom_point(data=dt %>%
group_by(bins=cut(x,breaks=seq(min(x),max(x),length.out=11), include.lowest=TRUE)) %>%
summarise(x=mean(x), y=mean(y)),
aes(x,y), size=3, color="blue") +
theme_bw()
@eipi10
也许最简单的解决方案是在您的绘图中添加一个带有限制的 scale_x_continuous
,以便从绘图中排除额外的 "NA" bin。
ggplot(dt, aes(x, y)) +
geom_point(alpha = 0.1, size = 0.01) +
stat_summary_bin(fun.y='mean', bins=10, color='orange', size=5, geom='point') +
scale_x_continuous(limits = range(x))
这对于大数据应该是可以接受的,例如在示例中,从 bin 中排除的少量数据点不会显着影响统计数据。但是,如果处理摘要统计中缺少几个数据点的情况很重要,那么@eipi 提供的解决方案会更好。