Как оптимизировать этот вложенный код l oop, работающий с pandas фреймами данных - PullRequest
1 голос
/ 29 апреля 2020

Я новичок в оптимизации и мне нужна помощь в улучшении времени выполнения этого кода. Это выполняет мою задачу, но это занимает вечность. Любые предложения по улучшению, чтобы он работал быстрее?

Вот код:

def probabilistic_word_weighting(df, lookup):

    # instantiate new place holder for class weights for each text sequence in the df
    class_probabilities = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
    for index, row in lookup.iterrows():
        if row.word in df.words.split():
            class_proba_ = row.class_proba.strip('][').split(', ')
            class_proba_ = [float(i) for i in class_proba_]
            class_probabilities = [a + b for a, b in zip(class_probabilities, class_proba_)]

    return class_probabilities

Два входных df выглядят так:

df

index                                     word
1                               i  havent  been  back 
2                                            but  its 
3                   they  used  to  get  more  closer 
4                                             no  way 
5       when  we  have  some  type  of  a  thing  for
6                and  she  had  gone  to  the  doctor 
7                                                suze 
8        the  only  time  the  parents  can  call  is
9               i  didnt  want  to  go  on  a  cruise 
10                            people  come  aint  got 

lookup

index    word                               class_proba
6231    been    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487]
8965    havent  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487]
3270    derive  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487]
7817    a       [0.0, 0.0, 7.451379, 6.552, 0.0, 0.0, 0.0, 0.0]
3452    hello   [0.0, 0.0, 0.0, 0.0, 0.000155327, 0.0, 0.0, 0.0]
5112    they    [0.0, 0.0, 0.00032289312, 0.0, 0.0, 0.0, 0.0, 0.0]
1012    time    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487]
7468    some    [0.000193199, 0.0, 0.0, 0.000212947, 0.0, 0.0, 0.0, 0.0]
6428    people  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487
5537    scuba   [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.27899487

По сути, он выполняет итерацию по каждой строке в поиске, которая содержит слово и его относительные веса классов. Если слово найдено в любой текстовой последовательности в df.word, то class_probabilities для lookup.word добавляется в переменную class_probabilities, назначенную каждой последовательности в df.word. Он проходит по каждой строке в df для каждой итерации строк поиска.

Как это можно сделать быстрее?

1 Ответ

3 голосов
/ 29 апреля 2020

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

1: изменять форму слов столбца df с str.split, stack и to_frame, чтобы получить новую строку для каждого слова:

s_df = df['words'].str.split(expand=True).stack().to_frame(name='split_word')
print (s_df.head(8))
    split_word
0 0          i
  1     havent
  2       been
  3       back
1 0        but
  1        its
2 0       they
  1       used

2: изменить lookup на set_index столбец слова, str.strip, str.split и astype, чтобы получить фрейм данных со словом в качестве индекса и каждым значением class_proba в столбце

split_lookup = lookup.set_index('word')['class_proba'].str.strip('][')\
                     .str.split(', ', expand=True).astype(float)
print (split_lookup.head())
          0    1         2      3         4    5    6         7
word                                                           
been    0.0  0.0  0.000000  0.000  0.000000  0.0  0.0  5.278995
havent  0.0  0.0  0.000000  0.000  0.000000  0.0  0.0  5.278995
derive  0.0  0.0  0.000000  0.000  0.000000  0.0  0.0  5.278995
a       0.0  0.0  7.451379  6.552  0.000000  0.0  0.0  0.000000
hello   0.0  0.0  0.000000  0.000  0.000155  0.0  0.0  0.000000

3: Merge оба, drop ненужный столбец и groupby level = 0 является исходным индексом df и sum

df_proba = s_df.merge(split_lookup, how='left',
                      left_on='split_word', right_index=True)\
               .drop('split_word', axis=1)\
               .groupby(level=0).sum()
print (df_proba.head())
          0    1         2         3    4    5    6         7
0  0.000000  0.0  0.000000  0.000000  0.0  0.0  0.0  10.55799
1  0.000000  0.0  0.000000  0.000000  0.0  0.0  0.0   0.00000
2  0.000000  0.0  0.000323  0.000000  0.0  0.0  0.0   0.00000
3  0.000000  0.0  0.000000  0.000000  0.0  0.0  0.0   0.00000
4  0.000193  0.0  7.451379  6.552213  0.0  0.0  0.0   0.00000

4: наконец, преобразовать в список и переназначить исходный df с помощью to_numpy и tolist:

df['class_proba'] = df_proba.to_numpy().tolist()
print (df.head())
                                           words  \
0                          i  havent  been  back   
1                                       but  its   
2              they  used  to  get  more  closer   
3                                        no  way   
4  when  we  have  some  type  of  a  thing  for   

                                         class_proba  
0   [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.55798974]  
1           [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  
2  [0.0, 0.0, 0.00032289312, 0.0, 0.0, 0.0, 0.0, ...  
3           [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  
4  [0.000193199, 0.0, 7.451379, 6.552212946999999...  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...