2017-08-03 139 views
1

問題:我有一個擁有1,000,000行的大熊貓數據框,連續(浮點)功能列爲F, 0和1.在數據中,F的分佈高度偏斜。如何從一個連續變量分層的Pandas數據框中分層隨機抽樣

我想利用從數據幀N行的隨機樣本(沒有替換),之間加權,使得的˚F樣品中的直方圖將大致均勻(或儘可能接近均勻!) ˚F = 0和˚F = 1

顯而易見的解決方案是

_ , sampleDF = train_test_split(bigDF, test_size = N, stratify = bigDF['F']) 

但這失敗的錯誤消息,大概是因爲train_test_split僅應該關於離散或分類變量進行分層。

ValueError: The least populated class in y has only 1 member, which is too few. The minimum number of groups for any class cannot be less than 2.

理想情況下,解決方案將是快速和強大的,並作爲獎金短。我最終想出了一個解決方案,包括stats.gaussian_kde來估計密度F,然後將該密度輸入到bigDF.sample(weights = 1/density),但它涉及大量的手工調整,此外似乎並未實際給出完全均勻的分佈。如果沒有人有一個好的解決方案,我可能會試圖把它寫成答案。

有沒有人知道一個很好的方法來做到這一點?

回答

1

您將需要這些進口:

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() 

distribution

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

distribution after stratified

這不是完美的,但我們可以看到,我們取得了比較好的近似均勻分佈。