【问题标题】:Filter a pandas dataframe by a list of column values通过列值列表过滤熊猫数据框
【发布时间】:2019-05-21 06:43:37
【问题描述】:

这是我的数据框的子样本:

idcontrn    ctosaldo    fecanota    diamovto    fecopera    codsprod
491748      000         2017-08-25         3    2017-08-25         0
1014320     000         2018-05-28     99999    2018-05-28        33
1907630     000         2017-06-12     99999    2017-06-09        21
1573897     000         2018-01-25       613    2018-01-25         0
1713456     000         2017-08-08        17    2017-08-07         0
186315      000         2017-06-29        13    2017-06-28         0
150328      000         2017-10-23         1    2017-10-23        84
1531535     000         2017-04-25         1    2017-04-25        78

我想提取“codsprod”列中出现频率最高的 20 个类别,所以我这样做了:

pd.DataFrame(sample.groupby(['codsprod']).size()).sort_values(by = 0,ascending = False).reset_index()[0:21]

产生:

codsprod    0
0   0   319971
1   76  120026
2   33  62017
3   119 48138
4   14  42180
5   104 40756
6   48  26902

以此类推……直到数字 20。

现在我要做的是通过“codsprod”列的前 20 个类别过滤原始 df。我知道如何根据条件将过滤器应用于 pandas df,但编写如下内容:

sample[sample['codsprod'] == category_number] 对我来说似乎很乏味和漫长,因为我将不得不手动建立 20 个条件,每个类别一个。

有没有更快更简洁的方法来实现这一点??

非常感谢您。

【问题讨论】:

    标签: python python-3.x pandas dataframe conditional-statements


    【解决方案1】:

    使用groupby + size + head 获得最大的'codsprod' 组。使用.isin 过滤原始DataFrame。要获得最大的 2 个组:

    df[df.codsprod.isin(df.groupby('codsprod').size().head(2).index)]
    

    输出:

       idcontrn  ctosaldo    fecanota  diamovto    fecopera  codsprod
    0    491748         0  2017-08-25         3  2017-08-25         0
    2   1907630         0  2017-06-12     99999  2017-06-09        21
    3   1573897         0  2018-01-25       613  2018-01-25         0
    4   1713456         0  2017-08-08        17  2017-08-07         0
    5    186315         0  2017-06-29        13  2017-06-28         0
    

    说明:

    df.groupby('codsprod').size() 返回一个Series,它根据组大小按降序排列。这个Series的值就是组大小,这个Series的索引就是对应的'codsprod'值:

    df.groupby('codsprod').size()
    #codsprod
    #0     4
    #21    1
    #33    1
    #78    1
    #84    1
    #dtype: int64
    

    采用.head(n) 将只返回顶部的n 记录,在这种情况下是n 最大的组。但请注意,它不处理关系,它只需要首先出现的任何内容(这也不会太难包含任何关系):

    df.groupby('codsprod').size().head(2)
    #codsprod
    #0     4
    #21    1
    #dtype: int64
    

    此时,您并不关心组有多大,您想知道哪些组最大。所以你需要这个系列的索引。

    df.groupby('codsprod').size().head(2).index
    #Int64Index([0, 21], dtype='int64', name='codsprod')
    

    这基本上是'codsprod' 值的列表,并根据值等于您使用.isin 的列表中的任何值来过滤DataFrame

    【讨论】:

    • 嘿,非常感谢您的回答。抱歉,为什么是head(2) 而不是head(20)??
    • @Miguel2488 对于您的真实数据,您将使用.head(20) 只是想在这里表明它实际上会过滤原始DataFrame。使用 .head(20) 在这种情况下它不会过滤任何内容(少于 20 个组),所以它不是很能说明问题。
    • 还要小心,因为您可以在这里看到,它可能无法按照您的意愿处理领带。
    • 谢谢!!为了学习和理解,请允许我再问你几个问题。因此,我们可以使用具有指定值的 head 来获得我们想要的结果数量,而不是使用切片和索引?而且我还猜想过滤魔法在.isin 方法中,对吗?为什么最后使用.index?这是在做什么?? “领带”是什么意思??
    • 真的非常感谢,解释再好不过了,我觉得我学到了关于熊猫数据过滤的非常重要的一课。 :)
    猜你喜欢
    • 2020-08-08
    • 2022-01-04
    • 2017-12-15
    • 2021-12-01
    • 1970-01-01
    • 2014-12-02
    • 2023-02-02
    • 2020-08-16
    • 2016-08-31
    相关资源
    最近更新 更多