假设我有一个非常大的SQL数据库,并且我想为一个float /数字列中的值创建一个密度图。我可以导入R中的所有值并轻松绘制密度。但是,由于该表有很多行,因此我想避免导入所有值,而是在SQL服务器上使用查询来计算摘要统计信息(例如,最小值,q25,中位数,q75,最大值),并且仅导入这几个摘要值,导致流量减少很多。
因此,在R中,我将获得类似agg
对象的数据:
require(data.table)
# test data
set.seed(1234)
vec = rgamma(1000, shape = 0.75)
dt = data.table(group = 'A',
val = vec)
agg = dt[ ,
.(min = min(val),
q25 = quantile(val, .25),
med = median(val),
q75 = quantile(val, .75),
max = max(val)) ]
如何使用{ggplot2}
包从此类汇总数据构建密度或小提琴图?我假设geom_density()
无论如何都是在幕后计算出来的,但是我无法直接将它们输入到函数中。
我想仅通过使用agg
对象来检索这样的图形:
require(ggplot2)
ggplot(dt) +
geom_density(aes(x = val))
旁注:另一种方法是仅导入值的样本。
答案 0 :(得分:2)
您可以在数据库侧使用足够小的bin对数据进行分组和统计,导出(小得多的)汇总数据,然后重建密度图。这里的“足够小”意味着足够小,以至于数据的实际分布与汇总数据的估计分布之间的差异足够小,对于您的目标无关紧要。
您可能需要尝试一下,因为它取决于密度变化的范围。在下面的示例中,我使用了10,000个bin,这仍然是从数据库导出的相对较小的数据集。请注意,我已将您的vec
样本数据扩展到一百万个值:
require(tidyverse)
require(patchwork) # Needed only for laying out the two plots
require(data.table)
# test data
set.seed(1234)
vec = rgamma(1e6, shape = 0.75)
dt = data.table(group = 'A',
val = vec)
agg = dt[ ,
.(min = min(val),
q25 = quantile(val, .25),
med = median(val),
q75 = quantile(val, .75),
max = max(val)) ]
# Set breaks for aggregrating
br = seq(min(vec), max(vec), length.out=10000)
dx = median(diff(br))
# Aggregate data
agg2 = dt %>%
count(val = cut(val, breaks=br, labels=(br + dx)[-length(br)],
include.lowest=TRUE),
val = as.numeric(as.character(val)))
p = ggplot(data=dt, aes(val)) +
geom_density(size=1, colour="blue", n=2^11) +
geom_density(data=agg2 %>% uncount(weight=n), colour="orange", n=2^11) +
theme_bw()
p + {p + coord_cartesian(xlim=c(0,0.3))}
左侧图将实际数据的密度图与从汇总到10,000个bin中的数据重建的密度进行比较。右侧图在x轴上放大到仅接近零的细峰区域。注意出色的重叠。