Мудрая итерация строки данных panda со ссылкой на предыдущие значения строк для условного соответствия - PullRequest
0 голосов
/ 27 сентября 2018

Я должен выяснить, сколько раз велосипед был на превышении скорости, и в каждом случае как долго (для простоты, сколько км)

df = pd.DataFrame({'bike':['b1']*15, 'km':list(range(1,16)), 'speed':[20,30,38,33,28,39,26,33,35,46,53,27,37,42,20]})
>>> df
   bike  km  speed
0    b1   1     20
1    b1   2     30
2    b1   3     38
3    b1   4     33
4    b1   5     28
5    b1   6     39
6    b1   7     26
7    b1   8     33
8    b1   9     35
9    b1  10     46
10   b1  11     53
11   b1  12     27
12   b1  13     37
13   b1  14     42
14   b1  15     20
#Expected result is
bike  last_OS_loc  for_how_long_on_OS
b1      4                2km
b1      11               5km
b1      15               1km

Теперь логика -

  1. должен пометить скорость> = 30 как Overspeed_Flag

  2. Если скорость остается более 30 на 1 или 1 + км, то это продолжение рассматривается как сеанс с превышением скорости(например: когда b1 находился в диапазоне от 2 до 4 км, 6–11 км, 13–14 км, MARK, это был не сеанс с превышением скорости, когда b1 был на 6 км, так как это было только для этого ряда, продолжения на> 30 не обнаружено).

  3. затем измерьте для сеанса, как долго / на сколько километров он остается на пределе превышения скорости.См. Таблицу ожидаемых результатов.

  4. также выяснение для сеанса превышения скорости, какой была последняя отметка км.

Просьба предложить, как мне этого добиться,И дайте мне знать, если что-то не понятно в этом вопросе.

P: S: я тоже пытаюсь, но это немного сложно для меня (Довольно запутался, как пометить, если это продолжение OS_flagили один экземпляр ОС.), Вернется в случае успеха в этом.Спасибо в ADV.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Вот еще один подход, использующий пару вспомогательных Series и lambda func:

os_session = (df['speed'].ge(30) & (df['speed'].shift(-1).ge(30) | df['speed'].shift().ge(30))).astype(int)
groups =  (os_session.diff(1) != 0).astype('int').cumsum()

f_how_long = lambda x: x.max() - x.min()

grouped_df = (df.groupby([os_session, groups, 'bike'])['km']
           .agg([('last_OS_loc', 'max'),
                 ('for_how_long_on_OS',f_how_long)])
           .xs(1, level=0)
           .reset_index(level=0, drop=True))

print(grouped_df)

      last_OS_loc  for_how_long_on_OS
bike                                 
b1              4                   2
b1             11                   3
b1             14                   1
0 голосов
/ 27 сентября 2018

Вы можете использовать:

#boolean mask
mask = df['speed'] >= 30
#consecutive groups
df['g'] = mask.ne(mask.shift()).cumsum()
#get size of each group
df['count'] = mask.groupby(df['g']).transform('size')
#filter by mask and remove unique rows
df = df[mask & (df['count'] > 1)]
print (df)
   bike  km  speed  g  count
1    b1   2     30  2      3
2    b1   3     38  2      3
3    b1   4     33  2      3
7    b1   8     33  6      4
8    b1   9     35  6      4
9    b1  10     46  6      4
10   b1  11     53  6      4
12   b1  13     37  8      2
13   b1  14     42  8      2

#aggregate first and last values
df1 = df.groupby(['bike','g'])['km'].agg([('last_OS_loc', 'last'), 
                                          ('for_how_long_on_OS','first')])
#substract last with first
df1['for_how_long_on_OS'] = df1['last_OS_loc'] - df1['for_how_long_on_OS']
#data cleaning
df1 = df1.reset_index(level=1, drop=True).reset_index()
print (df1)
  bike  last_OS_loc  for_how_long_on_OS
0   b1            4                   2
1   b1           11                   3
2   b1           14                   1

РЕДАКТИРОВАТЬ:

print (pd.concat([mask,
                  mask.shift(), 
                  mask.ne(mask.shift()), 
                  mask.ne(mask.shift()).cumsum()], axis=1, 
                  keys=('mask', 'shifted', 'not equal (!=)', 'cumsum')))

     mask shifted  not equal (!=)  cumsum
0   False     NaN            True       1
1    True   False            True       2
2    True    True           False       2
3    True    True           False       2
4   False    True            True       3
5    True   False            True       4
6   False    True            True       5
7    True   False            True       6
8    True    True           False       6
9    True    True           False       6
10   True    True           False       6
11  False    True            True       7
12   True   False            True       8
13   True    True           False       8
14  False    True            True       9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...