如何在Pandas中使用迭代器获取序列的平均值?

1 投票
1 回答
58 浏览
提问于 2025-04-14 16:42

我现在正在使用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来实现它。

所以我想问:

  1. 有没有办法在Pandas中实现这个?

  2. 如果没有,我应该转向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

撰写回答