如何在Pandas中使用迭代器获取序列的平均值?
我现在正在使用pandas来管理一个CSV文件,这个文件里包含了船只在地图上的位置数据。我有一个看起来像这样的Pandas数据框(这是简化版):
索引 | 组别 | C_p |
---|---|---|
1 | 1 | 27 |
2 | 1 | 85 |
3 | 1 | 83 |
4 | 1 | 78 |
5 | 1 | 66 |
6 | 1 | 47 |
7 | 3 | 82 |
8 | 3 | 80 |
9 | 3 | 66 |
C_p是一个置信系数,用来判断船只是否停靠。
判断船只是否停靠的方法是这样的:
如果一段数据的C_p平均值超过80
,并且这段数据的最小数量超过3
,那么这段数据就表示船只停靠。
在这个例子中,索引2到4的数据是停靠的船只,因为它们的C_p平均值是82.67,超过了80。虽然索引7到8的数据的C_p平均值也超过了80,但这段数据只有两个元素,所以不算停靠的船只。
所以我想得到这样的结果:
索引 | 组别 | C_p | 是否停靠 |
---|---|---|---|
1 | 1 | 27 | 0 |
2 | 1 | 85 | 1 |
3 | 1 | 83 | 1 |
4 | 1 | 78 | 1 |
5 | 1 | 66 | 0 |
6 | 1 | 47 | 0 |
7 | 3 | 82 | 0 |
8 | 3 | 80 | 0 |
9 | 3 | 66 | 0 |
我尝试把这个方法变成一个Leetcode的问题,像这样:
for i in range(n - 2): # n is the element number of a group
avg = (C_p[i] + C_p[i+1] + C_p[i+2]) / 3
if avg >= 80:
is_parked[i] = is_parked[i+1] = is_parked[i+2] = 1 # default value of is_parked is 0
但我不知道怎么用Pandas或Python来实现它。
所以我想问:
有没有办法在Pandas中实现这个?
如果没有,我应该转向Numpy或者其他工具来得到结果吗?
编辑:1
Nick的评论让我重新检查了我的例子和方法。
如果C_p[5] = 78,它仍然算是停靠的船只,并且是按组来计算的。
我之前没有考虑到这一点,所以我的第一次尝试是错误的。这里是我的新尝试:
for i in range(n):
thisSUM = C_p[i]
for j in range(i+1, n):
thisSUM += C_p[j]
avg = thisSUM / (j - i + 1)
if avg >= 80 and j - i + 1 >= 3:
for k in range(i, j+1):
is_parked_check[k] = 1
时间复杂度是O(n^3),这不是很好。
1 个回答
1
你可以在一个数据框中使用双重的 rolling
方法,结合 groupby.transform
。第一个 rolling
是用来计算滚动平均值的,然后我们检查这个值是否超过了某个阈值。接着,我们把数据反转过来,再计算一个滚动的 最大值,这样就能把 True/1 的结果传播到前面的 N-1 行。
N = 3
threshold = 80
df['is_parked'] = (df.groupby('Group')['C_p']
.transform(
lambda s: s.rolling(N).mean().gt(threshold)[::-1]
.rolling(N, min_periods=1).max()
.astype(int)
)
)
输出结果:
Index Group C_p is_parked
0 1 1 27 0
1 2 1 85 1
2 3 1 83 1
3 4 1 78 1
4 5 1 66 0
5 6 1 47 0
6 7 3 82 0
7 8 3 80 0
8 9 3 66 0
中间结果:
Index Group C_p formula avg >80 rev_roll
0 1 1 27 NaN NaN False 0
1 2 1 85 NaN NaN False 1
2 3 1 83 (83+85+27)/3 65.000000 False 1
3 4 1 78 (78+83+85)/3 82.000000 True 1
4 5 1 66 (66+78+83)/3 75.666667 False 0
5 6 1 47 (47+66+78)/3 63.666667 False 0
6 7 3 82 NaN NaN False 0
7 8 3 80 NaN NaN False 0
8 9 3 66 (66+80+82)/3 76.000000 False 0