模拟渗透/采用外推的CDF曲线

2024-05-16 03:53:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望能够为正态分布绘制一条类似cumulative distribution function的线,因为它对于模拟采用曲线非常有用:

Adoption curve

具体来说,我希望能够使用初始数据(产品采用率)来推断该曲线的其余部分,从而粗略估计每个阶段的时间线。例如,如果我们在30天内达到10%的渗透率,在40天内达到20%的渗透率,我们试着拟合这条曲线,我想知道我们什么时候才能达到80%的渗透率(而另一个人口可能需要50天才能达到10%的渗透率)

所以,我的问题是,我该怎么做呢?理想情况下,我能够提供初始数据(时间和渗透率),并使用python(例如matplotlib)为我绘制图表的其余部分。但我不知道从哪里开始!谁能给我指出正确的方向吗

(顺便说一句,我也在CrossValidated上发布了这个问题,但我不确定它是属于那里,因为它是一个统计问题,还是属于这里,因为它是一个python问题。为重复道歉!)


Tags: 数据产品时间绘制function阶段曲线distribution
1条回答
网友
1楼 · 发布于 2024-05-16 03:53:25

cdf可以通过scipy.stats.norm.cdf()计算。它的ppf可用于帮助映射所需的对应关系scipy.interpolate.pchip然后可以创建一个函数,以使变换平滑插值

import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter
import numpy as np
from scipy.interpolate import pchip  # monotonic cubic interpolation
from scipy.stats import norm

desired_xy = np.array([(30, 10), (40, 20)])  # (number of days, percentage adoption)
# desired_xy = np.array([(0, 1), (30, 10), (40, 20), (90, 99)])
labels = ['Innovators', 'Early\nAdopters', 'Early\nMajority', 'Late\nMajority', 'Laggards']
xmin, xmax = 0, 90  # minimum and maximum day on the x-axis

px = desired_xy[:, 0]
py = desired_xy[:, 1] / 100

# smooth function that transforms the x-values to the  corresponding spots to get the desired y-values
interpfunc = pchip(px, norm.ppf(py))

fig, ax = plt.subplots(figsize=(12, 4))
# ax.scatter(px, py, color='crimson', s=50, zorder=3)  # show desired correspondances
x = np.linspace(xmin, xmax, 1000)
ax.plot(x, norm.cdf(interpfunc(x)), lw=4, color='navy', clip_on=False)

label_divs = np.linspace(xmin, xmax, len(labels) + 1)
label_pos = (label_divs[:-1] + label_divs[1:]) / 2
ax.set_xticks(label_pos)
ax.set_xticklabels(labels, size=18, color='navy')
min_alpha, max_alpha = 0.1, 0.4
for p0, p1, alpha in zip(label_divs[:-1], label_divs[1:], np.linspace(min_alpha, max_alpha, len(labels))):
    ax.axvspan(p0, p1, color='navy', alpha=alpha, zorder=-1)
    ax.axvline(p0, color='white', lw=1, zorder=0)
ax.axhline(0, color='navy', lw=2, clip_on=False)
ax.axvline(0, color='navy', lw=2, clip_on=False)
ax.yaxis.set_major_formatter(PercentFormatter(1))
ax.set_xlim(xmin, xmax)
ax.set_ylim(0, 1)
ax.set_ylabel('Total Adoption', size=18, color='navy')
ax.set_title('Adoption Curve', size=24, color='navy')
for s in ax.spines:
    ax.spines[s].set_visible(False)
ax.tick_params(axis='x', length=0)
ax.tick_params(axis='y', labelcolor='navy')
plt.tight_layout()
plt.show()

resulting plot

desired_xy仅使用两个点,曲线将线性拉伸。如果给出更多点,将应用平滑变换。下面是使用[(0, 1), (30, 10), (40, 20), (90, 99)]时的情况。请注意0 %100 %将导致问题,因为它们位于正负无穷远处

fixing at 4 points

相关问题 更多 >