为了尝试使用ggplot2制作2d密度测试图,我使用了代码段:
ggplot(df, aes(x = S1.x, y = S1.y)) + geom_point() + geom_density_2d()
我收到错误消息:“ stat_density2d()
中的计算失败:带宽必须严格为正”
我的数据框如下:
> df
transcriptID S1.x S1.y S2.x S2.y
DQ459412 0.000000 0.000000 0.000000 0.000000
DQ459413 1.584963 2.358379 4.392317 3.085722
DQ459415 0.000000 0.000000 0.000000 0.000000
DQ459418 0.000000 0.000000 0.000000 0.000000
DQ459419 0.000000 0.000000 4.000000 2.891544
DQ459420 0.000000 0.000000 0.000000 0.000000
还有var(df[,"S1.x"]) > 0
和var(df[,"S1.y"]) > 0
。
Fig 1 - 2d density plot with error
但是,通过运行我得到了没有错误的密度图:
ggplot(df, aes(x = S2.x, y = S2.y)) + geom_point() + geom_density_2d()
Fig 2 - density plot without error
如何解决图1中的错误?
答案 0 :(得分:1)
@Mike Wise的回答确实很可靠,我的回答对此有所补充。实际上,bandwidth.nrd
函数计算的是 3rd 和 1st 分位数而不是2nd和1st(该函数的代码)之间的差:
r <- quantile(distances, c(0.25, 0.75))
我建议您自己预先计算带宽,然后将其传递给函数,以测试非零值,而不是像这样:
kde2d(df$s1x, df$s1y,
h = c(ifelse(bandwidth.nrd(df$s1x) == 0, 0.1, bandwidth.nrd(df$s1x)),
ifelse(bandwidth.nrd(df$s1y) == 0, 0.1, bandwidth.nrd(df$s1y))))
希望这会有所帮助。
答案 1 :(得分:0)
因此,真正的问题是S1.x
和S1.y
的值在其列中只有一个非零值。事实证明,geom_density_2d
不能仅用一个或两个值来估计密度。但是请继续阅读...
此问题曾被问过,答案通常是您需要在数据列中具有非零方差。 但是您确实有非零方差,为什么它不起作用?
geom_density_2d
的内部结构,我们发现它使用MASS::kde2d
包函数来计算分布。kde2d
看,我们发现它使用MASS::bandwidth.nrd(df$x)
来估算带宽。bandwidth.nrd
的帮助(包含代码),我们看到它使用经验法则来获取分布的quantile
,并从第一个分位数减去第二个分位数得到带宽估算。MASS::kde2d
带宽估计的基础上对原始数据运行bandwidth.nrd
会给您同样的错误:library(MASS) nn <- c("DQ459412","DQ459413","DQ459415","DQ459418","DQ459419","DQ459420") s1x <- c(0,1.584963,0,0,0,0) s1y <- c(0,2.358379,0,0,0,0) s2x <- c(0,4.392317,0,0,4,0) s2y <- c(0,3.085722,0,0,2.891544,0) df <- data.frame(transcriptID=nn,S1.x=s1x,S1.y=s1y,S2.x=s2x,S2.y=s2y)
> quantile(df$s1x)
0% 25% 50% 75% 100%
0.000000 0.000000 0.000000 0.000000 1.584963
> quantile(df$s1y)
0% 25% 50% 75% 100%
0.000000 0.000000 0.000000 0.000000 2.358379
h <- c(MASS::bandwidth.nrd(df$x), MASS::bandwidth.nrd(df$y)) dens <- MASS::kde2d(df$s1x, df$s1y, h = h, n = n, lims = c(0,1,0,1))
MASS :: kde2d(df $ s1x,df $ s1y,h = h,n = n,lims = c(0,1,0,1))中的错误: 带宽必须严格为正
因此,使用geom_density_2D
的真正标准是x和y数据的第一和第二分位数之间必须有一个非零的间隙。
现在要修复它,如果我做了一些小修改-用0.1替换零,就像这样:
nn <- c("DQ459412","DQ459413","DQ459415","DQ459418","DQ459419","DQ459420")
s1x <- c(0,1.584963,0,0,0.1,0)
s1y <- c(0,2.358379,0,0,0.1,0)
s2x <- c(0,4.392317,0,0,4,0)
s2y <- c(0,3.085722,0,0,2.891544,0)
df <- data.frame(transcriptID=nn,S1.x=s1x,S1.y=s1y,S2.x=s2x,S2.y=s2y)
print(df)
收益:
transcriptID S1.x S1.y S2.x S2.y
1 DQ459412 0.000000 0.000000 0.000000 0.000000
2 DQ459413 1.584963 2.358379 4.392317 3.085722
3 DQ459415 0.000000 0.000000 0.000000 0.000000
4 DQ459418 0.000000 0.000000 0.000000 0.000000
5 DQ459419 0.100000 0.100000 4.000000 2.891544
6 DQ459420 0.000000 0.000000 0.000000 0.000000
然后我得到这个图,而不是你的错误。
您可以让该0.1
值接近零,最终它将不再能够计算分布,并且您将再次得到错误。
一种处理这种情况的一般方法是在数据中添加少量噪声,这是一种模拟事实,即基于连续分布的真实测量进行的任何有意义的计算都应不受该噪声的影响。噪音。
希望有帮助。