Слияние двух df приводит к NaN в добавленных столбцах

#python #pandas #merge

#python #pandas #слияние

Вопрос:

Я уже давно борюсь со следующей проблемой и был бы признателен за любую помощь.

Я хочу объединить df1 и df2 в «стране».

 df1.head()
 
  --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- 
|   |  loan_theme_id  | partner_id |               field_partner_name                |         loan_theme_type          |      location_name      |    lat    |    lon     | rural_pct |    city    |     region      |     country     |
 --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- 
| 0 | a1050000000wDrQ |        175 | Koret Israel Economic Development Funds (KIEDF) | Underserved                      | Abu Sanaan, Israel      | 32.958030 | 35.171969  | 0.0       | Abu Sanaan | Israel          | Israel          |
| 1 | a1050000007S5Kt |        485 | Building Markets                                | SME                              | Yangon, Myanmar (Burma) | 16.866069 | 96.195132  | NaN       | Yangon     | Myanmar (Burma) | Myanmar (Burma) |
| 2 | a1050000002YCWe |        369 | AsociaciÍ_n Chajulense de Mujeres (ACMUV)       | Artisan                          | Chajul, Guatemala       | 15.483483 | -91.037070 | NaN       | Chajul     | Guatemala       | Guatemala       |
| 3 | a1050000007qJuI |         77 | Al Majmoua                                      | Vulnerable Populations (Syrian)2 | Aley, Lebanon           | 33.810086 | 35.597326  | 43.0      | Aley       | Lebanon         | Lebanon         |
| 4 | a1050000006FnC9 |        357 | Alivio Capital                                  | Imagen Dental                    | Matamoros,Tamps, Mexico | 25.869029 | -97.502738 | 3.0       | Matamoros  | Tamps           | Mexico          |
 --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- 
 

Вот типы столбцов для df1

 Int64Index: 100 entries, 108 to 549
Data columns (total 11 columns):
 #   Column              Non-Null Count  Dtype   
---  ------              --------------  -----   
 0   loan_theme_id       100 non-null    category
 1   partner_id          100 non-null    category
 2   field_partner_name  100 non-null    string  
 3   loan_theme_type     100 non-null    category
 4   location_name       100 non-null    string  
 5   lat                 100 non-null    float64 
 6   lon                 100 non-null    float64 
 7   rural_pct           79 non-null     float64 
 8   city                100 non-null    string  
 9   region              100 non-null    string  
 10  country             100 non-null    string  
dtypes: category(3), float64(3), string(5)
memory usage: 19.2 KB
 
 df2.head()
 
  --- ------------- ------------------------- ---------- 
|   |   country   |      world_region       |   MPI    |
 --- ------------- ------------------------- ---------- 
| 0 | Afghanistan | South Asia              | 0.309853 |
| 1 | Albania     | Europe and Central Asia | NaN      |
| 2 | Algeria     | Arab States             | NaN      |
| 3 | Armenia     | Europe and Central Asia | NaN      |
| 4 | Azerbaijan  | Europe and Central Asia | NaN      |
 --- ------------- ------------------------- ---------- 
 

Типы столбцов:

 <class 'pandas.core.frame.DataFrame'>
Int64Index: 102 entries, 0 to 101
Data columns (total 3 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   country       102 non-null    string 
 1   world_region  102 non-null    object 
 2   MPI           78 non-null     float64
dtypes: float64(1), object(1), string(1)
memory usage: 3.2  KB
 

Обеспечение хотя бы некоторого перекрытия:

 display(df2[(df2.country == 'Guatemala')])
 
  ---- ----------- ----------------------------- ---------- 
|    |  country  |        world_region         |   MPI    |
 ---- ----------- ----------------------------- ---------- 
| 34 | Guatemala | Latin America and Caribbean | 0.113957 |
 ---- ----------- ----------------------------- ---------- 
 

Слияние:

 df3 = pd.merge(df1, df2, on='country', how='left')
df3.head()
 
  --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- -------------- ----- 
|   |  loan_theme_id  | partner_id |               field_partner_name                |         loan_theme_type          |      location_name      |    lat    |    lon     | rural_pct |    city    |     region      |     country     | world_region | MPI |
 --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- -------------- ----- 
| 0 | a1050000000wDrQ |        175 | Koret Israel Economic Development Funds (KIEDF) | Underserved                      | Abu Sanaan, Israel      | 32.958030 | 35.171969  | 0.0       | Abu Sanaan | Israel          | Israel          | NaN          | NaN |
| 1 | a1050000007S5Kt |        485 | Building Markets                                | SME                              | Yangon, Myanmar (Burma) | 16.866069 | 96.195132  | NaN       | Yangon     | Myanmar (Burma) | Myanmar (Burma) | NaN          | NaN |
| 2 | a1050000002YCWe |        369 | AsociaciÍ_n Chajulense de Mujeres (ACMUV)       | Artisan                          | Chajul, Guatemala       | 15.483483 | -91.037070 | NaN       | Chajul     | Guatemala       | Guatemala       | NaN          | NaN |
| 3 | a1050000007qJuI |         77 | Al Majmoua                                      | Vulnerable Populations (Syrian)2 | Aley, Lebanon           | 33.810086 | 35.597326  | 43.0      | Aley       | Lebanon         | Lebanon         | NaN          | NaN |
| 4 | a1050000006FnC9 |        357 | Alivio Capital                                  | Imagen Dental                    | Matamoros,Tamps, Mexico | 25.869029 | -97.502738 | 3.0       | Matamoros  | Tamps           | Mexico          | NaN          | NaN |
 --- ----------------- ------------ ------------------------------------------------- ---------------------------------- ------------------------- ----------- ------------ ----------- ------------ ----------------- ----------------- -------------- ----- 

 

Типы столбцов

 <class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 13 columns):
 #   Column              Non-Null Count  Dtype   
---  ------              --------------  -----   
 0   loan_theme_id       100 non-null    category
 1   partner_id          100 non-null    category
 2   field_partner_name  100 non-null    string  
 3   loan_theme_type     100 non-null    category
 4   location_name       100 non-null    string  
 5   lat                 100 non-null    float64 
 6   lon                 100 non-null    float64 
 7   rural_pct           79 non-null     float64 
 8   city                100 non-null    string  
 9   region              100 non-null    string  
 10  country             100 non-null    string  
 11  world_region        0 non-null      object  
 12  MPI                 0 non-null      float64 
 

Я действительно не понимаю, почему результат NaN в world_region и MPI. Я убедился, что в df1 и df2 в country нет NAN и что есть хотя бы какое-то перекрытие. Также совпадают типы столбцов.

Редактировать: благодаря Полу я попытался получить информацию, например, о «Гватемале» в df1. В приведенной выше таблице мы видим, что он действительно присутствует в df1. Однако при запуске display(df2[(df2.country == 'Guatemala')]) возвращается пустой фрейм данных. Итак, я попытался запустить display(df2[(df2.country == ‘Гватемала’)]) с дополнительным пробелом в начале, и теперь мы получаем некоторые результаты:

  --- ----------------- ------------ ------------------------------------------- ----------------- ------------------- ----------- ----------- ----------- -------- ----------- ----------- 
|   |  loan_theme_id  | partner_id |            field_partner_name             | loan_theme_type |   location_name   |    lat    |    lon    | rural_pct |  city  |  region   |  country  |
 --- ----------------- ------------ ------------------------------------------- ----------------- ------------------- ----------- ----------- ----------- -------- ----------- ----------- 
| 2 | a1050000002YCWe |        369 | AsociaciÍ_n Chajulense de Mujeres (ACMUV) | Artisan         | Chajul, Guatemala | 15.483483 | -91.03707 | NaN       | Chajul | Guatemala | Guatemala |
 --- ----------------- ------------ ------------------------------------------- ----------------- ------------------- ----------- ----------- ----------- -------- ----------- ----------- 
 

Что приводит к вопросу, есть ли в pandas функция для проверки наличия пробелов в столбце df?

Ответ №1:

Вы выполняете левое соединение, указанное left ключевым словом в команде слияния. Это означает, что если в правом фрейме данных нет страны, которую имеет строка в левом, вы получите NaNs.
Для получения дополнительной информации о типах соединений и, в частности, о левых соединениях, см., Например, Здесь: https://www.w3schools.com/sql/sql_join_left.asp

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

Комментарии:

1. Привет, Пол, спасибо за твой ответ. Но у df2 есть «Гватемала», так как у df1 также есть «Гватемала» в строке 3. Разве объединение не должно работать, по крайней мере, в этом случае? Еще раз спасибо за ваше время и быстрый ответ!

2. Ты прав. В таком случае это должно сработать. Вы уверены, что в df1 нет лишнего места Guatemala или какой-либо другой опечатки? display(df1[(df1.country == 'Guatemala')]) Возвращает строку?

3. Привет, Пол, спасибо! Вы выдвинули правильную идею. Знаете ли вы функцию, с помощью которой я мог бы лучше проверить это в будущем?

4. может быть, вы можете удалить начальные и конечные пробелы с помощью trim функции, а может быть, и пользователя .lower() , чтобы иметь все в нижнем регистре и больше не беспокоиться о капитализации. Однако это не помогает по сравнению с другими опечатками

5. Эй, Пол, спасибо, я попробую. Если вы хотите, опубликуйте еще одно предложение о пустом дополнительном пространстве, чтобы я мог пометить его как правильный ответ.