Возникли проблемы с оптимизацией этого кода, интересно, почему он работает так медленно - как я могу оптимизировать этот код? - PullRequest
2 голосов
/ 18 марта 2019

Строка моих данных содержит 18 столбцов, каждый из которых имеет код сложности.

Класс сложности состоит из «имени», которое является именем сложности, такого как «HeartFailure», и у него также есть массив строк, хранящихся как «коды», которые имеют значения, такие как «500», и оно должно быть сопоставляются по 18 столбцам для каждого пациента (каждая строка финала) и находятся такие коды, как «5001» или «5002». Если код найден, то соответствующий столбец сложности в наборе данных необходимо обновить до 1.

Это было решение, которое я кодировал. Как вы думаете, это может быть более оптимизировано? Прямо сейчас требуется около 16 минут, чтобы запустить только 25000 пациентов, что просто недостаточно хорошо.

Данные:

DX1      DX2     DX3   DX4 HeartFailure
10R46   R*1005   8017  2   0
10R46   R*10335  5019  2   0
100R91  R*1005   8017  1   0
10R91   R*243    8870  1   0
10M95   R*4918   8305  3   0
10M95   R*9017   8305  3   0
10M95   R*9470   8221  3   0

Класс:

class HCUPCodes:
    def __init__(self,name,codes):
        self.name = name
        self.codes = codes

Инициализация класса:

complications_POA = []
complications_POA.append(HCUPCodes('HeartFailure',['80', 'R*1']))

Код:

 def defineComplicationsFeatures(patient, comp_list):
    for i in range(len(comp_list)):
        for x in comp_list[i].codes:
            if((any(patient.str.startswith(x,na=False)))):
                patient[comp_list[i].name]=1 #change 0 to 1 in the corresponding disease column for this patient
    return patient

final = final.apply(defineComplicationsFeatures, axis=1, comp_list = complications_POA)
final = final.apply(defineComplicationsFeatures, axis=1, comp_list = complications_NOPOA)

Выход:

DX1      DX2     DX3   DX4 HeartFailure
10R46   R*1005   8017  2   1
10R46   R*10335  5019  2   1
100R91  R*1005   8017  1   1
10R91   R*243    8870  1   0
10M95   R*4918   8305  3   0
10M95   R*9017   8305  3   0
10M95   R*9470   8221  3   0

Ответы [ 2 ]

3 голосов
/ 18 марта 2019

Две вещи замедляют ваш код:

  1. Использование двух для циклов
  2. Использование .apply с вашей собственной определенной функцией.

Вы можете оптимизировать свое решение с помощью векторизованных методов pandas и numpys:

  1. np.where
  2. np.stack_columns
  3. pandas.DataFrame.iloc

Решение: (в этом случае я не использовал ваш класс)

# Print the DataFrame we start with provided by OP
print(df)
      DX1      DX2   DX3 DX4  HeartFailure
0   10R46   R*1005  8017   2             0
1   10R46  R*10335  5019   2             0
2  100R91   R*1005  8017   1             0
3   10R91    R*243  8870   1             0
4   10M95   R*4918  8305   3             0
5   10M95   R*9017  8305   3             0
6   10M95   R*9470  8221   3             0
# Create new optimized function
def defineComplicationsFeatures(df):

    col_to_update = 'HeartFailure'

    strings_to_search = ['80', 'R*1']

    for string in strings_to_search:
        mask = np.column_stack([df[col].str.startswith(string, na=False) for col in df.iloc[:, :-1]]).any(axis=1)
        df[col_to_update] = np.where(mask, 1, 0)

    return df

df_new = defineComplicationsFeatures(df)
print(df_new)

      DX1      DX2   DX3 DX4  HeartFailure
0   10R46   R*1005  8017   2             1
1   10R46  R*10335  5019   2             1
2  100R91   R*1005  8017   1             1
3   10R91    R*243  8870   1             0
4   10M95   R*4918  8305   3             0
5   10M95   R*9017  8305   3             0
6   10M95   R*9470  8221   3             0

Примечание Вы можете передать col_to_update & strings_to_search в аргументы функции, что делает его немного чище, я решил не делать этого для простоты прямо сейчас.

3 голосов
/ 18 марта 2019

Для достижения минимального ускорения вы можете добавить break после того, как код найден:

 def defineComplicationsFeatures(patient, comp_list):
    for i in range(len(comp_list)):
        for x in comp_list[i].codes:
            if((any(patient.str.startswith(x,na=False)))):
                patient[comp_list[i].name]=1 #change 0 to 1 in the 
                break
    return patient
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...