【发布时间】:2021-07-20 18:50:19
【问题描述】:
在过去的几天里,我一直在尝试使用 python 绘制圆形数据,方法是构建一个从 0 到 2pi 的圆形直方图并拟合 Von Mises 分布。我真正想要实现的是:
- 具有拟合 Von-Mises 分布的方向数据。该图是使用 Matplotlib、Scipy 和 Numpy 构建的,可以在以下位置找到:http://jpktd.blogspot.com/2012/11/polar-histogram.html
- 此图是使用 R 生成的,但给出了我想要绘制的概念。可以在这里找到:https://www.zeileis.org/news/circtree/
到目前为止我做了什么:
from scipy.special import i0
import numpy as np
import matplotlib.pyploy as plt
# From my data I fitted a Von-Mises distribution, calculating Mu and Kappa.
mu = -0.343
kappa = 10.432
# Construct random Von-Mises distribution based on Mu and Kappa values
r = np.random.vonmises(mu, kappa, 1000)
# Adjust Von-Mises curve from fitted data
x = np.linspace(-np.pi, np.pi, num=501)
y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa))
# Adjuste x limits and labels
plt.xlim(-np.pi, np.pi)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
labels=[r'$-\pi$ (0º)', r'$-\frac{\pi}{2}$ (90º)', '0 (180º)', r'$\frac{\pi}{2}$ (270º)', r'$\pi$'])
# Plot adjusted Von-Mises function as line
plt.plot(x, y, linewidth=2, color='red', zorder=3
# Plot distribution
plt.hist(r, density=True, bins=20, alpha=1, edgecolor='white');
plt.title('Slaty Cleavage Strike', fontweight='bold', fontsize=14)
我尝试根据Circular / polar histogram in python
等问题绘制圆形直方图# From the data above (mu, kappa, x and y):
theta = np.linspace(-np.pi, np.pi, num=50, endpoint=False)
radii = np.exp(kappa*np.cos(theta-mu))/(2*np.pi*i0(kappa))
# Bin width?
width = (2*np.pi) / 50
# Construct ax with polar projection
ax = plt.subplot(111, polar=True)
# Set Zero to North
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
# Plot bars:
bars = ax.bar(x = theta, height = radii, width=width)
# Plot Line:
line = ax.plot(x, y, linewidth=1, color='red', zorder=3)
# Grid settings
ax.set_rgrids(np.arange(1, 1.6, 0.5), angle=0, weight= 'black');
注意事项:
- 我的圆形直方图将我的数据绘制在错误的方向上,相差 180 度:比较两个直方图。 见编辑 1
- 我相信这可能与在 [-pi,pi] https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.vonmises.html 上定义的 scipy.stats.vonmises 有关 参见编辑 1
- 我的数据最初在 [0,2pi] 之间变化。我转换为 [-pi,pi] 以拟合 Von Mises 并计算 Mu 和 Kappa。 见编辑 1
我真的很想将我的数据绘制为第一个图。我的数据是地质方向数据(方位角)。有人有什么想法吗? PS。对不起,很长的帖子。我希望这至少会有所帮助
编辑 1:
查看 cmets 后,我意识到有些人对来自 [0,2pi] 或 [-pi,pi] 的数据感到困惑。我意识到在我的圆形直方图中绘制的错误方向来自以下:
- 我的原始数据(地质数据)范围在
[0,2pi]之间,即0到360度; - 但是,scipy.stats.vonmises 计算
[-pi, pi]中的概率密度函数; - 我从数据中减去了 pi,以便使用 scipy.stats.vonmises
my_data - pi; - 计算出
Mu和Kappa后(正确),我将pi添加到Mu值中,以恢复原始方向,现在再次介于[0,2pi]之间。 - 现在,我的数据已正确定向到东南:
# Add pi to fitted Mu.
mu = - 0.343 + np.pi
kappa = 10.432
x = np.linspace(-np.pi, np.pi, num=501)
y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa))
theta = np.linspace(-np.pi, np.pi, num=50, endpoint=False)
radii = np.exp(kappa*np.cos(theta-mu))/(2*np.pi*i0(kappa))
# Bin width?
width = (2*np.pi) / 50
ax = plt.subplot(111, polar=True)
# Angles increase clockwise from North
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
bars = ax.bar(x = theta, height = radii, width=width)
line = ax.plot(x, y, linewidth=1, color='red', zorder=3)
ax.set_rgrids(np.arange(1, 1.6, 0.5), angle=0, weight= 'black');
编辑 2
正如接受答案的 cmets 所建议的那样,技巧正在改变y_lim,如下所示:
# SE DIRECTION
mu = - 0.343 + np.pi
kappa = 10.432
x = np.linspace(-np.pi, np.pi, num=501)
y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa))
theta = np.linspace(-np.pi, np.pi, num=50, endpoint=False)
radii = np.exp(kappa*np.cos(theta-mu))/(2*np.pi*i0(kappa))
# PLOT
plt.figure(figsize=(5,5))
ax = plt.subplot(111, polar=True)
# Bin width?
width = (2*np.pi) / 50
# Angles increase clockwise from North
ax.set_theta_zero_location('N'); ax.set_theta_direction(-1);
bars = ax.bar(x=theta, height = radii, width=width, bottom=0)
# Plot Line
line = ax.plot(x, y, linewidth=2, color='firebrick', zorder=3 )
# 'Trick': This will display Zero as a circle. Fitted Von-Mises function will lie along zero.
ax.set_ylim(-0.5, 1.5);
ax.set_rgrids(np.arange(0, 1.6, 0.5), angle=60, weight= 'bold',
labels=np.arange(0,1.6,0.5));
最后说明:
- 提供的直方图已经标准化,因此可以使用相同比例的 vM 分布进行绘制。
【问题讨论】:
-
使用您报告的参数(
mu = -0.343和kappa = 10.432),您显示的圆形直方图看起来完全合理。 -
@gboffi 是的。我必须弄清楚如何适应/转换(?)作为我的第一个直方图的方向(这是正确的)
-
我真的很喜欢你发布了所有代码并在问题中包含了图片,这真的很有帮助。
-
顺便说一句,您必须对直方图进行归一化或将 vM 分布乘以样本的数量
标签: python matplotlib