【问题标题】:Python pandas - how to group close elementsPython pandas - 如何对关闭元素进行分组
【发布时间】:2018-01-05 08:15:42
【问题描述】:

我有一个数据框,我需要对距离不超过 1 的元素进行分组。 例如,如果这是我的 df:

     group_number  val
0              1    5
1              1    8
2              1   12
3              1   13
4              1   22
5              1   26
6              1   31
7              2    7
8              2   16
9              2   17
10             2   19
11             2   29
12             2   33
13             2   62

所以我需要按group_numberval 进行分组,其中val 的值小于或等于1。

因此,在本例中,23 行将组合在一起,89 行也会组合在一起。

我尝试使用 diff 或相关函数,但我没有弄明白。

任何帮助将不胜感激!

【问题讨论】:

    标签: python algorithm pandas group-by


    【解决方案1】:

    使用 diff 是正确的方法 - 只需将其与 gtcumsum 结合使用,您就拥有了自己的群组。

    我们的想法是对大于阈值的差异使用累积和。大于您的阈值的差异将变为True。相反,等于或低于您的阈值的差异将变为False。对布尔值进行累积求和将使差异等于或低于您的阈值不变,因此它们得到相同的组号。

    max_distance = 1
    
    df["group_diff"] = df.sort_values("val")\
                         .groupby("group_number")["val"]\
                         .diff()\
                         .gt(max_distance)\
                         .cumsum()
    
    print(df)
    
        group_number    val group_diff
    0   1               5   0
    1   1               8   1
    2   1               12  2
    3   1               13  2
    4   1               22  5
    5   1               26  6
    6   1               31  8
    7   2               7   0
    8   2               16  3
    9   2               17  3
    10  2               19  4
    11  2               29  7
    12  2               33  9
    13  2               62  10
    

    您现在可以在 group_numbergroup_diff 上使用 groupby 并查看结果组:

    grouped = df.groupby(["group_number", "group_diff"])
    print(grouped.groups)
    
    {(1, 0): Int64Index([0], dtype='int64'),
     (1, 1): Int64Index([1], dtype='int64'),
     (1, 2): Int64Index([2, 3], dtype='int64'),
     (1, 5): Int64Index([4], dtype='int64'),
     (1, 6): Int64Index([5], dtype='int64'),
     (1, 8): Int64Index([6], dtype='int64'),
     (2, 0): Int64Index([7], dtype='int64'),
     (2, 3): Int64Index([8, 9], dtype='int64'),
     (2, 4): Int64Index([10], dtype='int64'),
     (2, 7): Int64Index([11], dtype='int64'),
     (2, 9): Int64Index([12], dtype='int64'),
     (2, 10): Int64Index([13], dtype='int64')}
    

    感谢@jezrael 提示避免使用新列以提高性能:

    group_diff = df.sort_values("val")\
                   .groupby("group_number")["val"]\
                   .diff()\
                   .gt(max_distance)\
                   .cumsum()
    
    grouped = df.groupby(["group_number", group_diff])
    

    【讨论】:

    • 谢谢!但是您假设 val 值已排序-它们不必如此。请稍微修改一下您的答案,我会很乐意接受。
    • @BinyaminEven 这就是为什么我将sort_values("val") 放在表达式中以防止未排序的值(与您的示例不同)。
    • 但您还必须按group number 进行排序。我会将其编辑为.sort_values(by=['group_number','val'])。 (在这种情况下,您不会得到,在本例中,第 7 行将在第 0 组中)。无论如何我当然会接受。
    • 您不需要按group_number 排序,因为sort_values 之后的groupby 隐含地类似于sort_values。您可以将group_number 添加到sort_values 但不会改变结果。
    • @jezrael 谢谢,终于明白你的意思了:-)。将其添加到答案中。
    【解决方案2】:

    所以您想将 val 中差值为 1 或更接近的值组合在一起?

    你可以做的一件事:

    假设您有十进制数字,您可以按四舍五入的值对它们进行分组,这意味着您可以使用df.round 将它们分组到最接近的指定小数位置,例如将它们四舍五入到最接近的整数:

    df.groupby(df["val"].round(0))
    

    既然你有整数,你可以做的就是将 val 除以 2,所以之前相差 1 的值现在相差 0.5。现在你用上面的函数将它们四舍五入到最接近的整数,你可以这样对它们进行分组!

    顺便说一句,我不认为这是一个完整的答案,它只是对该主题的一个建议,任何发现这个问题的人都可能会感兴趣

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多