Оптимизация итерации по фрейму данных - PullRequest
0 голосов
/ 15 мая 2018

У меня есть фрейм данных, который выглядит следующим образом:

            timestamp    battery_state  battery_level
0   2017-10-08 13:42:02  Charging       0.94
1   2017-10-08 13:45:43  Charging       0.95
2   2017-10-08 13:49:08  Charging       0.96
3   2017-10-08 13:54:07  Charging       0.97
4   2017-10-08 13:57:26  Charging       0.98
5   2017-10-08 14:01:35  Charging       0.99
6   2017-10-08 14:03:03  Full           1.00
7   2017-10-08 14:17:19  Charging       0.98
8   2017-10-08 14:26:05  Charging       0.97
9   2017-10-08 14:46:10  Charging       0.98
10  2017-10-08 14:47:47  Full           1.00
11  2017-10-08 16:36:24  Charging       0.91
12  2017-10-08 16:40:32  Charging       0.92
13  2017-10-08 16:47:58  Charging       0.93
14  2017-10-08 16:51:51  Charging       0.94
15  2017-10-08 16:55:26  Charging       0.95

Как вы, ребята, видите на этом фрейме данных, у меня есть 3 подмножества выборок, которые соответствуют периоду зарядки устройства:

  • Образец от 0 до 6
  • Образец от 7 до 10
  • Образец от 11 до 15

Примечание: Период зарядки не всегдадо полного состояния, как в примере 11 до 15

Цель состоит в том, чтобы поместить эти 3 периода в переменную и обработать их, когда они будут созданы.

Для этого я сделал этокод:

previous_index = 0 #stores the initial index of each period

for index in islice(device_charge_samples.index, 1, None): #use islice because the first row does not have privious sample to compare

    #creates a period by comparing each line two by two
    if device_charge_samples.get_value(index, 'battery_level') < device_charge_samples.get_value(index - 1, 'battery_level'):
         subset = device_charge_samples[previous_index:index].reset_index(drop=True)

         #Process subset function here

         previous_index = index

    #last period case
    if index == len(device_charge_samples) - 1:
         subset = device_charge_samples[previous_index:index + 1].reset_index(drop=True)

         #Process subset function here

Я уже заменяю device_charge_samples.iteraterows () для device_charge_samples.index в цикле for, и я заменяю device_charge_samples.loc [index, 'battery_level] для device_charge_samples.get_value (index,' battery_level ') , оба очень помогли.

Есть ли какие-либо другие оптимизации, которые я могу сделать?как, например, использование функции применения dataframe (которая, кажется, работает как цикл for для каждой строки, но я не знаю, как использовать ее в этой ситуации, или, если даже стоит ее использовать), или любая другая оптимизация, которую я могу использоватьв моем решении

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Вы можете использовать np.split(), где battery_state == 'Full' и удалить эти строки.

m = df['battery_state'] == 'Full'
for subset in np.split(df[~m],df.index[m] - np.arange(sum(m))):
    #1000 loops, best of 3: 783 µs per loop
    # do something with subset here

Или, как выразился DJK с кончиной (но здесь более компактная версия для честного выбора времени)

m  = df.battery_state == 'Full'
for idx, subset in df[~m].groupby(m.cumsum()):
    # 1000 loops, best of 3: 999 µs per loop
    # do something with subset here

Полный пример:

import pandas as pd
import numpy as np

data = '''\
timestamp            battery_state  battery_level
2017-10-08T13:42:02  Charging       0.94
2017-10-08T13:45:43  Charging       0.95
2017-10-08T13:49:08  Charging       0.96
2017-10-08T13:54:07  Charging       0.97
2017-10-08T13:57:26  Charging       0.98
2017-10-08T14:01:35  Charging       0.99
2017-10-08T14:03:03  Full           1.00
2017-10-08T14:17:19  Charging       0.98
2017-10-08T14:26:05  Charging       0.97
2017-10-08T14:46:10  Charging       0.98
2017-10-08T14:47:47  Full           1.00
2017-10-08T16:36:24  Charging       0.91
2017-10-08T16:40:32  Charging       0.92
2017-10-08T16:47:58  Charging       0.93
2017-10-08T16:51:51  Charging       0.94
2017-10-08T16:55:26  Charging       0.95'''

df = pd.read_csv(pd.compat.StringIO(data), sep='\s+', parse_dates=['timestamp'])

m = df['battery_state'] == 'Full'
for subset in np.split(df[~m],df.index[m] - np.arange(sum(m))):
    print(subset)

Возвращает:

            timestamp battery_state  battery_level
0 2017-10-08 13:42:02      Charging           0.94
1 2017-10-08 13:45:43      Charging           0.95
2 2017-10-08 13:49:08      Charging           0.96
3 2017-10-08 13:54:07      Charging           0.97
4 2017-10-08 13:57:26      Charging           0.98
5 2017-10-08 14:01:35      Charging           0.99
            timestamp battery_state  battery_level
7 2017-10-08 14:17:19      Charging           0.98
8 2017-10-08 14:26:05      Charging           0.97
9 2017-10-08 14:46:10      Charging           0.98
             timestamp battery_state  battery_level
11 2017-10-08 16:36:24      Charging           0.91
12 2017-10-08 16:40:32      Charging           0.92
13 2017-10-08 16:47:58      Charging           0.93
14 2017-10-08 16:51:51      Charging           0.94
15 2017-10-08 16:55:26      Charging           0.95
0 голосов
/ 15 мая 2018

Сначала создайте столбец, который уникально сегментирует ваш фрейм данных, используя cumsum

df['group'] = (df.battery_state == 'Full').cumsum().shift(1).fillna(0)

Теперь вы можете перебирать группы вместо того, чтобы перебирать строки

for index, frame in df.groupby('group'):
    subsetFunction(frame)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...