Python: переписывание вложенных циклов с пандами для оптимизации производительности - PullRequest
0 голосов
/ 26 июня 2019

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

df_1 содержит все item_ids, и для каждого item_id указывается, в каких кварталах этот элемент находился в производстве:

df_1 = 
    item_id        qtr
0         X1 2016-06-01
1         X1 2016-09-01
2         X1 2017-01-01
3         X1 2017-03-01
4         X1 2017-06-01
5         X1 2017-09-01
6         X1 2018-01-01
7         X1 2018-03-01
8         X1 2018-06-01
9         X1 2018-09-01
10        X1 2019-01-01
11        X1 2019-03-01
12        X1 2019-06-01
13        X2 2016-06-01
14        X2 2016-09-01
15        X2 2017-01-01
16        X2 2017-03-01
17        X2 2017-06-01
18        X2 2017-09-01
19        X3 2018-03-01
20        X3 2018-06-01
21        X3 2018-09-01
22        X3 2019-01-01
23        X3 2019-03-01
24        X3 2019-06-01

df_2 список ошибок по item_id, сдаты начала и окончания ошибки и код ошибки:

df_2=
 item_id  error_num start_date   end_date code
0      X1          1 2016-11-05 2017-04-16    A
1      X1          2 2018-12-18 2019-03-09    B
2      X2          1 2017-02-04 2017-05-17    C
3      X3          1 2018-08-11 2019-02-20    B

для каждого item_id в df_1, мне нужно проверить, находится ли дата qtr между start_date и end_date для любой из ошибок этого элемента,затем верните флаг, чтобы указать, была ли ошибка, error_num и код.Вывод должен выглядеть следующим образом:

   item_id        qtr  error error_num code
0       X1 2016-06-01      0       N/A  N/A
1       X1 2016-09-01      0       N/A  N/A
2       X1 2017-01-01      1         1    A
3       X1 2017-03-01      1         1    A
4       X1 2017-06-01      0       N/A  N/A
5       X1 2017-09-01      0       N/A  N/A
6       X1 2018-01-01      0       N/A  N/A
7       X1 2018-03-01      0       N/A  N/A
8       X1 2018-06-01      0       N/A  N/A
9       X1 2018-09-01      0       N/A  N/A
10      X1 2019-01-01      1         2    B
11      X1 2019-03-01      1         2    B
12      X1 2019-06-01      0       N/A  N/A
13      X2 2016-06-01      0       N/A  N/A
14      X2 2016-09-01      0       N/A  N/A
15      X2 2017-01-01      0       N/A  N/A
16      X2 2017-03-01      1         1    C
17      X2 2017-06-01      0       N/A  N/A
18      X2 2017-09-01      0       N/A  N/A
19      X3 2018-03-01      0       N/A  N/A
20      X3 2018-06-01      0       N/A  N/A
21      X3 2018-09-01      1         1    B
22      X3 2019-01-01      1         1    B
23      X3 2019-03-01      0       N/A  N/A
24      X3 2019-06-01      0       N/A  N/A

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

 item_ids = df_1.item_id.unique()
err_flags = pd.DataFrame(columns = ['item_id', 'qtr', 'error', 'error_num', 'code'])
for item_id in item_ids:
    item_id_dates = df_1.loc[df_1['item_id']==item_id]
    item_id_errs = df_2.loc[df_2['item_id']==item_id]

    for row in item_id_errs.itertuples(index = True, name = 'Pandas'):
        start_date = getattr(row, 'start_date')
        end_date = getattr(row, 'end_date')
        err_num = getattr(row, 'error_num')
        err_code = getattr(row, 'code')

        item_id_dates.loc[(item_id_dates.qtr >= start_date) & (item_id_dates.qtr <= end_date), 'error'] = 1
        item_id_dates.loc[(item_id_dates.qtr >= start_date) & (item_id_dates.qtr <= end_date), 'error_num'] = err_num
        item_id_dates.loc[(item_id_dates.qtr >= start_date) & (item_id_dates.qtr <= end_date), 'code'] = err_code

    err_flags = err_flags.append(item_id_dates, ignore_index = True)

err_flags = err_flags[['item_id', 'qtr', 'error', 'error_num', 'code']]
values = {'error': 0, 'error_num': 'N/A', 'code': 'N/A'}
err_flags = err_flags.fillna(values)

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

...