March 21, 2021

Чек-лист для решения проблемы с объединением данных в Python

Что делать, если данные не хотят объединяться. Рассмотрим типичные действия.

Пусть есть две таблицы, представляющие заработок людей из разных городов (идентифицируются по индексу) и суммы помощи людям из местного бюджета (для каждого города фиксированная сумма) следующего вида:

Перед нами стоит задача их объединения, которое, очевидно, производится по индексу города (как я упоминал ранее осуществляется средствами библиотеки Pandas - функцией merge). В результате получается таблица, в которую попали не все записи из первоначальной:

Что не попало в объединение

В этой ситуации напрашивается необходимость исследования "проблемных" строк. Для этого следует в обеих таблицах проверить записи, которые не попали в объединение. Это осуществляется с помощью метода isin следующим образом:

df.loc[~df['индекс_города'].isin(df_m['индекс_города']),'индекс_города']
df_help.loc[~df_help['индекс_города'].isin(df_m['индекс_города']),
            'индекс_города']

Для удобства изучения может потребоваться сохранить записи в файл:

df.loc[~df['индекс_города'].isin(df_m['индекс_города']),'индекс_города'].\
                            to_excel('pr1.xlsx',index=False)
df_help.loc[~df_help['индекс_города'].isin(df_m['индекс_города']),
            'индекс_города'].to_excel('pr2.xlsx',index=False)

Исследуем значения "проблемного" столбца

После ознакомления с данными, у нас возникают предположения о природе несоответствий. Для вывода таких подозрительных значений воспользуемся векторизованными операциями со строками и проверим наличие в полях символа "-":

df.loc[df['индекс_города'].str.contains('-'),'индекс_города']

Преобразовываем значения "проблемного" столбца

Из последнего рисунка можно предположить, что некоторые индексы городов не участвуют в объединении из-за наличия служебных символов, например, "-". Для преобразования полей можно использовать мощь регулярных выражений:

df['индекс_города'] = df['индекс_города'].str.replace('-','')

Получаем нужные подстроки из данных

На данном этапе мы считаем, что все обработали, сделали вывод о том, что индекс города состоит из семи цифр и пытаемся их извлечь из всех полей методом extract:

df['интересуемая_подстрока'] = df['индекс_города'].str.extract('([0-9]{7,})') 

Как можно заметить, некоторые значения не распознаны, определим какие:

df.loc[(df['интересуемая_подстрока'].isnull()) & 
       (df['индекс_города'].notnull()),'индекс_города']

То есть необходимо удалить еще один служебный символ - "/". Это надо было сделать еще на этапе удаления "-":

df['индекс_города'] = df['индекс_города'].str.replace('[-/]','', regex=True)

Пробуем опять объединить данные:

df_m = pd.merge(df, df_help, on='индекс_города')

Теперь все получается!