如何从pandas数据帧中统一抽取每个子组的n行

2024-04-26 01:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

在pandas数据帧中,我有具有不同且大量行的子组。我希望减少用于初步分析的行数,同时确保数据在整个范围内仍然具有代表性。在

我用2个因子或参数('A','B')和每个因子2个级别或值('A1','A2','B1','B2')运行了一个模拟。每个模拟对应于'A','B'值的组合。在计数器高于定义的数字(下例中为“35”)后,模拟停止。 对于每个模拟,计数器及其增加量都是不同的。在每个步骤中,从模拟中总结出一个值'eval'。在

下面的示例显示了模拟结果的示例。现在,模拟实际运行的时间要长得多(举个例子来说,直到它超过10000),并且在我的初步分析中,绘制eval值的演变图需要几个小时。在

此代码生成模拟结果的示例:

import pandas as pd
import numpy as np

columns = ['FactorA', 'FactorB', 'step']
data = [['A1', 'B1', 8], ['A1', 'B1', 13], ['A1', 'B1', 18], ['A1', 'B1', 23], ['A1', 'B1', 28], ['A1', 'B1', 33], ['A1', 'B1', 38],
        ['A1', 'B2', 7], ['A1', 'B2', 13],['A1', 'B2', 19],['A1', 'B2', 25],['A1', 'B2', 31],['A1', 'B2', 37],
        ['A2', 'B1', 6], ['A2', 'B1', 14],['A2', 'B1', 22],['A2', 'B1', 30],['A2', 'B1', 38],
        ['A2', 'B2', 10], ['A2', 'B2', 12],['A2', 'B2', 14],['A2', 'B2', 16],['A2', 'B2', 18],['A2', 'B2', 20],['A2', 'B2', 22],['A2', 'B2', 24],['A2', 'B2', 26],['A2', 'B2', 28],['A2', 'B2', 30],['A2', 'B2', 32],['A2', 'B2', 34],['A2', 'B2', 36]
       ]
df = pd.DataFrame(data, columns=columns)
df['eval'] = np.random.randint(1, 6, df.shape[0])

我尝试过这样做,但虽然它减少了数据点,但它不能平衡每个模拟的数据点数量:

^{pr2}$

也尝试过:

^{3}$

但它也不能平衡每次模拟的数据点数量。在

我想要一个数据帧,其中每个子组具有相同的行数。 为了确保选择或采样是平衡的,我希望使用.iloc对每个子组的切片考虑确保为每个子组选择'n'个成员的步骤。 最好是包含每个子组的第一行和最后一行。在


Tags: columns数据importa2示例pandasdfa1
2条回答

请看您帖子中的以下说明:

df.sample(n=int(len(df)))

奇怪的是:

  • 不需要int(len已经有int类型)。在
  • len(df)df选择所有行,因此您的“sample”是这样创建的 包含完整原始df,仅对顺序进行无序处理。 这是你想要的吗?在

就集团平衡而言:

决定如何保持平衡:

  • 选项1:每组样本行数相等。在
  • 选择2:每组样本的分数相等。在

当你下定决心时:

  • 对组条件运行源数据帧的groupby
  • 应用从当前组返回相应样本的函数。在

示例:如果要从df中选择2行的样本 每组(选项1),运行:

^{pr2}$

如果要返回原始(单级)索引,请添加:

.reset_index(level=[0, 1], drop=True)

按照上面的指示。在

如果你喜欢选项2(分数),改变n=。。。frac=。。。。在

在@Valdi_Bo的回答之后,我进入了Group By: split-apply-combine页面,将herehereherehere、和{a6}中的想法混合起来,得到了一个不优雅但有效的解决方案。在

对于示例中的dataframe,我们可以计算每个组的行数:

grouped = df.groupby(['FactorA','FactorB'])
grouped.size()

这会产生:

^{pr2}$

为了将每个组的数据行减少到一个以上但接近3的数字,每个子组的step列中的值之间的间距相等,并强制包含最大的step,我使用:

def filter_group(dfg, col, qty):
    col_min = dfg[col].min()
    col_max = dfg[col].max()
    col_length = dfg[col].size
    jumps = col_length-1
    jump_size = int((col_max - col_min) / jumps)
    new_jump_size =  jumps/qty
    if new_jump_size > 1:
        new_jump_size = int(new_jump_size)*jump_size
    else:
        new_jump_size = jump_size

    col_select = list(range(col_min, col_max, new_jump_size))
    col_select.append(col_max)

    return dfg[dfg[col].isin(col_select)]
grouped = df.groupby(['FactorA','FactorB'], group_keys=False).apply(lambda x: filter_group(x,'step',3))

我们可以验证演示数据帧的行数:

grouped = grouped.groupby(['FactorA','FactorB'])
grouped.size()

这会产生:

FactorA  FactorB
A1       B1         4
         B2         6
A2       B1         5
         B2         5
dtype: int64

如果有时间的话,我会尝试,并在修改它以使用与steps列范围相关的权重的示例函数时发布它。所以我得到了一半的数据点在前三分之一的范围内。在

相关问题 更多 >