matplotlib - statsmodels:IntegrationWarning:已达到最大细分数(50)
问题描述
尝试使用 seaborns 绘制 CDF,然后遇到此错误:
../venv/lib/python3.7/site-packages/statsmodels/nonparametric/kde.py:178: IntegrationWarning: The maximum number of subdivisions (50) has been achieved.
If increasing the limit yields no improvement it is advised to analyze
the integrand in order to determine the difficulties. If the position of a
local difficulty can be determined (singularity, discontinuity) one will
probably gain from splitting up the interval and calling the integrator
on the subranges. Perhaps a special-purpose integrator should be used.
args=endog)[0] for i in range(1, gridsize)]
按下回车键几分钟后
../venv/lib/python3.7/site-packages/statsmodels/nonparametric/kde.py:178: IntegrationWarning: The integral is probably divergent, or slowly convergent.
args=endog)[0] for i in range(1, gridsize)]
代码:
plt.figure()
plt.title('my distribution')
plt.ylabel('CDF')
plt.xlabel('x-labelled')
sns.kdeplot(data,cumulative=True)
plt.show()
如果有帮助:
print(len(data))
4360700
样本数据:
print(data[:10])
[ 0.00362846 0.00123409 0.00013711 -0.00029235 0.01515175 0.02780404
0.03610236 0.03410224 0.03887933 0.0307084 ]
不知道细分是什么,有没有办法增加呢?
解决方案
通过对每个数据点求和一个高斯钟形来创建kde图。对 400 万条曲线求和会产生内存和性能问题,这可能会导致来函数失败。确切的错误消息可能非常神秘。
解决该问题的最简单方法是对数据进行二次采样,因为对于或多或少的平滑分布,无论数据是否进行二次采样,kde(以及累积的 kde 或 cdf)看起来都非常相似。使用切片很容易每 100个data[::100]
条目进行二次采样。
或者,对于这么多数据,可以通过绘制排序数据与从 0 到 1 的 N 个均匀间隔的数字来绘制“真实”cdf。(其中 N 是数据点的数量。)
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
N = 1000000
data = np.random.normal(np.repeat(np.random.uniform(10, 20, 10), N // 10), 1)
sns.kdeplot(data[::100], cumulative=True, color='g', label='cumulative kde')
q = np.linspace(0, 1, data.size)
data.sort()
plt.plot(data, q, ':r', lw=2, label='cdf from sorted data')
plt.legend()
plt.show()
请注意,考虑到足够大的排序数据数组的差异,您可以通过类似的方式绘制一个“更诚实”的 kde,尽管稍微复杂一些。np.interp
将分位数插值到规则间隔的 x 轴. 由于原始差异相当参差不齐,因此需要进行一些平滑处理。
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import statsmodels.api as sm
N = 1000000
data = np.random.normal(np.repeat(np.random.uniform(10, 20, 10), N // 10), 1)
sns.kdeplot(data[::100], cumulative=False, color='g', label='kde')
p = np.linspace(0, 1, data.size)
data.sort()
x = np.linspace(data.min(), data.max(), 1000)
y = np.interp(x, data, p)
# use lowess filter to smoothen the curve
lowess = sm.nonparametric.lowess(np.diff(y) * 1000 / (data.max() - data.min()), (x[:-1] + x[1:]) / 2, frac=0.05)
plt.plot(lowess[:, 0], lowess[:, 1], '-r', label='smoothed diff of sorted data')
# plt.plot((x[:-1]+x[1:])/2,
# np.convolve(np.diff(y), np.ones(20)/20, mode='same')*1000/(data.max() - data.min()),
# label='test np.diff')
plt.legend()
plt.show()
推荐阅读
- database - 插入 MATCH_RECOGNIZE 选择 Oracle 的第一行和最后一行
- c++ - stl 算法,constexpr,C++
- reactjs - aws-sdk S3:在 Reactjs 中使用 listObjectsV2 列出所有键
- postgresql - 这两个实体关系之间有什么区别吗?
- azure - Azure 管道因“应用程序必须在名为 embedded.mobileprovision 的文件中包含配置文件”而失败
- php - PHP isset 后置条件不执行
- python - 什么是使数组中的下 n 项为 True 的最 Pythonic 方法,只要数组中有 True 值
- javascript - 静态容器内的 CSS 剪辑图像绝对定位到祖父母
- python - 我想把一个字符串(基本上应该是一个字典列表)变成一个字典列表?
- javafx-11 - 根据 GPS 输入动态更新 Javafx 节点