Ускорьте два вложенных для циклов и несколько операторов if - PullRequest
1 голос
/ 23 сентября 2019

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

ID  | Time     | Min_time | Max_time | Status | Date        |
1   | 15:32:20 | 15:32:20 | 15:33:04 | High   | 01/01/2019  |
1   | 15:32:30 | 15:32:20 | 15:33:04 | High   | 01/01/2019  |
1   | 15:33:04 | 15:32:20 | 15:33:04 | High   | 01/01/2019  |
2   | 15:32:10 | 15:32:10 | 15:40:05 | High   | 01/01/2019  |
2   | 15:40:05 | 15:32:10 | 15:40:05 | High   | 01/01/2019  |
3   | 17:20:04 | 17:20:04 | 17:29:20 | Low    | 02/01/2019  |
3   | 17:25:10 | 17:20:04 | 17:29:20 | Low    | 02/01/2019  |
3   | 17:29:20 | 17:20:04 | 17:29:20 | Low    | 02/01/2019  |
4   | 15:32:30 | 15:32:30 | 15:40:08 | High   | 01/01/2019  |
4   | 15:32:38 | 15:32:30 | 15:40:08 | High   | 01/01/2019  |
4   | 15:40:08 | 15:32:30 | 15:40:08 | High   | 01/01/2019  |
5   | 15:35:10 | 15:35:10 | 15:36:08 | Low    | 01/01/2019  |
5   | 15:36:08 | 15:35:10 | 15:36:08 | Low    | 01/01/2019  |
..  |          |          |          |        |

Я хотел бы найти идентификаторы, где

  1. статус заказане равно (поэтому, когда значение High, тогда должны быть найдены идентификаторы с 'Low') AND
  2. Дата в тот же день AND
  3. Минимальное время находится между минимальным и максимальным временемпорядка с другой стороны.

Так же для пункта 3: Например, «15:32:30» идентификатора 4 находится между min_time и max_time идентификатора 2.

Мой код выглядит следующим образом:

dict_results = {"ID_outer_loop":[], "ID_inner_loop":[]}
for key, value in df.iterrows():
    for key2, value2 in df.iterrows():
        if value["Min_time"] > value2["Min_time"]:
            if value["Min_time"] < value2["Max_time"]:
                if value["Date"] == value2["Date"]:
                    if value["Status"] != value2["Status"]:
                        dict_results["ID_outer_loop"].append(value["ID"])
                        dict_results["ID_inner_loop"].append(value2["ID"])

Как бы я ускорил этот процесс на 200 тыс. Строк?

Ответы [ 2 ]

0 голосов
/ 24 сентября 2019

Вы можете использовать itertools.product для создания парного сравнения строк, а затем filter в соответствии с указанными критериями:

import itertools as it
import pandas as pd

df = pd.read_csv('test.csv')
valid_pairs = filter(
    lambda x: x[0][1] != x[1][1] and x[0][2] == x[1][2] and x[1][3] <= x[0][3] <= x[1][4],
    it.product(zip(df['ID'], df['Status'], df['Date'], df['Min_time'], df['Max_time']), repeat=2)
)
valid_ids = ((x[0][0], x[1][0]) for x in valid_pairs)
ID_outer_loop, ID_inner_loop = zip(*valid_ids)

Создание только пар уникальных идентификаторов может быть достигнуто с помощьюиспользуя valid_ids = set(valid_ids).Если имеется много дубликатов valid_pairs, это может сэкономить значительный объем памяти, поскольку все предыдущие шаги лениво вычисляются и оцениваются только при добавлении в набор (исключая дубликаты).

Другой способ, с помощью которого ярлыки на первомсовпадение для каждой пары идентификаторов - сначала groupby('ID'), затем объедините группы в группы и, наконец, убедитесь, что после первого совпадения не выполняется вычисление с помощью any:

valid_pairs = filter(
    lambda g: any(x[0][0] != x[1][0] and x[0][1] == x[1][1] and x[1][2] <= x[0][2] <= x[1][3]
                  for x in zip(zip(g[0][1]['Status'], g[0][1]['Date'], g[0][1]['Min_time']),
                               zip(g[1][1]['Status'], g[1][1]['Date'], g[1][1]['Min_time'], g[1][1]['Max_time']))),
    it.product(df.groupby('ID'), repeat=2)
)
0 голосов
/ 24 сентября 2019

Вы можете использовать внешние продукты Numpy и радиовещание для парных сравнений:

import numpy as np
import pandas as pd

df = pd.read_csv('test.csv')
mask = np.logical_and(
    np.not_equal.outer(df['Status'], df['Status']),
    np.logical_and(
        np.equal.outer(df['Date'], df['Date']),
        np.logical_and(
            df['Min_time'].values[:, None] <= df['Min_time'].values[None, :],
            df['Min_time'].values[None, :] <= df['Max_time'].values[:, None])))
indices = mask.nonzero()
ID_outer_loop = df['ID'].iloc[indices[0]]
ID_inner_loop = df['ID'].iloc[indices[1]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...