我有一个数据帧,我需要在其中对距离不超过 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_number
和val
进行分组,其中val
的值小于或等于 1。
因此,在此示例中,行 2
和 3
将组合在一起,行 8
和 9
将组合在一起。
我尝试使用 diff 或相关函数,但我没有弄清楚。
任何帮助将不胜感激!
使用diff
是正确的方法 - 只需将其与gt
和cumsum
相结合,您就可以拥有自己的组。
这个想法是使用累积总和来表示大于阈值的差异。大于阈值的差异将变为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_number和group_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
差值为 1 或更近的值组合在一起?
你可以做的一件事:
假设你有十进制数,你可以按它们的舍入值对它们进行分组,这意味着你使用df.round
将它们分组到最接近的指定小数位,例如将它们四舍五入到最接近的整数:
df.groupby(df["val"].round(0))
由于你有整数,你可以做的是将 val 除以 2,所以以前相差 1 的值现在相差 0.5。现在,您可以使用上述函数将它们四舍五入到最接近的整数,然后您可以以这种方式对它们进行分组!
顺便说一句,我不认为这是一个完整的答案,它只是关于该主题的建议,对于任何发现这个问题的人来说都可能很有趣