Python 如何从按连续变量分层的熊猫数据帧中获取分层随机样本

Python 如何从按连续变量分层的熊猫数据帧中获取分层随机样本,python,pandas,numpy,scipy,scikit-learn,Python,Pandas,Numpy,Scipy,Scikit Learn,问题:我有一个1000000行的大熊猫数据帧,其中一列表示0到1之间变化的连续(浮点)特性F。数据中F的分布高度偏斜 我想从数据帧中随机抽取N行样本(无需替换),加权后样本中F的直方图将在F=0和F=1之间近似均匀(或尽可能接近均匀!) 显而易见的解决办法是 _ , sampleDF = train_test_split(bigDF, test_size = N, stratify = bigDF['F'] ) 但这会失败并显示错误消息,可能是因为train\u test\u split只应针

问题:我有一个1000000行的大熊猫数据帧,其中一列表示0到1之间变化的连续(浮点)特性F。数据中F的分布高度偏斜

我想从数据帧中随机抽取N行样本(无需替换),加权后样本中F的直方图将在F=0和F=1之间近似均匀(或尽可能接近均匀!)

显而易见的解决办法是

_ , sampleDF = train_test_split(bigDF, test_size = N, stratify = bigDF['F'] )
但这会失败并显示错误消息,可能是因为
train\u test\u split
只应针对离散或分类变量进行分层

ValueError:y中填充最少的类只有1个成员,这太少了。任何类的最小组数不能小于2

理想情况下,这个问题的解决方案应该是快速、稳健的,并且作为一种额外的奖励而简短。我最终提出了一个解决方案,涉及到
stats.gaussian_kde
来估计F的密度,然后将该密度输入到
bigDF.sample(weights=1/density)
,但它涉及到大量的手工调整,而且似乎实际上并没有给出完全均匀的分布。如果没有人有好的解决办法,我可以试着写下来作为答案


有人知道这样做的好方法吗

您将需要这些导入:

from scipy.stats import gaussian_kde
import numpy as np
这是我目前正在使用的功能:

def samplestrat(df, stratifying_column_name, num_to_sample, maxrows_to_est = 10000, bw_per_range = 50, eval_points = 1000 ):
    '''Take a sample of dataframe df stratified by stratifying_column_name
    '''
    strat_col_values = df[stratifying_column_name].values
    samplcol = (df.sample(maxrows_to_est)  if df.shape[0] > maxrows_to_est else df  )[stratifying_column_name].values
    vmin, vmax = min(samplcol), max(samplcol)
    pts = np.linspace(vmin,vmax  ,eval_points) 
    kernel = gaussian_kde( samplcol , bw_method = float(  (vmax - vmin)/bw_per_range  )   )
    density_estim_full = np.interp(strat_col_values, pts , kernel.evaluate(pts) )
    return df.sample(n=num_to_sample, weights = 1/(density_estim_full))
对一些合成数据进行测试:

def sigmoid(x,mi, mx): return mi + (mx-mi)*(lambda t: (1+200**(-t+0.5))**(-1) )( (x-mi)/(mx-mi) )
toyDF = pd.DataFrame( data =  sigmoid(np.random.normal(loc = 10.0, scale = 1.0, size = 10000) , 7 , 13)  ,  columns=['val']  )
pd.DataFrame.hist(toyDF, column = 'val', bins =20 )
plt.show()

这并不完美,但正如我们所见,我们得到了一个相对较好的均匀分布近似值

df_stratified_sample = samplestrat(toyDF, 'val', 1500 )
pd.DataFrame.hist(df_stratified_sample, column = 'val', bins =20 )
plt.show()