Python 分组并减去大熊猫的第一次出现和最后一次出现

Python 分组并减去大熊猫的第一次出现和最后一次出现,python,pandas,Python,Pandas,我在熊猫中有以下数据帧 code date time dip flag tank qty 123 2018-12-23 08:00:00 389 0 1 1300 123 2018-12-23 09:00:00 380 0 1 1250 123 2018-12-23 10:00:00 378 0 1

我在熊猫中有以下数据帧

 code    date         time         dip     flag   tank   qty
 123     2018-12-23   08:00:00     389     0      1      1300
 123     2018-12-23   09:00:00     380     0      1      1250
 123     2018-12-23   10:00:00     378     0      1      1200
 123     2018-12-23   11:00:00     345     1      1      1150
 123     2018-12-23   12:00:00     342     1      1      1100
 123     2018-12-23   13:00:00     340     1      1      1050
 123     2018-12-23   14:00:00     338     1      1      1000
 123     2018-12-23   15:00:00     380     0      1      1500
 123     2018-12-23   16:00:00     340     1      1      1000
 123     2018-12-23   17:00:00     340     1      1      1000
 123     2018-12-23   08:00:00     389     0      2      1300
 123     2018-12-23   09:00:00     380     0      2      1250
 123     2018-12-23   10:00:00     378     0      2      1200
 123     2018-12-23   11:00:00     345     1      2      1150
 123     2018-12-23   12:00:00     342     1      2      1100
 123     2018-12-23   13:00:00     340     1      2      1050
 123     2018-12-23   14:00:00     338     1      2      1000
我想知道多少次
dip
低于350,直到什么时候(以小时为单位)保持在350以下,以及低于350时的销售量是多少 下面是我想要的数据帧。当倾角小于350时,我已经将标志设置为1

 code    date        tank     frequency    qty_sold    time
 123     2018-12-23  1        4            150         3
 123     2018-12-23  2        4            150         3
我可以通过groupby找到频率。需要帮忙找另外两个吗

  df_agg= df.groupby(['code','date','tank']).agg({'flag':['sum']}).reset_index()
你可以做:

# to get till what time (hour)
df.loc[df['dip'].lt(350),'time'].dt.hour.max()

# what is the quantity sold
df.loc[df['dip'].lt(350),'qty'].sum()
使用:


只有一个问题,如果有多个问题中编辑的小于350的标志实例,该怎么办。这个答案仍然正确吗?现在,在这个问题中,350以下的实例是11:00-14:00和16:00-17:00,在一个解决方案中,我们使用第一个和最后一个条目。@Neil-是的,它是这样工作的-首先通过
df[df['dip']<350]
过滤,所以获得350以下的所有行。然后,如果有多组日期时间(如编辑答案中所示),则第一组和最后一组的日期时间使用第一组的第一个日期时间(11:00),最后一组的最后一个日期时间使用最后一个日期时间(17:00)。所以差异是不正确的,因为17:00-11:00也计算不在组中的日期时间(14:00到16:00)。所以答案必须改变,请给我一些时间,如果我的时间频率是半小时呢?我可以将您的代码编辑为
pd.Timedelta(0.5,'H')
#create datetimes column
df['datetime'] = pd.to_datetime(df['date'] + ' ' + df['time'])

#add aggregation by first and last 
df_agg= df[df['dip'] < 350].groupby(['code','date','tank']).agg({'flag':['sum'], 
                                                                'datetime':['first','last'],
                                                                'qty':['first','last']})
#flatten MultiIndex
df_agg.columns = df_agg.columns.map('_'.join)

#substract columns, timedeltas convert to hours
df_agg['qty_sold'] = df_agg.pop('qty_first') - df_agg.pop('qty_last') 
df_agg['time'] = (df_agg.pop('datetime_last') - df_agg.pop('datetime_first'))
                       .dt.total_seconds().div(3600).astype(int)
#rename column and create default index
df_agg = df_agg.rename(columns={'flag_size':'frequency'}).reset_index()

print (df_agg)
   code        date  tank  flag_sum  qty_sold  time
0   123  2018-12-23     1         4       150     3
1   123  2018-12-23     2         4       150     3
df['datetime'] = pd.to_datetime(df['date'] + ' ' + df['time'])

df_agg= df[df['dip'] < 350].copy()

df_agg['g'] = (df_agg.groupby(['code','date','tank'])['datetime'].diff()
                     .ne(pd.Timedelta(1, 'H'))
                     .cumsum())

df_agg= df_agg.groupby(['code','date','tank','g']).agg({'flag':['sum'], 
                                                        'datetime':['first','last'],
                                                        'qty':['first','last']})
df_agg.columns = df_agg.columns.map('_'.join)
df_agg['qty_sold'] = df_agg.pop('qty_first') - df_agg.pop('qty_last') 
df_agg['time'] = ((df_agg.pop('datetime_last') - df_agg.pop('datetime_first'))
                         .dt.total_seconds().div(3600).astype(int))

df_agg = (df_agg.rename(columns={'flag_size':'frequency'})
                .sum(level=[0,1,2])
                .reset_index()
          )

print (df_agg)
   code        date  tank  flag_sum  qty_sold  time
0   123  2018-12-23     1         6       150     4
1   123  2018-12-23     2         4       150     3