VLOOKUP Pandas для двух кадров данных со значениями NaN

#python #pandas #dataframe #merge #left-join

Вопрос:

У меня есть следующий фрейм данных df1

     name           mobile_no      
0   Hector ABC       123       
1   Hector ABC       287        
2   Jose JKD         567      
3   Luis AH          NaN      
4   Billy DH         NaN 
5   Harry AC         569

 
 

И еще один фрейм данных df2

     download_date  mobile_no      
0   2021-05-30       123        
1   2020-09-28       287      
2   2021-02-11       789        
3   2021-10-06       321        
4   2020-01-15       569      
 

Я хочу вернуть дату загрузки из df2, если номер мобильного телефона df1 совпадает. Выполнение pd.merge каким-то образом удваивает количество строк для df1. Есть ли способ проверить эту строку за строкой и вернуть дату загрузки?
Я не могу удалить дубликаты (если таковые имеются) в df1, а в df1 намного больше столбцов. Я вроде как хочу, чтобы это было похоже на VLOOKUP excel, который вернет результат выбранного столбца для этой строки, просто сопоставив значение поиска. Я попробовал что-то вроде:

 df1['download_date'] = np.where(df1.mobile_no == df2.mobile_no, df2.download_date, np.nan)
 

Желаемый результат:

     name         mobile_no    download_date
0   Hector ABC      123        2021-05-30
1   John DYC        237        2020-09-28
2   Jose JKD        567           NaN
3   Luis AH         NaN           NaN
4   Billy DH        NaN           NaN
5   Harry AC        569        2020-01-15
 

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

1. «Выполнение pd.merge каким-то образом удваивает количество строк для df1». Делает ли это для этого образца набора данных? Можете ли вы включить код слияния, который вы используете, и показать, чем он отличается от того, что вы ожидаете? Потому что слияние слева кажется здесь правильным ответом.

2. @HenryEcker я использовал df1.merge(df2, how='left', on=['mobile number']) , и он не увеличил количество строк, когда я запустил его в ячейках блокнота Jupyter. Однако, когда я запускаю скрипт на python с тем же кодом, он более чем удваивает количество строк (та же среда, та же версия pandas).

Ответ №1:

То, что вы ищете, это Series.map :

 df["download_date"] = df["mobile_no"].map(df2.set_index("mobile_no")["download_date"])
print (df)

         name  mobile_no download_date
0 Hector  ABC      123.0    2021-05-30
1 Hector  ABC      287.0    2020-09-28
2 Jose    JKD      567.0           NaN
3 Luis     AH        NaN           NaN
4 Billy    DH        NaN           NaN
5 Harry    AC      569.0    2020-01-15
 

Ответ №2:

merge с pd.concat

 m = df1.mobile_no.isna()
merged_df = pd.concat([df1.loc[m], df1.loc[~m].merge(df2, on='mobile_no', how ='left')]).sort_index()
 

выход

          name  mobile_no download_date
0  Hector ABC        123    2021-05-30
1  Hector ABC        287    2020-09-28
2    Jose JKD        567           NaN
3     Luis AH       <NA>           NaN
3    Harry AC        569    2020-01-15
4    Billy DH       <NA>           NaN
 

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

1. Есть ли способ сохранить порядок df1?

2. .sort_index после concat ? Я все еще думаю, что это то же самое, что слияние слева, нет?

3. @HenryEcker да. использовать sort_index()