meo*_*eow 5 python sampling pandas
我有一个包含D实例数据集的Pandas DataFrame ,这些实例都具有一些连续值x。x以某种方式分布,比如说统一,可以是任何东西。
我想提请n样本D用于其x拥有的目标分配,我可以品尝或近似。这是来自一个数据集,这里我只取正态分布。
如何从中采样实例,D使得样本中的分布x等于/类似于我指定的任意分布?
现在,我对一个 value x,子集进行采样,D以便它包含所有内容x +- eps并从中采样。但是当数据集变大时,这很慢。人们一定想出了一个更好的解决方案。也许解决方案已经很好,但可以更有效地实施?
我可以分成x层,这样会更快,但是没有这个有解决方案吗?
我当前的代码运行良好但速度很慢(30k/100k 为 1 分钟,但我有 200k/700k 左右。)
import numpy as np
import pandas as pd
import numpy.random as rnd
from matplotlib import pyplot as plt
from tqdm import tqdm
n_target = 30000
n_dataset = 100000
x_target_distribution = rnd.normal(size=n_target)
# In reality this would be x_target_distribution = my_dataset["x"].sample(n_target, replace=True)
df = pd.DataFrame({
'instances': np.arange(n_dataset),
'x': rnd.uniform(-5, 5, size=n_dataset)
})
plt.hist(df["x"], histtype="step", density=True)
plt.hist(x_target_distribution, histtype="step", density=True)
def sample_instance_with_x(x, eps=0.2):
try:
return df.loc[abs(df["x"] - x) < eps].sample(1)
except ValueError: # fallback if no instance possible
return df.sample(1)
df_sampled_ = [sample_instance_with_x(x) for x in tqdm(x_target_distribution)]
df_sampled = pd.concat(df_sampled_)
plt.hist(df_sampled["x"], histtype="step", density=True)
plt.hist(x_target_distribution, histtype="step", density=True)
Run Code Online (Sandbox Code Playgroud)
不是生成新点并在 中查找最近邻点df.x,而是定义应根据目标分布对每个点进行采样的概率。您可以使用np.random.choice。df.x对于高斯目标分布,在一秒左右的时间内采样一百万个点,如下所示:
x = np.sort(df.x)
f_x = np.gradient(x)*np.exp(-x**2/2)
sample_probs = f_x/np.sum(f_x)
samples = np.random.choice(x, p=sample_probs, size=1000000)
Run Code Online (Sandbox Code Playgroud)
sample_probs是关键数量,因为它可以连接回数据框或用作 的参数df.sample,例如:
# sample df rows without replacement
df_samples = df["x"].sort_values().sample(
n=1000,
weights=sample_probs,
replace=False,
)
Run Code Online (Sandbox Code Playgroud)
的结果plt.hist(samples, bins=100, density=True):
让我们看看当原始样本是从高斯分布中抽取并且我们希望从均匀目标分布中采样时该方法的执行情况:
x = np.sort(np.random.normal(size=100000))
f_x = np.gradient(x)*np.ones(len(x))
sample_probs = f_x/np.sum(f_x)
samples = np.random.choice(x, p=sample_probs, size=1000000)
Run Code Online (Sandbox Code Playgroud)
在此分辨率下,尾部看起来有些抖动,但如果我们增加 bin 大小,它们就会变得平滑。
样本的近似概率计算x公式如下:
概率 (x_i) ~ delta_x*rho(x_i)
其中rho(x_i)是密度函数,np.gradient(x)用作微分值。如果忽略差分权重,f_x则在重采样中将过度表示接近点而低估稀疏点。我最初犯了这个错误,影响很小,因为 x 是均匀分布的(但通常可能很重要):
| 归档时间: |
|
| 查看次数: |
860 次 |
| 最近记录: |