【问题标题】:Slicing Pandas Dataframe according to number of lines根据行数对 Pandas Dataframe 进行切片
【发布时间】:2017-05-21 04:30:04
【问题描述】:

我想这很简单,但我不知道怎么做。我一直在搜索教程和stackoverflow。

假设我有一个像这样的数据框 df:

Group   Id_In_Group   SomeQuantity
1        1              10
1        2              20
2        1               7
3        1              16
3        2              22
3        3               5
3        4              12
3        5              28
4        1               1
4        2              18
4        3              14
4        4               7
5        1              36

我只想选择组中至少有 4 个对象的行(因此至少有 4 行具有相同的“组”编号),并且当在组中排序时,第 4 个对象的 SomeQuantity SomeQuantity 升序,大于 20(例如)。

例如,在给定的 Dataframe 中,它只会返回第 3 个组,因为它有 4 个(>=4)个成员,并且它的第 4 个 SomeQuantity(排序后)是 22(>=20),所以它应该构造数据框:

Group   Id_In_Group   SomeQuantity
3        1              16
3        2              22
3        3               5
3        4              12
3        5              28

(无论是否按 SomeQuantity 排序)。

有人可以帮助我吗? :)

【问题讨论】:

    标签: python pandas dataframe slice


    【解决方案1】:

    我会使用.groupby() + .filter() 方法:

    In [66]: df.groupby('Group').filter(lambda x: len(x) >= 4 and x['SomeQuantity'].max() >= 20)
    Out[66]:
       Group  Id_In_Group  SomeQuantity
    3      3            1            16
    4      3            2            22
    5      3            3             5
    6      3            4            12
    7      3            5            28
    

    【讨论】:

    • 最好不要鼓励将列作为属性访问,即使这在这种情况下有效,例如:df.groupby('Group').filter(lambda x: len(x) >= 4 and x['SomeQuantity'].max() >= 20) +1 仍然
    • 应该是&还是不是?
    • @TedPetrou 这里的 lambda 将是单行值而不是数组,所以 and 在这里是正确的
    • 真是太完美了!非常感谢@MaxU。
    • 感谢@EdChum 的精确。 :)
    【解决方案2】:

    使用mapvalue_countsgroupbyfilter 的方法略有不同:

    (df[df.Group.map(df.Group.value_counts().ge(4))]
       .groupby('Group')
       .filter(lambda x: np.any(x['SomeQuantity'].sort_values().iloc[3] >= 20)))
    


    步骤分解:

    执行value_counts 计算Group 列中存在的不同元素的总数。

    >>> df.Group.value_counts()
    
    3    5
    4    4
    1    2
    5    1
    2    1
    Name: Group, dtype: int64
    

    使用map,其功能类似于字典(其中索引成为键,系列元素成为值)将这些结果映射回原始DF

    >>> df.Group.map(df.Group.value_counts())
    
    0     2
    1     2
    2     1
    3     5
    4     5
    5     5
    6     5
    7     5
    8     4
    9     4
    10    4
    11    4
    12    1
    Name: Group, dtype: int64
    

    然后,我们检查具有 4 或更大值的元素,这是我们的阈值限制,并仅从整个 DF 中获取那些子集。

    >>> df[df.Group.map(df.Group.value_counts().ge(4))]   
    
        Group  Id_In_Group  SomeQuantity
    3       3            1            16
    4       3            2            22
    5       3            3             5
    6       3            4            12
    7       3            5            28
    8       4            1             1
    9       4            2            28
    10      4            3            14
    11      4            4             7
    

    为了对此使用groupby.filter操作,我们必须确保在执行排序过程时返回与每个分组键对应的单个布尔值,并将第四个元素与阈值20进行比较。 np.any 返回与我们的过滤器匹配的所有此类可能性。

    >>> df[df.Group.map(df.Group.value_counts().ge(4))]         \
          .groupby('Group').apply(lambda x: x['SomeQuantity'].sort_values().iloc[3])
    
     Group
    3    22
    4    18
    dtype: int64
    

    根据这些,我们比较第四个元素 .iloc[3],因为它是从 0 开始索引的,并返回所有这些有利的匹配项。

    【讨论】:

    • 是的,这个完美!!!!非常感谢。我不确定是否完全理解答案,例如,我应该看一下地图,但无论如何我都可以使用结果! :) :) :) :)
    • 很好的答案:)
    【解决方案3】:

    这就是我解决您的问题的方式,疣和所有问题。我相信有很多更好的方法可以做到这一点。

    查找“组中有 4 个对象”的组

    import collections
    
    groups = list({k for k, v in collections.Counter(df.Group).items() if v > 3} );groups
    
    Out:[3, 4]
    

    使用这些组过滤到包含这些组的新 df:

    df2 = df[df.Group.isin(groups)]
    

    “第 4 个 SomeQuantity(排序后)为 22 (>=20)”

     df3 = df2.sort_values(by='SomeQuantity',ascending=False)
    

    (根据下面的评论更新...)

    df3.groupby('Group').filter(lambda grp: any(grp.sort_values('SomeQuantity').iloc[3] >= 20)).sort_index()
    
        Group   Id_In_Group SomeQuantity
      3    3        1       16
      4    3        2       22
      5    3        3       5
      6    3        4       12
      7    3        5       28
    

    【讨论】:

    • 非常感谢,我真的需要解决这个问题。 :) 不幸的是,您的方法似乎也不起作用:如果我在第 3 组中将 SomeQuantity 设置为 19 而不是 22,它仍然返回第 3 组,尽管没有任何组符合标准...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    相关资源
    最近更新 更多