【发布时间】:2019-05-09 23:49:20
【问题描述】:
我正在尝试plot 一个multivariate distribution,它是由multiple xy coordinates 产生的。
下面的code 旨在获取每个坐标并将其应用于半径([_Rad])。然后COVmatrix 调整scaling 因子([_Scaling])以扩大x-direction 中的半径并收缩y-direction。其方向由rotation angle ([_Rotation]) 测量。
输出表示为probability函数,表示各个组坐标在一定空间上的影响。
虽然,目前我只能让code 将此应用于df 中的最后一组coordinates。所以使用下面的输入,只有A3_X, A3_Y 有效。 A1_X, A1_Y, A2_X, A2_Y 和 B1_X, B1_Y, B2_X, B2_Y。可视化表示请参见附图。
注意:很抱歉很长的df。这是复制我的dataset 的唯一方法。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as sts
def rot(theta):
theta = np.deg2rad(theta)
return np.array([
[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]
])
def getcov(radius=1, scale=1, theta=0):
cov = np.array([
[radius*(scale + 1), 0],
[0, radius/(scale + 1)]
])
r = rot(theta)
return r @ cov @ r.T
def datalimits(*data, pad=.15):
dmin,dmax = min(d.values.min() for d in data), max(d.values.max() for d in data)
spad = pad*(dmax - dmin)
return dmin - spad, dmax + spad
d = ({
'Time' : [1],
'A1_Y' : [5883.102906],
'A1_X' : [3321.527705],
'A2_Y' : [5898.467202],
'A2_X' : [3328.331657],
'A3_Y' : [5886.270552],
'A3_X' : [3366.777169],
'B1_Y' : [5897.925245],
'B1_X' : [3297.143092],
'B2_Y' : [5905.137781],
'B2_X' : [3321.167842],
'B3_Y' : [5888.291025],
'B3_X' : [3347.263205],
'A1_Radius' : [10.3375199],
'A2_Radius' : [10.0171423],
'A3_Radius' : [11.42129333],
'B1_Radius' : [18.69514267],
'B2_Radius' : [10.65877044],
'B3_Radius' : [9.947025444],
'A1_Scaling' : [0.0716513620],
'A2_Scaling' : [0.0056262380],
'A3_Scaling' : [0.0677243260,],
'B1_Scaling' : [0.0364290850],
'B2_Scaling' : [0.0585827450],
'B3_Scaling' : [0.0432806750],
'A1_Rotation' : [20.58078926],
'A2_Rotation' : [173.5056346],
'A3_Rotation' : [36.23648405],
'B1_Rotation' : [79.81849817],
'B2_Rotation' : [132.2437404],
'B3_Rotation' : [44.28198078],
})
df = pd.DataFrame(data=d)
A_Y = df[df.columns[1::2][:3]]
A_X = df[df.columns[2::2][:3]]
B_Y = df[df.columns[7::2][:3]]
B_X = df[df.columns[8::2][:3]]
A_Radius = df[df.columns[13:16]]
B_Radius = df[df.columns[16:19]]
A_Scaling = df[df.columns[19:22]]
B_Scaling = df[df.columns[22:25]]
A_Rotation = df[df.columns[25:28]]
B_Rotation = df[df.columns[28:31]]
limitpad = .5
clevels = 5
cflevels = 50
xmin,xmax = datalimits(A_X, B_X, pad=limitpad)
ymin,ymax = datalimits(A_Y, B_Y, pad=limitpad)
X,Y = np.meshgrid(np.linspace(xmin, xmax), np.linspace(ymin, ymax))
fig = plt.figure(figsize=(10,6))
ax = plt.gca()
Zs = []
for l,color in zip('AB', ('red', 'blue')):
ax.plot(A_X.iloc[0], A_Y.iloc[0], '.', c='red', ms=10, label=l, alpha = 0.6)
ax.plot(B_X.iloc[0], B_Y.iloc[0], '.', c='blue', ms=10, label=l, alpha = 0.6)
Zrows = []
for _,row in df.iterrows():
for i in [1,2,3]:
x,y = row['{}{}_X'.format(l,i)], row['{}{}_Y'.format(l,i)]
cov = getcov(radius=row['{}{}_Radius'.format(l,i)],scale=row['{}{}_Scaling'.format(l,i)], theta=row['{}{}_Rotation'.format(l,i)])
mnorm = sts.multivariate_normal([x, y], cov)
Z = mnorm.pdf(np.stack([X, Y], 2))
Zrows.append(Z)
Zs.append(np.sum(Zrows, axis=0))
Z = Zs[0] - Zs[1]
normZ = Z - Z.min()
normZ = normZ/normZ.max()
cs = ax.contour(X, Y, normZ, levels=clevels, colors='w', alpha=.5)
ax.clabel(cs, fmt='%2.1f', colors='w')#, fontsize=14)
cfs = ax.contourf(X, Y, normZ, levels=cflevels, cmap='viridis', vmin=0, vmax=1)
cbar = fig.colorbar(cfs, ax=ax)
cbar.set_ticks([0, .2, .4, .6, .8, 1])
如下所示。 code 仅适用于A3_X, A3_Y 和B3_X, B3_Y。
不适用于坐标A1_X, A1_Y, A2_X, A2_Y 和B1_X, B1_Y, B2_X, B2_Y。
【问题讨论】:
-
@Parfait,抱歉,我将编辑问题。不受欢迎的
output是代码只应用于一组coordinates(A3 and B3)。然而,我希望它适用于每一组坐标(A1-A2, B1-B2) -
其他坐标是什么?我看到 A#_x 和 B#_y 系列的 12 个值,如果配对对应于图中包含的 6 个点。
-
@Parfait,我已经修改了这个问题。是不是更清楚了?对于
plot、A3_X A3_Y和B3_X B3_Y中的 6 个点,是应用了半径的点。A1_X A1_Y, A2_X A2_Y和B1_X B1_Y, B2_X B2_Y没有被有效应用。 -
这显然是您的earlier question 的后续行动。我可以帮你修复代码,但我仍然不清楚的部分是你的 z 轴应该代表什么,以及它应该如何标准化。似乎您可能对概率的定义有点模糊(或者至少没有清楚地描述您想要什么)。 z 是否应该是 A 组在特定 xy 点有影响的概率?
-
@tel,我同意我之前有点不清楚。不过,你已经成功了。
Z是对特定xy point有影响的组(可以是任何组)的probability。据我了解,这是当前的输出,不是吗?这有意义吗?
标签: python pandas numpy matplotlib distribution