【问题标题】:How to sample from pandas DataFrame n rows from each subgroup uniformly如何从每个子组的pandas DataFrame中统一采样n行
【发布时间】:2019-11-05 15:45:52
【问题描述】:

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

我使用 2 个因子或参数 ('A','B') 以及每个因子 ('A1','A2','B1','B2') 的 2 个水平或值运行了一个模拟。每个模拟对应于'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])

我试过这个,但是虽然它减少了数据点,但它并没有平衡每次模拟的数据点数量:

df_reduced = df.iloc[::2]

也试过了:

df_reduced = df.sample(n=int(len(df)/6))

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

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

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

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

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

    这里有什么奇怪的:

    • int 不需要(len 已经有 int 类型)。
    • len(df)df 中选择 所有 行,因此您的“样本”以这种方式创建 包含 full 原始 df,仅打乱顺序。 这是你想要的吗?

    就群体平衡而言:

    决定如何保持平衡:

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

    当你下定决心时:

    • 在组标准上运行源 DataFrame 的 groupby
    • 应用从当前组返回相应样本的函数。

    示例:如果您想从 df 中选择 2 行的示例 每个组(选项 1),运行:

    df.groupby(['FactorA', 'FactorB']).apply(lambda grp: grp.sample(n=2))
    

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

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

    到上面的指令。

    如果您更喜欢选项 2(分数),请将 n=... 更改为 frac=...

    【讨论】:

    • 我刚刚编辑了我的帖子,以展示我如何使用df.sample 来减少我的数据行。感谢您指向groupby 函数。因为我想从每个模拟中获得相同的数据点,所以我现在有办法做到这一点。在阅读了一些文档后只是一个快速的疑问。如果我有两个具有相同数量和步骤顺序的子组或模拟,¿有没有办法确保选择相同的步骤?这就是我使用iloc 的意图
    • 如果你想从2个子组中选择具有相同步骤的行,恐怕没有Pandas函数可以做出这样的选择。也许您应该编写自己的函数来执行此操作(找到常见的步骤集并仅通过这些步骤选择行)。如果有 两个 组可供选择,我可以弄清楚该怎么做,但是如果有更多组(实际上你有 四个 其中)。
    【解决方案2】:

    在@Valdi_Bo 的回答之后,我进入了Group By: split-apply-combine 的页面,并将hereherehereherehere 中的想法混合在一起,得到了一个不优雅的但可行的解决方案。

    对于示例中的数据框,我们可以统计每组的行数:

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

    这会产生:

    FactorA  FactorB
    A1       B1          7
             B2          6
    A2       B1          5
             B2         14
    dtype: int64
    

    并将每个组的数据行减少到一个以上但接近三个的数字,每个子组的 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))
    

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

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

    这会产生:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-21
      • 2021-10-05
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 2018-04-22
      • 2012-08-24
      • 2022-01-21
      相关资源
      最近更新 更多