【问题标题】:Pandas split DataFrame by column valuePandas 按列值拆分 DataFrame
【发布时间】:2016-02-17 23:26:47
【问题描述】:

我有DataFrameSales 列。

如何根据Sales 值将其拆分为 2?

第一个DataFrame 将有'Sales' < s 和第二个'Sales' >= s 的数据

【问题讨论】:

    标签: python pandas dataframe indexing split


    【解决方案1】:

    你可以使用boolean indexing:

    df = pd.DataFrame({'Sales':[10,20,30,40,50], 'A':[3,4,7,6,1]})
    print (df)
       A  Sales
    0  3     10
    1  4     20
    2  7     30
    3  6     40
    4  1     50
    
    s = 30
    
    df1 = df[df['Sales'] >= s]
    print (df1)
       A  Sales
    2  7     30
    3  6     40
    4  1     50
    
    df2 = df[df['Sales'] < s]
    print (df2)
       A  Sales
    0  3     10
    1  4     20
    

    也可以将mask 反转为~

    mask = df['Sales'] >= s
    df1 = df[mask]
    df2 = df[~mask]
    print (df1)
       A  Sales
    2  7     30
    3  6     40
    4  1     50
    
    print (df2)
       A  Sales
    0  3     10
    1  4     20
    

    print (mask)
    0    False
    1    False
    2     True
    3     True
    4     True
    Name: Sales, dtype: bool
    
    print (~mask)
    0     True
    1     True
    2    False
    3    False
    4    False
    Name: Sales, dtype: bool
    

    【讨论】:

    • 有没有办法做到这一点而不必对数据帧进行两次切片?因为这样我们将不得不翻转索引 onve 来创建 df1,并在另一个时间为 df2 完全相同的条件。但我不知道如何在一行中获取两个数据帧..
    • 不幸的是,我认为只有这个解决方案 - 请参阅 cookbook
    • 使用mask 与传统切片之间的性能差异是什么?我的测试显示 mask 有点快,但差别不大
    • @Mike Palmice 嗯,如果认为第一段和第二段的性能相同,那么由你决定哪种方法更适合你。如果需要多次组合或者需要重复使用掩码,第二个应该会更好,如果一些长而复杂的掩码那么第二个应该更具可读性。
    • 不完全是,但我通过 for 循环弄明白了;遍历每个唯一的列值,然后通过切片将 df 按值拆分。其实也不难,我什至不知道我为什么问。不过还是谢谢。
    【解决方案2】:

    使用groupby,您可以拆分为两个数据帧,例如

    In [1047]: df1, df2 = [x for _, x in df.groupby(df['Sales'] < 30)]
    
    In [1048]: df1
    Out[1048]:
       A  Sales
    2  7     30
    3  6     40
    4  1     50
    
    In [1049]: df2
    Out[1049]:
       A  Sales
    0  3     10
    1  4     20
    

    【讨论】:

    • 这个操作似乎比 jezrael 的两个选项更昂贵,虽然语法上更优雅 imo
    • 这并不完全等同于 jezrael 的选项。如果拆分后其中一个数据集为空,则 group by 将返回仅包含一个元素的列表,并且将无法解压缩为 df1 和 df2。
    【解决方案3】:

    使用“groupby”和列表理解:

    将所有拆分的数据帧存储在列表变量中,并通过索引访问每个分离的数据帧。

    DF = pd.DataFrame({'chr':["chr3","chr3","chr7","chr6","chr1"],'pos':[10,20,30,40,50],})
    ans = [y for x, y in DF.groupby('chr', as_index=False)]
    

    像这样访问分离的 DF:

    ans[0]
    ans[1]
    ans[len(ans)-1] # this is the last separated DF
    

    像这样访问分离的 DF 的列值:

    ansI_chr=ans[i].chr 
    

    【讨论】:

    • 这是一个很好的答案!
    • 我认为你可以简化为 ans = [y for x, y in DF.groupby('chr', as_index=False)],因为 y 已经是一个 DataFrame
    • 这个答案不依赖于拆分的数量。它应该被投票#1 只需要根据@C8H10N4O2 的评论更新它
    【解决方案4】:

    使用海象运算符的单线(Python 3.8):

    df1, df2 = df[(mask:=df['Sales'] >= 30)], df[~mask]
    

    考虑使用copy 来避免SettingWithCopyWarning

    df1, df2 = df[(mask:=df['Sales'] >= 30)].copy(), df[~mask].copy()
    

    或者,你可以使用query的方法:

    df1, df2 = df.query('Sales >= 30').copy(), df.query('Sales < 30').copy()
    

    【讨论】:

      【解决方案5】:

      我喜欢用它来加速搜索或滚动平均查找 .apply(lambda x...) 类型的函数,因此我将大文件拆分为数据框字典:

      df_dict = {sale_v: df[df['Sales'] == sale_v] for sale_v in df.Sales.unique()}
      

      如果您想基于分类组,应该这样做。

      【讨论】:

        猜你喜欢
        • 2020-11-30
        • 1970-01-01
        • 1970-01-01
        • 2016-05-13
        • 2018-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多