[python]熊猫如何标记开始(1)和多个结束(2或3)之间的行?

· 收录于 2023-09-24 03:59:17 · source URL

问题详情

我有以下数据帧:

import numpy as np
import pandas as pd

df = pd.DataFrame([])
df['Date'] = ['2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-05',
              '2020-01-06','2020-01-07','2020-01-08','2020-01-09','2020-01-10',
              '2020-01-11','2020-01-12','2020-01-13','2020-01-14','2020-01-15',
              '2020-01-16','2020-01-17','2020-01-18','2020-01-19','2020-01-20']
df['Machine'] = ['A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A']
df['Signal'] = [0,1,2,0,1,3,0,0,0,3,0,1,0,0,3,0,1,0,0,1]
df['Status'] =  0

以及以下函数,它为机器 A 生成状态列。在信号列中,1 打开机器(状态列 1),保持 1,直到机器收到 2 或 3 的信号,将机器状态切换为 0(关闭),直到机器再次收到信号 1。

我已经使用以下函数解决了保持以前的状态行值 1 或 0 的问题:

def s_gen(dataset, Signal):
    _status = 0
    status0 = []
    for (i) in Signal:
        if _status == 0:
            if i == 1:
                _status = 1 
        elif _status == 1:
            if (i == 2 or i==3):
                _status = 0
        status0.append(_status)
        
    dataset['status0'] = status0

    return dataset['status0']

df['Status'] = s_gen(df,df['Signal'])
df.drop('status0',axis=1,inplace = True)
df

这会将新创建的列追加到数据帧。但是,我有一个更大的数据帧,在机器列中具有许多不同的值(分组为系列;A,A,A,B,B,B等),函数的结果不能重叠。使用分组不起作用。因此,我认为下一步是将状态的每个序列生成为单独的列表,并在将整个系列作为较大外部循环的一部分附加到更大的数据帧之前将它们连接起来。

这是期望的结果:

df = pd.DataFrame([])
df['Date'] = ['2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-05',
              '2020-01-06','2020-01-07','2020-01-08','2020-01-09','2020-01-10',
              '2020-01-11','2020-01-12','2020-01-13','2020-01-14','2020-01-15',
              '2020-01-16','2020-01-17','2020-01-18','2020-01-19','2020-01-20',
              '2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-05',
              '2020-01-06','2020-01-07','2020-01-08','2020-01-09','2020-01-10',
              '2020-01-11','2020-01-12','2020-01-13','2020-01-14','2020-01-15',
              '2020-01-16','2020-01-17','2020-01-18','2020-01-19','2020-01-20']

df['Machine'] = ['A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A',
                'B','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B','B',]
df['Signal'] = [0,1,2,0,1,3,0,0,0,3,0,1,0,0,3,0,1,0,0,1,0,1,2,0,1,3,0,0,0,3,0,1,0,0,3,0,1,0,0,1]
df['Status'] = [0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1]
df

我苦苦挣扎的是,如果函数单独处理每台机器的数据,然后将其附加到数据帧,它将不得不遍历每台机器,然后连接生成的所有状态系列,然后将该较大的系列附加到数据帧。

这是我到目前为止尝试过的:

这会导致错误 - KeyError:[索引(['A', 'A', 'A', 'A', 'A', 'B',\n 'b', 'b']

,\n dtype='object')] 不在 [列]中

是否最好通过 dfListU(唯一机器列表)循环函数,然后连接结果?我试图避免使用循环,但找不到任何其他方法将上一个状态行与 Signal 列中的同一行进行比较。

任何帮助都真诚地感谢。

最佳回答

一个简单的方法是<a href=https://pandas.pydata.org/docs/reference/api/pandas.Series.map.html rel=noreferrer>映射已知状态,然后groupby.ffill 它们:

输出:

          Date Machine  Signal  Status
0   2020-01-01       A       0       0
1   2020-01-02       A       1       1
2   2020-01-03       A       2       0
3   2020-01-04       A       0       0
4   2020-01-05       A       1       1
5   2020-01-06       A       3       0
6   2020-01-07       A       0       0
7   2020-01-08       A       0       0
8   2020-01-09       A       0       0
9   2020-01-10       A       3       0
10  2020-01-11       A       0       0
11  2020-01-12       A       1       1
12  2020-01-13       A       0       1
13  2020-01-14       A       0       1
14  2020-01-15       A       3       0
15  2020-01-16       A       0       0
16  2020-01-17       A       1       1
17  2020-01-18       A       0       1
18  2020-01-19       A       0       1
19  2020-01-20       A       1       1
20  2020-01-01       B       0       0
21  2020-01-02       B       1       1
22  2020-01-03       B       2       0
23  2020-01-04       B       0       0
24  2020-01-05       B       1       1
25  2020-01-06       B       3       0
26  2020-01-07       B       0       0
27  2020-01-08       B       0       0
28  2020-01-09       B       0       0
29  2020-01-10       B       3       0
30  2020-01-11       B       0       0
31  2020-01-12       B       1       1
32  2020-01-13       B       0       1
33  2020-01-14       B       0       1
34  2020-01-15       B       3       0
35  2020-01-16       B       0       0
36  2020-01-17       B       1       1
37  2020-01-18       B       0       1
38  2020-01-19       B       0       1
39  2020-01-20       B       1       1