繁体   English   中英

在pd.DataFrame中创建三个样本组

[英]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是一个训练集,可用于训练模型以预测xy的 z
  • Group2是一个验证集,用于评估在Group1中训练的模型(或参数的不同模型/调整)的准确性,我将为Group12填写正确的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM