我想从以下df中使用python进行随机抽样选择,以使至少65%的所得样本应具有黄色,并且所选数量的累积总和应小于或等于18。
原始数据集:
Date Id color qty
02-03-2018 A red 5
03-03-2018 B blue 2
03-03-2018 C green 3
04-03-2018 D yellow 4
04-03-2018 E yellow 7
04-03-2018 G yellow 6
04-03-2018 H orange 8
05-03-2018 I yellow 1
06-03-2018 J yellow 5
我总共有数量。选定的条件已涵盖,但停留在如何与%条件进行积分上:
df2 = df1.sample(n = df1.shape [0])
df3 = df2 [df2.qty.cumsum()<= 18]
所需数据集:
Date Id color qty
03-03-2018 B blue 2
04-03-2018 D yellow 4
04-03-2018 G yellow 6
06-03-2018 J yellow 5
或者类似这样的东西:
Date Id color qty
02-03-2018 A red 5
04-03-2018 D yellow 4
04-03-2018 E yellow 7
05-03-2018 I yellow 1
任何帮助将不胜感激!
谢谢。
答案 0 :(得分:1)
使用'yellow'
过滤行,并选择一个至少占总样本量65%的随机样本
import random
yellow_size = float(random.randint(65,100)) / 100
df_yellow = df3[df3['color'] == 'yellow].sample(yellow_size*sample_size)
用其他颜色过滤行,并为剩余的样本量选择一个随机样本。
others_size = 1 - yellow_size
df_others = df3[df3['color'] != 'yellow].sample(others_size*sample_size)
将两者结合在一起,并随机排列行。
df_sample = pd.concat([df_yellow, df_others]).sample(frac=1)
更新:
如果要同时检查两个条件,这可能是一种方法:
import random
df_sample = df
while sum(df_sample['qty']) > 18:
yellow_size = float(random.randint(65,100)) / 100
df_yellow = df[df['color'] == 'yellow'].sample(yellow_size*sample_size)
others_size = 1 - yellow_size
df_others = df[df['color'] != 'yellow'].sample(others_size*sample_size)
df_sample = pd.concat([df_yellow, df_others]).sample(frac=1)
答案 1 :(得分:0)
我将使用此程序包将您的黄色过度采样为具有所需余额的新样本:
https://imbalanced-learn.readthedocs.io/en/stable/over_sampling.html
从那里随机选择项目并检查总和,直到获得所需的设置。
时间复杂度较低的方法是二进制搜索范围为数据帧长度的范围,然后使用二进制搜索项作为样本大小,直到获得所需的总和。假定特征是对称分布的。
答案 2 :(得分:0)
我认为这个例子对您有帮助。我添加df2 ['yellow_rate']列并计算汇率。您只需检查df2.iloc [df2.shape [0]-1] ['yellow_rate']值。
df1=pd.DataFrame({'id':['A','B','C','D','E','G','H','I','J'],'color':['red','bule','green','yellow','yellow','yellow','orange','yellow','yellow'], 'qty':[5,2, 3, 4, 7, 6, 8, 1, 5]})
df2 = df1.sample(n=df1.shape[0])
df2['yellow_rate'] = df2[df2.qty.cumsum() <= 18]['color'].apply( lambda x : 1 if x =='yellow' else 0)
df2 = df2.dropna().append(df2.sum(numeric_only=True)/ df2.count(numeric_only=True), ignore_index=True)