Pandas / Numpy - Векторизация расчета даты и времени - PullRequest
0 голосов
/ 01 марта 2020

tl; др

  1. Мне нужно df.dates[iter]-df.dates[initial_fixed] на срез кадра данных, индексированного item_id самым быстрым из возможных способов (ради обучение и повышение квалификации ... и сроки).

  2. Как рассчитать рабочие часы между этими же датами, а не просто прямым временем. И мне нужны неполные дни (например, 4,763 дня), а не просто целое число, например .days

Привет,

Во-первых, у меня есть фрейм данных df

item_id      dates               new_column   ...   other_irrelevant_columns

101          2020-09-10-08-...   FUNCTION           -neglected-
101          2020-09-18-17-...   FUNCTION           -neglected-
101          2020-10-03-11-...   FUNCTION           -neglected-

107          2017-08-dd-hh-...   FUNCTION           -neglected-
107          2017-09-dd-hh-...   FUNCTION           -neglected-

209          2019-01-dd-hh-...   FUNCTION           -neglected
209          2019-01-dd-hh-...   FUNCTION           -neglected-
209          2019-01-dd-hh-...   FUNCTION           -neglected-
209          2019-01-dd-hh-...   FUNCTION           -neglected-

где столбец дат (тип = объект datetime) является хронологическим для item_id, поэтому первый экземпляр является самой ранней датой.

У меня более 400 000 строк, и мне нужно вычислить истекшее время, принимая расстояние между каждым datetime и источником datetime, для item_id. Затем есть последовательность

item_id      dates               [new_column        = elapsed_time]   ...   other_irrelevant_columns

101          2020-09-10-08-...   [dates[0]-dates[0] = 0       days]         -neglected- for plotting
101          2020-09-18-17-...   [dates[1]-dates[0] = 8.323   days]         -neglected-
101          2020-10-03-11-...   [dates[2]-dates[0] = 23.56   days]         -neglected-

. На данный момент я застрял, используя for l oop, который, я думаю, векторизован, который вычисляет общее количество секунд timedelta и преобразуется в дней как поплавок:

for id in df.item_id:
    df.elapsed_days[df.item_id == id] = ((df.dates[df.item_id == id] - min(df.dates[df.boot_id == id])).dt.total_seconds()/86400).astype(float)

, который длится вечно. Не в духе данных науки. То, что я хотел бы знать, это лучший способ выполнить это, если он использует apply () с лямбда-выражением, и я попытался использовать digitize и isin () из этой статьи парней , но не могу понять как создать элемент item_id, чтобы он работал.

Во-вторых, меня также интересует аналогичная продолжительность, но только в рабочие часы (с 8:00 до 18:00 без выходных или праздничных дней в Канаде), поэтому в режиме реального времени item активно измеряется.

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 01 марта 2020

Вы можете использовать join , чтобы сделать это намного быстрее.

Сначала вам нужно выполнить мин, как в текущем коде:

tmp = df.loc[df['item_id'] == df['boot_id']] # row filtering
tmp = df[['item_id','date']] # column filtering
dateMin = tmp.groupby('item_id', as_index=False).min() # Find the minimal date for each item_id

Затем Вы можете сделать слияние:

# Actual merge
indexed_df = df.set_index('item_id')
indexed_dateMin = dateMin.set_index('item_id')
merged = indexed_df.join(indexed_dateMin, lsuffix='_df', rsuffix='_dateMin')

# Vectorized computation
df['elapsed_days'] = (merged['date_df'] - merged['date_dateMin']).dt.total_seconds()/86400).astype(float)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...