Замена большого набора данных Несколько условий L oop более быстрой альтернативой в Pandas Dataframe - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь выполнить вложенное l oop на Dataframe, но у меня возникают серьезные проблемы со скоростью. По сути, у меня есть список уникальных значений, через которые я хочу выполнить l oop, и все они должны быть повторены в четырех разных столбцах. Код показан ниже:

def get_avg_val(temp_df, col):
    temp_df = temp_df.replace(0, np.NaN)
    avg_val = temp_df[col].mean()

    return (0 if math.isnan(avg_val) else avg_val)

Final_df = pd.DataFrame(rows_list, columns=col_names)

""" Inserts extra column to identify Securities by Group type - then identifies list of unique values"""
Final_df["Group_SecCode"] = Final_df['Group'].map(str)+ "_" + Final_df['ISIN'].map(str)
unique_list = Final_df.Group_SecCode.unique().tolist()

""" The below allows for replacing missing values with averages """
col_list = ['Option Adjusted Spread','Effective Duration','Spread Duration','Effective Convexity']

for unique_val in unique_list:
    temp_df = Final_df[Final_df['Group_SecCode'] == unique_val]    

    for col in col_list:
        amended_val = get_avg_val (temp_df, col)

        """ The below identifies columns where Unique code is and there is an NaN - via mask; afterwards np.where replaces the value in the cell with the amended value"""
        mask = (Final_df['Group_SecCode'] == unique_val) & (Final_df[col].isnull())
        Final_df[col] = np.where(mask, amended_val, Final_df[col])

В разделе «Маска» указывается, когда в фрейме данных выполняются два условия, а np.where заменяет значения в ячейках, обозначенных значением Amendend (которое само является функцией выполнение среднего значения).

Теперь это обычно работает, но с более чем 400 000 строк и дюжиной столбцов скорость действительно низкая. Есть ли какой-нибудь рекомендуемый способ улучшить два «For ..»? Как я полагаю, это причина, по которой код занимает некоторое время.

Спасибо всем!

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

ОБНОВЛЕНИЕ - Найден альтернативный способ выполнения изменений с помощью словаря, теперь задача занимает 1,5 минуты, а не 35 минут.

Код ниже. Другой подход здесь позволяет фильтровать DataFrame на меньшие, для которых выполняется ряд операций. На этот раз новые данные сохраняются в словаре, а al oop добавляет в него больше данных. Наконец, словарь переносится обратно в исходный DataFrame, полностью заменяя его обновленным набором данных.

""" Creates Dataframe compatible with Factset Upload and using rows previously stored in rows_list"""
col_names = ['Group','Date','ISIN','Name','Currency','Price','Proxy Duration','Option Adjusted Spread','Effective Duration','Spread Duration','Effective Convexity']
Final_df = pd.DataFrame(rows_list, columns=col_names)

""" Inserts extra column to identify Securities by Group type - then identifies list of unique values"""
Final_df["Group_SecCode"] = Final_df['Group'].map(str)+ "_" + Final_df['ISIN'].map(str)
unique_list = Final_df.Group_SecCode.unique().tolist()

""" The below allows for replacing missing values with averages """
col_list = ['Option Adjusted Spread','Effective Duration','Spread Duration','Effective Convexity']

""" Sets up Dictionary where to store Unique Values Dataframes"""
final_dict = {}

for unique_val in unique_list:
    condition = Final_df['Group_SecCode'].isin([unique_val])
    temp_df = Final_df[condition].replace(0, np.NaN)

    for col in col_list:
        """ Perform Amendments at Filtered Dataframe - by column """
        """ 1. Replace NaN values with Median for the Datapoints encountered """
        #amended_val = get_avg_val (temp_df, col) #Function previously used to compute average
        #mask = (Final_df['Group_SecCode'] == unique_val) & (Final_df[col].isnull())
        #Final_df[col] = np.where(mask, amended_val, Final_df[col])
        amended_val = 0 if math.isnan(temp_df[col].median()) else temp_df[col].median()
        mask = temp_df[col].isnull()
        temp_df[col] = np.where(mask, amended_val, temp_df[col])

        """ 2. Perform Validation Checks via Function defined on line 36 """
        temp_df = val_checks (temp_df,col)

    """ Updates Dictionary with updated data at Unique Value level """
    final_dict.update(temp_df.to_dict('index')) #Updates Dictionary with Unique value Dataframe

""" Replaces entirety of Final Dataframe including amended data """
Final_df = pd.DataFrame.from_dict(final_dict, orient='index', columns=col_names)
0 голосов
/ 02 апреля 2020

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

for col in col_list:
    Final_df[col] = Final_df.groupby('Group_SecCode')[col].transform(lambda x: 
                                                            x.fillna(x.mean()))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...