Как взять среднее из 3 значений, прежде чем флаг поменяется с 0 на 1 Python - PullRequest
1 голос
/ 26 марта 2020

У меня есть датафрейм со столбцами A, B и flag. Я хочу вычислить среднее значение из 2 значений до смены флага с 0 на 1 и записать значение при изменении флага с 0 на 1 и записать значение при изменении флага с 1 на 0.

# Input dataframe
df=pd.DataFrame({'A':[1,3,4,7,8,11,1,15,20,15,16,87],
                 'B':[1,3,4,6,8,11,1,19,20,15,16,87],
                 'flag':[0,0,0,0,1,1,1,0,0,0,0,0]})

# Expected output
df_out=df=pd.DataFrame({'A_mean_before_flag_change':[5.5],
                        'B_mean_before_flag_change':[5],
                        'A_value_before_change_flag':[7], 
                        'B_value_before_change_flag':[6]})

Ответы [ 2 ]

2 голосов
/ 27 марта 2020

Я пытаюсь создать более общее решение:

df=pd.DataFrame({'A':[1,3,4,7,8,11,1,15,20,15,16,87],
                 'B':[1,3,4,6,8,11,1,19,20,15,16,87],
                 'flag':[0,0,0,0,1,1,1,0,0,1,0,1]})
print (df)
     A   B  flag
0    1   1     0
1    3   3     0
2    4   4     0
3    7   6     0
4    8   8     1
5   11  11     1
6    1   1     1
7   15  19     0
8   20  20     0
9   15  15     1
10  16  16     0
11  87  87     1

Сначала создайте группы по маске для 0 со следующими 1 значениями flag:

m1 = df['flag'].eq(0) & df['flag'].shift(-1).eq(1)
df['g'] = m1.iloc[::-1].cumsum()
print (df)
     A   B  flag  g
0    1   1     0  3
1    3   3     0  3
2    4   4     0  3
3    7   6     0  3
4    8   8     1  2
5   11  11     1  2
6    1   1     1  2
7   15  19     0  2
8   20  20     0  2
9   15  15     1  1
10  16  16     0  1
11  87  87     1  0

, затем отфильтровать группы с меньшим размером, например N:

N = 4    
df1 = df[df['g'].map(df['g'].value_counts()).ge(N)].copy()
print (df1)
    A   B  flag  g
0   1   1     0  3
1   3   3     0  3
2   4   4     0  3
3   7   6     0  3
4   8   8     1  2
5  11  11     1  2
6   1   1     1  2
7  15  19     0  2
8  20  20     0  2

Отфильтровать последние N строки:

df2 = df1.groupby('g').tail(N)

И объединить last с mean:

d = {'mean':'_mean_before_flag_change', 'last': '_value_before_change_flag'}
df3 = df2.groupby('g')['A','B'].agg(['mean','last']).sort_index(axis=1, level=1).rename(columns=d)
df3.columns = df3.columns.map(''.join)
print (df3)
   A_value_before_change_flag  B_value_before_change_flag  \
g                                                           
2                          20                          20   
3                           7                           6   

   A_mean_before_flag_change  B_mean_before_flag_change  
g                                                        
2                      11.75                      12.75  
3                       3.75                       3.50  
1 голос
/ 26 марта 2020

Я предполагаю, что это должно работать для случаев с более чем одним нарастающим фронтом и что последовательные значения и средние значения добавляются в списки вывода:

# the first step is to extract the rising and falling edges using diff(), identify sections and length
df['flag_diff'] = df.flag.diff().fillna(0)
df['flag_sections'] = (df.flag_diff != 0).cumsum()
df['flag_sum'] = df.flag.groupby(df.flag_sections).transform('sum')

# then you can get the relevant indices by checking for the rising edges
rising_edges = df.index[df.flag_diff==1.0]
val_indices = [i-1 for i in rising_edges]
avg_indices = [(i-2,i-1) for i in rising_edges]

# and finally iterate over the relevant sections
df_out = pd.DataFrame()
df_out['A_mean_before_flag_change'] = [df.A.loc[tpl[0]:tpl[1]].mean() for tpl in avg_indices]
df_out['B_mean_before_flag_change'] = [df.B.loc[tpl[0]:tpl[1]].mean() for tpl in avg_indices]
df_out['A_value_before_change_flag'] = [df.A.loc[idx] for idx in val_indices]
df_out['B_value_before_change_flag'] = [df.B.loc[idx] for idx in val_indices]
df_out['length'] = [df.flag_sum.loc[idx] for idx in rising_edges]
df_out.index = rising_edges
...