【问题标题】:Splitting Pandas dataframe into multiple dataframes based on condition in column根据列中的条件将 Pandas 数据帧拆分为多个数据帧
【发布时间】:2019-02-03 09:40:45
【问题描述】:

要为 ML 任务正确准备数据,我需要能够将原始数据帧拆分为多个较小的数据帧。我想获取上面的所有行,包括“BOOL”列的值为1的行-每次出现1。即n个数据帧,其中n是1的出现次数。

数据样本:

df = pd.DataFrame({"USER_ID": ['001', '001', '001', '001', '001'],
'VALUE' : [1, 2, 3, 4, 5], "BOOL": [0, 1, 0, 1, 0]})

预期输出是 2 个数据帧,如图所示:

还有:

我考虑过使用 if-else 语句来追加行的 for 循环 - 但对于我正在使用的数据集来说,它的效率非常低。寻找一种更蟒蛇的方式来做到这一点。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以使用np.split,它接受要拆分的索引数组:

    np.split(df, *np.where(df.BOOL == 1))
    

    如果您想将带有 BOOL == 1 的行包含到前一个数据框中,您只需将 1 添加到所有索引:

    np.split(df, np.where(df.BOOL == 1)[0] + 1)
    

    【讨论】:

    • 就像一个魅力,但我如何访问每个生成的数据帧?
    • @Ash “访问”是什么意思?该函数返回一个包含所有数据框的列表,以便您可以访问该列表。请注意,索引保留在每个子数据帧中。
    • np.split(df, np.where(df.BOOL == 1)[0] + 1) 也不起作用,您将数据帧拆分为 3 ,我认为他需要 0 到 n (n 是 BOOL ==1 索引)
    • @Wen-Ben 为什么不呢?它确实适用于给定的示例,即使索引超出范围也不会引发错误;在这种情况下,您只会得到空数据框。
    • @a_guest 我认为在他的预期输出中他需要两个数据帧(0-1 和 0-3),然后你返回 3,每个长度都是 2,2,1 对吗?
    【解决方案2】:

    我认为这里使用 for 循环更好

    idx=df.BOOL.nonzero()[0]
    
    d={x : df.iloc[:y+1,:] for x , y in enumerate(idx)}
    d[0]
       BOOL USER_ID  VALUE
    0     0     001      1
    1     1     001      2
    

    【讨论】:

    • 非常好的方法 - 适用于示例数据集。但是由于某些神秘的原因不适用于我的实际数据框。它返回 n 个数据帧 - 所有原始大小。
    • @Ash 不管怎样,我只是按照你的预期输出(上两张图片)
    • @Wen-Ben 你混合了indexiloc 这可能是它不适用于其他数据框的原因(如果索引不是简单的枚举)。
    • @Wen-Ben 但现在对于非数字索引,+1 将失败。所以你可能应该坚持 iloc 并使用索引的位置。
    • @a_guest 检查非零
    【解决方案3】:

    为什么不列出理解?喜欢:

    >>> l=[df.iloc[:i+1] for i in df.index[df['BOOL']==1]]
    >>> l[0]
       BOOL USER_ID  VALUE
    0     0     001      1
    1     1     001      2
    >>> l[1]
       BOOL USER_ID  VALUE
    0     0     001      1
    1     1     001      2
    2     0     001      3
    3     1     001      4
    >>> 
    

    【讨论】:

    • 简化了@Wen-Ben 的 1 行方法——但我仍然遇到同样的问题。适用于样本数据集。但不在我的实际数据框中。这将返回 n 个数据帧 - 所有原始大小。
    • 您将indexiloc 混合在一起,这可能是它不适用于其他数据框的原因(如果索引没有简单的枚举)。
    • @a_guest 对不起,伙计,你能解释一下你的意思吗?不太清楚我理解你所说的混合索引和 iloc 是什么意思?
    • @Ash iloc 返回索引位置,而loc 使用索引它们自己。因此,对于您的示例,没有区别,因为您的索引是 [0, 1, 2, 4, 5] 并且索引匹配它们的位置。但是,如果您使用例如['a', 'b', 'c', 'd', 'e'] 作为索引,那么df.index[df.BOOL == 1] 将返回['b', 'd'],而iloc 需要相应的位置,即[1, 3]。另一方面,@ 987654332@ 确实期望索引,但是您不能进行增量@ 987654333@。因此,在这种情况下,您应该坚持使用index_position = df.BOOL.nonzero()[0] + 1 并将其与df.iloc[:i] 一起使用。
    猜你喜欢
    • 2021-04-18
    • 2018-05-05
    • 2021-04-29
    • 1970-01-01
    • 2019-05-31
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多