[英]create three samples groups in a pd.DataFrame
我有一个pd.DataFrame
,其结构与以下示例类似:
index x y z
0 x0 y0 None
1 x1 y1 None
2 x2 y2 None
3 x3 y3 None
4 x4 y4 None
5 x5 y5 None
6 x6 y6 None
我的目标是创建DataFrame的3个子集:
Group1
是一个训练集,可用于训练模型以预测x和y的 z ; Group2
是一个验证集,用于评估在Group1中训练的模型(或参数的不同模型/调整)的准确性,我将为Group1
和2
填写正确的z值。
保持Group3
直到选择模型来预测z 。
在这种情况下,最有效的分配方法是什么? 我正在考虑只在一个DataFrame中创建子组,如下所示:
index x y z group
- - - - - - - - - - - - - - - - - - - -
0 x0 y0 None training
1 x1 y1 None validation
2 x2 y2 None held out
3 x3 y3 None held out
4 x4 y4 None validation
5 x5 y5 None training
6 x6 y6 None held out
但是我在其他地方看到的有关随机分配的技巧通常会创建一个新的DataFrame。 是因为这样更可行吗?
rows = np.random.choice(df.index.values, 10)
sampled_df = df.ix[rows]
另外,由于我想一次采样3个组而不是2个,所以我不确定什么是最好的不替换采样方法。
你可以用
df['group'] = np.random.choice(
np.repeat(['training', 'validation', 'held out'], (2,2,3)), len(df), replace=False)
为每行分配一个training/validation/held out
标签。 上面的(2,2,3)
表示您希望具有的每种类型的行数。 由于每一行都应获得标签,因此元组的总和应等于len(df)
。
分配标签比创建子DataFrame好吗?
如果分配标签,最终将得到如下代码:
df['group'] = np.random.choice(
np.repeat(['training', 'validation', 'held out'], (2,2,3)), len(df), replace=False)
goodness = dict()
params = dicts()
for model in models:
params[model] = fit(model, df.loc[df['group'] == 'train'])
goodness[model] = validate(model, params[model], df.loc[df['group'] == 'validation'])
best_model = max(models, key=goodness.get)
result = process(best_model, params[best_model], df.loc[df['group'] == 'held_out'])
如果分割df
(使用MaxU的solution ),最终将得到如下代码:
train, validate, held_out = np.split(df.sample(frac=1), [2,4])
goodness = dict()
params = dicts()
for model in models:
params[model] = fit(model, train)
goodness[model] = validate(model, params[model], validate)
best_model = max(models, key=goodness.get)
result = process(best_model, params[best_model], held_out)
每次Python遇到df['group'] == 'train'
,都会扫描整个Series df['group']
-O(N)操作。 df.loc[f['group'] == 'train']
然后从df
复制行以形成新的子DataFrame。 由于这是在一个循环中完成的,因此for model in models
,每个循环要进行两次,因此此O(N)操作将执行2*len(model)
次。
相反,如果一开始就拆分DataFrame,则复制仅完成一次。 因此,MaxU的代码更快。
另一方面,使用标签按需创建子DataFrame会节省一些内存,因为您不会立即实例化所有三个子DataFrame。 但是,除非您对内存的使用非常紧张,否则可能会需要比更高效的内存代码更快的代码。 因此,如果是这样,请使用MaxU的解决方案 。
当然可以
df['group'] = np.random.choice(
np.repeat(['training', 'validation', 'held out'], (2,2,3)), len(df), replace=False)
train, validate, held_out = [df.loc[df['group'] == label] for label in ['train', 'validation', 'held out']]
代替
train, validate, held_out = np.split(df.sample(frac=1), [2,4])
但是以这种方式进行操作也没有速度或内存优势。 您仍然需要从DataFrame扫描和复制三次,而不是一次。 因此,MaxU的解决方案还是首选。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.