Как оптимизировать такие коды следующим образом в python? - PullRequest
5 голосов
/ 05 марта 2020

У меня есть собственный метри c для реализации следующим образом:

def metric(pred:pd.DataFrame(), valid:pd.DataFrame()):
    date_begin = valid.dt.min()
    date_end = valid.dt.max()
    x = valid[valid.label == 1].dt.min()

    # p
    p_n_tpp_df = valid[(valid.dt >= x) &\
                       (valid.dt <= x + timedelta(days=30)) &\
                       (p_n_tpp_df.label == 1)]
    p_n_pp_df =  valid[(valid.dt >= date_begin + timedelta(days=30)) &\ 
                       (valid.dt <= date_end + timedelta(days=30)) &\
                       (p_n_tpp_df.label == 1)]


    p_n_tpp = len([x for x in pred.serial_number.values\ 
                     if x in p_n_tpp_df.serial_number.unique()])
    p_n_pp = len([x for x in pred.serial_number.values\ 
                    if x in p_n_pp_df.serial_number.unique()])

    p = p_n_tpp / p_n_pp
    print('p: ', p)

    # r
    p_n_tpr_df = valid[(valid.dt >= date_begin - timedelta(days=30)) &\ 
                      (valid.dt <= date_end - timedelta(days=30)) &\
                      (p_n_tpr_df.label == 1)]
    p_n_pr_df = valid[(valid.dt >= date_begin) &\ 
                      (valid.dt <= date_end) &\ 
                      (p_n_pr_df.label == 1)]


    p_n_tpr = len([x for x in pred.serial_number.values\
                     if x in p_n_tpr_df.serial_number.unique()])
    p_n_pr = len([x for x in pred.serial_number.values\
                    if x in p_n_pr_df.serial_number.unique()])

    r = p_n_tpr / p_n_pr
    print('p: ', r)

    m = 2 * p * r / (p + r)

    return m

pd.DataFrame() из pred и valid имеют одинаковые столбцы, а dt не имеет пересечений ,
И все значения serial_number в valid являются подмножеством всех значений serial_number в pred.
В столбце label есть только 2 значения: 0 или 1.
Вот пример pred и valid выглядит следующим образом:


print(pred.head(3))
    serial_number  dt          label  
0   123            2011-03-21  1
1   52             2011-03-22  0
2   12             2011-03-01  1
..., ...


print(pred.info())
Int64Index: 10000000 entries,
Data columns (total 3 columns):
serial_number  int32
dt             datetimes64[ns]
label          int8
..., ...

print(valid.head(3))
    serial_number  dt          label  
0   324            2011-04-22  1
1   52             2011-04-22  0
2   14             2011-04-01  1
..., ...


print(valid.info())
Int64Index: 10000000 entries,
Data columns (total 3 columns):
serial_number  int32
dt             datetimes64[ns]
label          int8

А размер ввода pd.DataFrame составляет около 10 000 000 сэмплов и 3 функции.
Когда я пытаюсь использовать его для вычисления этого показателя c, он действительно медленный, и затраты времени на Intel 9600KF превышают 2 часа.
Поэтому мне интересно, как оптимизировать такой код по времени.
Спасибо заранее.

1 Ответ

6 голосов
/ 12 марта 2020

Вот самый большой выигрыш в производительности кода, который у вас есть:

Numpy set logi c

len([x for x in pred.serial_number.values\
                     if x in p_n_tpr_df.serial_number.unique()])

Любая строка, которая выглядит так, получает размер установленное пересечение pred.serial_number и p_n_tpr_df.serial_number. Использование numpy вместо понимания списка и вызова unique сэкономит значительное время вычислений:

intersect_size = np.intersect1d(pred.serial_number.values,
                                p_n_tpr_df.serial_number.values).shape[0]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...