Python 在差异条件下在数据帧中写入值(日期时间)

Python 在差异条件下在数据帧中写入值(日期时间),python,pandas,datetime,Python,Pandas,Datetime,我想在“开始时间”列中写入分组时间测量第一次非零出现的日期时间值,并将分组时间测量最后一次出现的时间写入“结束时间”列。如果分组测量值为0,“开始时间”和“结束时间”应等于0 我用diffna()选项尝试了各种diff(),但没有成功。这是我的密码: import pandas as pd import numpy as np import datetime current_time=datetime.datetime.now() L=[] for i in range(22): L

我想在“开始时间”列中写入分组时间测量第一次非零出现的日期时间值,并将分组时间测量最后一次出现的时间写入“结束时间”列。如果分组测量值为0,“开始时间”和“结束时间”应等于0

我用diffna()选项尝试了各种diff(),但没有成功。这是我的密码:

import pandas as pd 
import numpy as np
import datetime

current_time=datetime.datetime.now()
L=[]
for i in range(22):
    L.append(current_time+datetime.timedelta(milliseconds=(i*500)))

# Define input dataframe
df = {'value':      [1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0],
        'time':     L}
df = pd.DataFrame(df,columns= ['value','time'])
# print("Dataframe is:\n",df)

print("Grouping data according to servo positions, please wait...")
df['grouped_measurement'] = df['value'].diff().fillna(df['value']).eq(1).cumsum().mask(df['value'] == 0, 0)

df['Start_time'] = df['grouped_measurement'].diff().fillna(df['time'])
df['End_time'] = df['grouped_measurement'].diff().fillna(df['time'])

print("Dataframe is:\n",df)
我的实际结果是:

     value                       time  grouped_measurement    Start_time      End_time
0       1 2019-08-31 19:14:42.259304                     1  1.567279e+18  1.567279e+18
1       1 2019-08-31 19:14:42.759304                     1  0.000000e+00  0.000000e+00
2       1 2019-08-31 19:14:43.259304                     1  0.000000e+00  0.000000e+00
3       0 2019-08-31 19:14:43.759304                     0 -1.000000e+00 -1.000000e+00
4       0 2019-08-31 19:14:44.259304                     0  0.000000e+00  0.000000e+00
5       0 2019-08-31 19:14:44.759304                     0  0.000000e+00  0.000000e+00
6       1 2019-08-31 19:14:45.259304                     2  2.000000e+00  2.000000e+00
7       1 2019-08-31 19:14:45.759304                     2  0.000000e+00  0.000000e+00
8       1 2019-08-31 19:14:46.259304                     2  0.000000e+00  0.000000e+00
9       1 2019-08-31 19:14:46.759304                     2  0.000000e+00  0.000000e+00
10      1 2019-08-31 19:14:47.259304                     2  0.000000e+00  0.000000e+00
11      0 2019-08-31 19:14:47.759304                     0 -2.000000e+00 -2.000000e+00
12      0 2019-08-31 19:14:48.259304                     0  0.000000e+00  0.000000e+00
13      0 2019-08-31 19:14:48.759304                     0  0.000000e+00  0.000000e+00
14      0 2019-08-31 19:14:49.259304                     0  0.000000e+00  0.000000e+00
15      1 2019-08-31 19:14:49.759304                     3  3.000000e+00  3.000000e+00
16      1 2019-08-31 19:14:50.259304                     3  0.000000e+00  0.000000e+00
17      1 2019-08-31 19:14:50.759304                     3  0.000000e+00  0.000000e+00
18      1 2019-08-31 19:14:51.259304                     3  0.000000e+00  0.000000e+00
19      1 2019-08-31 19:14:51.759304                     3  0.000000e+00  0.000000e+00
20      1 2019-08-31 19:14:52.259304                     3  0.000000e+00  0.000000e+00
21      0 2019-08-31 19:14:52.759304                     0 -3.000000e+00 -3.000000e+00
而预期产出如下:

     value                       time  grouped_measurement    Start_time               End_time
0       1 2019-08-31 19:14:42.259304                     1  2019-08-31 19:14:42.259304  2019-08-31 19:14:43.259304 
1       1 2019-08-31 19:14:42.759304                     1  2019-08-31 19:14:42.259304  2019-08-31 19:14:43.259304 
2       1 2019-08-31 19:14:43.259304                     1  2019-08-31 19:14:42.259304  2019-08-31 19:14:43.259304 
3       0 2019-08-31 19:14:43.759304                     0  0                           0
4       0 2019-08-31 19:14:44.259304                     0  0                           0
5       0 2019-08-31 19:14:44.759304                     0  0                           0
6       1 2019-08-31 19:14:45.259304                     2  2019-08-31 19:14:45.259304  2019-08-31 19:14:47.259304
7       1 2019-08-31 19:14:45.759304                     2  2019-08-31 19:14:45.259304  2019-08-31 19:14:47.259304
8       1 2019-08-31 19:14:46.259304                     2  2019-08-31 19:14:45.259304  2019-08-31 19:14:47.259304
9       1 2019-08-31 19:14:46.759304                     2  2019-08-31 19:14:45.259304  2019-08-31 19:14:47.259304
10      1 2019-08-31 19:14:47.259304                     2  2019-08-31 19:14:45.259304  2019-08-31 19:14:47.259304
11      0 2019-08-31 19:14:47.759304                     0  0                           0
12      0 2019-08-31 19:14:48.259304                     0  0                           0
13      0 2019-08-31 19:14:48.759304                     0  0                           0
14      0 2019-08-31 19:14:49.259304                     0  0                           0
15      1 2019-08-31 19:14:49.759304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
16      1 2019-08-31 19:14:50.259304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
17      1 2019-08-31 19:14:50.759304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
18      1 2019-08-31 19:14:51.259304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
19      1 2019-08-31 19:14:51.759304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
20      1 2019-08-31 19:14:52.259304                     3  2019-08-31 19:14:49.759304  2019-08-31 19:14:52.259304
21      0 2019-08-31 19:14:52.759304                     0  0                           0

你很接近!在您创建的“分组测量”列上使用groupby

df['grouped_measurement'] = df['value'].diff().fillna(1).eq(1).cumsum().where(df['value'].ne(0))

result = (df.join(df.groupby('grouped_measurement')['time']
                    .agg([('Start_time','min'),('End_time','max')])
                 , on='grouped_measurement')
            .fillna(0,downcast='infer'))
您可能需要
pandas 0.25
才能使用
.agg([('Start\u time','min'),('End\u time','max')]

编辑

假设时间列已排序,则以下方法将不依赖于groupby

label_start_end = df['value'].diff().fillna(1, downcast='infer')

df['Start_time'] = df['time'].where(label_start_end.eq(1)).ffill().where(df['value'].eq(1),0)

df['End_time'] = df['time'].where(label_start_end.eq(-1)).bfill().where(df['value'].eq(1),0)
编辑2(datetime列无0)


非常接近!请在您创建的“分组测量”列中使用groupby

df['grouped_measurement'] = df['value'].diff().fillna(1).eq(1).cumsum().where(df['value'].ne(0))

result = (df.join(df.groupby('grouped_measurement')['time']
                    .agg([('Start_time','min'),('End_time','max')])
                 , on='grouped_measurement')
            .fillna(0,downcast='infer'))
您可能需要
pandas 0.25
才能使用
.agg([('Start\u time','min'),('End\u time','max')]

编辑

假设时间列已排序,则以下方法将不依赖于groupby

label_start_end = df['value'].diff().fillna(1, downcast='infer')

df['Start_time'] = df['time'].where(label_start_end.eq(1)).ffill().where(df['value'].eq(1),0)

df['End_time'] = df['time'].where(label_start_end.eq(-1)).bfill().where(df['value'].eq(1),0)
编辑2(datetime列无0)


你知道如何提高效率吗?我的熊猫数据帧非常大,包含2-5000万行。执行
df['groupped_measurement']=df['value'].diff().fillna(1.eq(1.cumsum().where(df['value'].ne(0))
持续时间不到1秒。当我执行
结果=
行时,它持续时间超过30秒,这很长…@Tomasz,它已经过优化。如果使用groupby转换或应用,它将需要更长的时间。我想你有很多组?试着运行
df.groupby('groupped_measurement')['time'].agg([(‘开始时间’、‘最小’、‘结束时间’、‘最大’))
在我的例子中,要查看需要多长时间,在执行任何操作之前,“时间”列显然是经过排序的。使用不依赖groupby的方法,操作时间从30秒减少到了7秒,这很好,但“开始时间”和“结束时间”始终为0。另一方面
df.groupby(“groupped\u测量”)[“时间”].agg([('Start_time','min'),('End_time','max'))
没有做我想做的事情,因为它会分组。@你确定吗?我可以复制结果(使用非0的Start_time和End_time)你知道如何提高效率吗?我的pandas数据框非常大,包含2-50百万行。
df['groupped_measurement'的执行]=df['value'].diff().fillna(1).eq(1).cumsum().where(df['value'].ne(0))
持续时间不到1秒。当我执行
结果=
行时,它持续时间超过30秒,这很长…@Tomasz,它已经过优化。如果使用groupby转换或应用,它将需要更长的时间。我想你有很多组?试着运行
df.groupby('groupped_measurement')['time'].agg([(‘开始时间’、‘最小’、‘结束时间’、‘最大’))
在我的例子中,要查看需要多长时间,在执行任何操作之前,“时间”列显然是经过排序的。使用不依赖groupby的方法,操作时间从30秒减少到了7秒,这很好,但“开始时间”和“结束时间”始终为0。另一方面
df.groupby(“groupped\u测量”)[“时间”].agg([('Start\u time','min'),('End\u time','max'))
不执行我想要的操作,因为它会分组。@您确定吗?我可以复制结果(使用非0的Start\u time和End\u time)