Python:使用熊猫重写嵌套的for循环以优化性能

时间:2019-06-25 23:51:02

标签: python-2.7 performance

我正在尝试比较日期以在两个熊猫数据框中设置标记,并按item_ids进行分组。我的两个数据帧如下:

df_1包含所有item_id,并为每个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

对于df_1中的每个item_id,我需要检查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还是很陌生,但是我知道足够多,这可能是效率最低的方法。我曾尝试研究列表理解或矢量化方法,但很难找到包含类似分组类型的示例。

0 个答案:

没有答案