以计数作为标签的二维汇总图
2D summary plot with counts as labels
我在特定点(lon
和 lat
)测量了一个数量(value
),如下面的示例数据:
library(ggplot2)
set.seed(1)
dat <- data.frame(lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000))
我想用 space 中的颜色对测量值进行二维汇总(例如平均值),最重要的是我想将计数显示为标签。
我可以绘制标签和摘要图
## Left plot
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex")
## Right plot
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
但是当我将两者结合起来时,我失去了总结:
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
我可以实现相反的,算作颜色和摘要算作标签:
ggplot(dat, aes(lon, lat, z = value)) +
geom_hex(bins = 5) +
stat_summary_hex(aes(label=..value..), bins = 5,
fun = function(x) round(mean(x), 3),
geom = "text")
在写问题时,花了几个小时的测试,我找到了一个解决方案:在文本中添加一个 fill=NULL
或 fill=mean(value)
一个给了我我想要的。在代码及其结果图下方;唯一的区别是图例的标签。
但感觉非常hacky,所以我希望有更好的解决方案。
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count.., fill = NULL), bins = 5, geom = "text") +
theme_bw()
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count.., fill = mean(value)), bins = 5, geom = "text") +
theme_bw()
这里的问题是两个图共享相同的图例比例。
由于比例范围不同:0-40
vs -1.5 - 0.5
,最大范围使最小范围的值以(几乎)相同的颜色出现。
这就是为什么将 count
显示为颜色有效,但反之似乎无效的原因。
作为示例,如果您重新缩放 mean
计算,颜色变化是可见的:
rescaled_mean <- function(x) mean(x)*40
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "rescaled_mean", geom = "hex")+
stat_binhex(aes(label = ..count..), bins = 5, geom = "text") +
theme_bw()
公平地说,我发现这是一种非常奇怪的行为。不过我喜欢你的解决方案——我真的不觉得添加 fill = NULL 很麻烦。相反,我觉得这很优雅。这是一种更 hacky 的方法,基本上结果相同,但多了一行。它正在使用 ggnewscale。
library(ggplot2)
set.seed(1)
dat <- data.frame(lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000))
ggplot(dat) +
aes(x = lon, y = lat,z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
ggnewscale::new_scale_fill() +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
由 reprex package (v2.0.1)
创建于 2022-02-17
我提出了一个完全不同的方法来解决这个问题。但是,首先需要澄清一下。你写 “我在特定点(lon
和 lat
)测量了一个数量(值)” 但你没有指定 这些点正好。您的数据(生成的)包含 1000 lon
个点和相同数量的 lat
个点。
总之,你自己看看吧。
library(tidyverse)
set.seed(1)
dat <-
tibble(
lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000)
)
dat %>% distinct(lon) %>% nrow() #1000
dat %>% distinct(lat) %>% nrow() #1000
我的猜测是,对于真实数据,lon
和 lat
的值集要小得多。
让我将其分解为 2 的精度。
grid = 2
dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n()
)
正如您在四舍五入后看到的那样,数据根据这两个变量进行了分组,然后我计算了您感兴趣的统计数据(平均值和观察次数)。
另请注意,这些统计数据是在 lon
和 lat
的交点处生成的,因此我们有一个正方形网格。在您的解决方案中,情况完全不是这样。您没有获得这些点的观测值数量,并且您的网格不是正方形的。
所以让我们做一个图表。
dat %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
theme_bw()
没有什么能阻止您增加网格,比方说 4。
grid = 4
datg = dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n()
)
datg %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
theme_bw()
使用这样的解决方案,我们可以很容易地在我们感兴趣的地方补充标签,例如与平均值。这次我们将使用 grid = 1.5
.
grid = 1.5
datg = dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n(),
lab2 = paste0("(", round(mean, 2), ")")
)
datg %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
geom_text(aes(label = lab2), nudge_y = -.5, size = 3) +
theme_bw()
希望此解决方案比基于 stat_binhex
的解决方案更能满足您的需求。
我在特定点(lon
和 lat
)测量了一个数量(value
),如下面的示例数据:
library(ggplot2)
set.seed(1)
dat <- data.frame(lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000))
我想用 space 中的颜色对测量值进行二维汇总(例如平均值),最重要的是我想将计数显示为标签。
我可以绘制标签和摘要图
## Left plot
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex")
## Right plot
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
但是当我将两者结合起来时,我失去了总结:
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
我可以实现相反的,算作颜色和摘要算作标签:
ggplot(dat, aes(lon, lat, z = value)) +
geom_hex(bins = 5) +
stat_summary_hex(aes(label=..value..), bins = 5,
fun = function(x) round(mean(x), 3),
geom = "text")
在写问题时,花了几个小时的测试,我找到了一个解决方案:在文本中添加一个 fill=NULL
或 fill=mean(value)
一个给了我我想要的。在代码及其结果图下方;唯一的区别是图例的标签。
但感觉非常hacky,所以我希望有更好的解决方案。
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count.., fill = NULL), bins = 5, geom = "text") +
theme_bw()
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
stat_binhex(aes(label = ..count.., fill = mean(value)), bins = 5, geom = "text") +
theme_bw()
这里的问题是两个图共享相同的图例比例。
由于比例范围不同:0-40
vs -1.5 - 0.5
,最大范围使最小范围的值以(几乎)相同的颜色出现。
这就是为什么将 count
显示为颜色有效,但反之似乎无效的原因。
作为示例,如果您重新缩放 mean
计算,颜色变化是可见的:
rescaled_mean <- function(x) mean(x)*40
ggplot(dat) +
aes(x = lon, y = lat, z = value) +
stat_summary_hex(bins = 5, fun = "rescaled_mean", geom = "hex")+
stat_binhex(aes(label = ..count..), bins = 5, geom = "text") +
theme_bw()
公平地说,我发现这是一种非常奇怪的行为。不过我喜欢你的解决方案——我真的不觉得添加 fill = NULL 很麻烦。相反,我觉得这很优雅。这是一种更 hacky 的方法,基本上结果相同,但多了一行。它正在使用 ggnewscale。
library(ggplot2)
set.seed(1)
dat <- data.frame(lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000))
ggplot(dat) +
aes(x = lon, y = lat,z = value) +
stat_summary_hex(bins = 5, fun = "mean", geom = "hex") +
ggnewscale::new_scale_fill() +
stat_binhex(aes(label = ..count..), bins = 5, geom = "text")
由 reprex package (v2.0.1)
创建于 2022-02-17我提出了一个完全不同的方法来解决这个问题。但是,首先需要澄清一下。你写 “我在特定点(lon
和 lat
)测量了一个数量(值)” 但你没有指定 这些点正好。您的数据(生成的)包含 1000 lon
个点和相同数量的 lat
个点。
总之,你自己看看吧。
library(tidyverse)
set.seed(1)
dat <-
tibble(
lon = runif(1000, 1, 15),
lat = runif(1000, 40, 60),
value = rnorm(1000)
)
dat %>% distinct(lon) %>% nrow() #1000
dat %>% distinct(lat) %>% nrow() #1000
我的猜测是,对于真实数据,lon
和 lat
的值集要小得多。
让我将其分解为 2 的精度。
grid = 2
dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n()
)
正如您在四舍五入后看到的那样,数据根据这两个变量进行了分组,然后我计算了您感兴趣的统计数据(平均值和观察次数)。
另请注意,这些统计数据是在 lon
和 lat
的交点处生成的,因此我们有一个正方形网格。在您的解决方案中,情况完全不是这样。您没有获得这些点的观测值数量,并且您的网格不是正方形的。
所以让我们做一个图表。
dat %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
theme_bw()
没有什么能阻止您增加网格,比方说 4。
grid = 4
datg = dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n()
)
datg %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
theme_bw()
使用这样的解决方案,我们可以很容易地在我们感兴趣的地方补充标签,例如与平均值。这次我们将使用 grid = 1.5
.
grid = 1.5
datg = dat %>% mutate(
lon = round(lon/grid)*grid,
lat = round(lat/grid)*grid,
) %>%
group_by(lon, lat) %>%
summarise(
mean = mean(value),
label = n(),
lab2 = paste0("(", round(mean, 2), ")")
)
datg %>% ggplot(aes(lon,lat,z=mean)) +
geom_contour_filled(binwidth = 0.25) +
geom_text(aes(label = label)) +
geom_text(aes(label = lab2), nudge_y = -.5, size = 3) +
theme_bw()
希望此解决方案比基于 stat_binhex
的解决方案更能满足您的需求。