为什么numpy KDE的输出不能很容易地Map到输入?

mbyulnm0  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(115)

我想使用KDE来估计我在显微镜图像中检测到的XY点列表上的簇密度(这是一个完全不同的过程)。我试着修改这个答案中的代码:https://stackoverflow.com/a/64499779/2009558
为什么KDE的输出不能Map到输入维度?我不明白把KDE输出Map到网格的必要性。也不知道为什么网格的尺寸与输入数据不匹配。这一行中的“128j”值是多少?

gx, gy = np.mgrid[x.min():x.max():128j, y.min():y.max():128j]

这是什么样的python对象?既有数字又有字母,但不是字符串?我试着在谷歌上搜索这个问题,但找不到答案。Numpy有时候太不pythonic了,让我抓狂。
这是我目前的情况。数据只是一个pandas df,X和Y坐标作为浮点数。

import numpy as np
import plotly.express as px
import plotly.offline as offline
import pandas as pd
from scipy.stats import gaussian_kde

xx = df['X']
yy = df['Y']
xy = np.vstack((xx, yy))
kde = gaussian_kde(xy)

gx, gy = np.mgrid[xx.min():xx.max():128j, yy.min():yy.max():128j]
gxy = np.dstack((gx, gy))
# print(gxy[0])
z = np.apply_along_axis(kde, 2, gxy)
z = z.reshape(128, 128)

fig = px.imshow(z)
fig.add_trace(go.Scatter(x = xx, y = yy, mode='markers', marker = dict(color='green', size=1)))
fig.show()

这就产生了我想要的大部分情节:点叠加在其上的密度图,但密度数据的维度为128 x 128,而不是输入极限的维度。

当我试着用真实的维度来代替重塑时

z = z.reshape(ceil(xx.max()-xx.min()), ceil(yy.max()-yy.min()))

我只是得到错误。

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_19840/2556669395.py in <module>
     12 z = np.apply_along_axis(kde, 2, gxy)
     13 # z = z.reshape(128, 128)
---> 14 z = z.reshape(ceil(xx.max()-xx.min()), ceil(yy.max()-yy.min()))
     15 
     16 fig = px.imshow(z)

ValueError: cannot reshape array of size 16384 into shape (393,464)
nkkqxpd9

nkkqxpd91#

首先回答您的问题:
我不明白把KDE输出Map到网格的必要性。
需要来自于将结果绘制为图像,并且因此绘制为像素阵列的期望。网格在两个维度中使用常规步长Map数据空间(但每个维度的步长不同),然后您可以使用该步长来计算每个像素的颜色。
为什么KDE的输出不能Map到输入维度?
它是这样的,但由于px.imshow(z)唯一知道的是矩阵z,两个轴都是指矩阵坐标,这在这里是混乱的。
也不知道为什么网格的尺寸与输入数据不匹配。
这是一个任意的选择,将定义图像的分辨率。这里是128 x 128,因为数据空间是这样划分的:
gx, gy = np.mgrid[xx.min():xx.max():128j, yy.min():yy.max():128j]
但你可以选择其他任何东西
这一行中的“128 j”值是多少?
正如 slothropDaraan 在评论中指出的那样,这只是一个numpy约定,以精确确定是否希望包含区间的端点。
关于你的错误,它来自于你试图将你的向量z(由于你的空间之前被划分的方式,它有128 x 128个元素)重新组织成一个393 x 464个元素的矩阵。

建议方案:

你的问题是因为px.imshow(z)没有关于xy的线索。为了解决这个问题,我们将使用plotly支持xarray的事实,这将允许我们将矩阵z中的数据链接到它们的(x, y)坐标。

da = xr.DataArray(
    data=z,
    dims=["x", "y"],
    coords=dict(
        x=np.linspace(xx.min(), xx.max(), 128),
        y=np.linspace(yy.min(), yy.max(), 128),
    ),
)

然后在imshow调用中使用da而不是z,就是这样!

相关问题