Рекурсивный парсинг строчного поля
Рассмотрим, как эффективно распарсить строчное поле средствами библиотеки Pandas. Я для этого использую рекурсивный подход.
Его суть в следующей последовательности шагов:
- создаем копию анализируемой таблицы (пусть исходная - df, а копия - df_left, после станет понятно ее предназначение)
- проводим обзор шаблонов в df_left
- выбираем шаблон, который хотим заменить на некое значение, проводим действие с копией таблицы df_left (называю df_copy) и удостоверяемся в корректности операции
- применяем действие к исходной таблице df (или откладываем для применения всех операций вместе после алгоритма)
- удаляем шаблон из df_left и повторяем действия от второго шага
Рассмотрим на примере. Предположим, мы хотим распарсить поле days из массива, описывающего дни работы офисов вашей организации:
Обзор шаблонов удобно провести с помощью метода Series под названием value_counts:
df_left = df.copy() df_left['days'].value_counts()
Пусть первый шаблон, с которым мы захотели разобраться, - это поля вида "-". Требуется заменить его на значение None для последующей обработки вместе с пропущенными значениями. Заводим копию таблицы df_left, проводим действие с ней, а затем проверяем корректность с помощью функции get_diffs_data_cols (подробнее рассказывал ранее):
df_copy = df_left.copy() df_copy['days'] = df_copy['days'].replace({'-': None}) a = general.df_check_info.get_diffs_data_cols(df_left.drop_duplicates(subset='ids'), df_copy.drop_duplicates(subset='ids'), ['ids', 'days'], 'days')
Убедившись в корректности операции, применяем ее к исходной таблице df и удаляем шаблон из df_left:
df['days'] = df['days'].replace({'-': None}) df_left = df_left[df_left['days']!='-']
Далее опять проводим обзор шаблонов, выбираем конкретный, реализуем операцию на копии и выводим разницу для проверки корректности, например, так:
pats = df_left['days'].value_counts() df_copy = df_left.copy() df_copy['days'] = df_copy['days'].replace(r',+', r'.', regex=True) df_copy['days'] = df_copy['days'].replace(r'\.{2,}', r'.', regex=True) a = general.df_check_info.get_diffs_data_cols(df_left.drop_duplicates(subset='ids'), df_copy.drop_duplicates(subset='ids'), ['ids', 'days'], 'days')
Вновь применяем операцию к df и убираем шаблон из df_left:
df['days'] = df['days'].replace(r',+', r'.', regex=True) df['days'] = df['days'].replace(r'\.{2,}', r'.', regex=True) df_left['days'] = df_left['days'].replace(r',+', r'.', regex=True) df_left['days'] = df_left['days'].replace(r'\.{2,}', r'.', regex=True) df_left = df_left[~df_left['days'].str.contains(r'[А-Яа-я]{2}\.', na=False)]
Теперь множество оставшихся шаблонов примет вид:
pats = df_left['days'].value_counts()
Продолжаем рекурсивно применять операции до достижения желаемого результата.