我目前正在使用Pandas 管理一个CSV文件,该文件包含 map 上船只位置的数据.我有一个Pandas 数据框,看起来像这样(简化后):

Index Group 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以上,但该层序只有两个元素,因此这不是一艘停放的船只.

所以我想要得到这个:

Index Group C_p is_parked
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

我try 将此方法更改为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 S的 comments 让我对我的例子和方法进行了重新判断.

如果C_p[5]=78,它仍然是一艘停放的船只,并且它是按每组计算的.

我没有考虑到这一点,所以我的第一次try 是错误的. 这是我的新try

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),这是不好的.

推荐答案

你可以在groupby.transform中使用双rolling.第一种是计算滚动平均值,然后我们判断该值是否高于阈值.然后我们反转级数并计算滚动max以将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

Python相关问答推荐

使用numpy提取数据块

由于NEP 50,向uint 8添加-256的代码是否会在numpy 2中失败?

Pandas 有条件轮班操作

Python中绕y轴曲线的旋转

对所有子图应用相同的轴格式

优化器的运行顺序影响PyTorch中的预测

关于Python异步编程的问题和使用await/await def关键字

在vscode上使用Python虚拟环境时((env))

什么是最好的方法来切割一个相框到一个面具的第一个实例?

如何合并两个列表,并获得每个索引值最高的列表名称?

在Python中计算连续天数

导入错误:无法导入名称';操作';

Polars Group by描述扩展

Polars map_使用多处理对UDF进行批处理

如何在Python Pandas中填充外部连接后的列中填充DDL值

如何重新组织我的Pandas DataFrame,使列名成为列值?

如何获得满足掩码条件的第一行的索引?

修改.pdb文件中的值并另存为新的

如何在基于时间的数据帧中添加计算值

有什么方法可以在不对多索引DataFrame的列进行排序的情况下避免词法排序警告吗?