панды - слияние с пропущенными значениями

Кажется, есть причуда с функцией слияния панд. Он считает значения NaN равными и объединяет NaN с другими NaN:

>>> foo = DataFrame([
    ['a',1,2],
    ['b',4,5],
    ['c',7,8],
    [np.NaN,10,11]
], columns=['id','x','y'])

>>> bar = DataFrame([
    ['a',3],
    ['c',9],
    [np.NaN,12]
], columns=['id','z'])

>>> pd.merge(foo, bar, how='left', on='id')
Out[428]: 
    id   x   y   z
0    a   1   2   3
1    b   4   5 NaN
2    c   7   8   9
3  NaN  10  11  12

[4 rows x 4 columns]

Это не похоже ни на одну RDB, которую я видел, обычно отсутствующие значения обрабатываются с агностицизмом и не будут объединены вместе, как если бы они были равны. Это особенно проблематично для наборов данных с разреженными данными (каждый NaN будет объединен с каждым другим NaN, что приведет к огромному DataFrame!)

Есть ли способ игнорировать отсутствующие значения во время слияния, не вырезая их сначала?


person aensm    schedule 29.05.2014    source источник


Ответы (3)


Вы можете исключить значения из bar (и даже foo, если хотите), где id имеет значение null во время слияния. Однако не уверен, что это то, что вам нужно, поскольку они нарезаны.

(Из вашего левого соединения я предположил, что вы заинтересованы в сохранении всего foo, но хотите объединить только те части bar, которые совпадают и не являются нулевыми.)

foo.merge(bar[pd.notnull(bar.id)], how='left', on='id')

Out[11]: 
id   x   y   z
0    a   1   2   3
1    b   4   5 NaN
2    c   7   8   9
3  NaN  10  11 NaN
person meloncholy    schedule 29.05.2014
comment
По сути, это то, чем я сейчас занимаюсь в качестве обходного пути. Мне было интересно, есть ли возможность предотвратить поведение сопоставления NaN, которое, похоже, делают панды. - person aensm; 29.05.2014
comment
Ах, извините. Я не знаю ни одного, но, кажется, всегда есть что-то новое, что можно узнать, когда дело доходит до панд. :) - person meloncholy; 29.05.2014
comment
Большое спасибо, 'bar[pd.notnull(bar.id)]' сработало. :) - person Vineesh TP; 07.09.2019
comment
Это именно то, что я хотел. Благодаря тонну. - person prem; 17.06.2021

если не нужен NaN как в левом, так и в правом DF, используйте

pd.merge(foo.dropna(), bar.dropna(), how='left', on='id')

иначе, если нужно NaN в левом DF, используйте

pd.merge(foo, bar.dropna(), how='left', on='id')
person Liang    schedule 30.04.2017
comment
Это плохой ответ, так как он не обобщает. dropna() удалит все строки, в которых любой из столбцов содержит значение NaN, что сильно отличается от ожидаемого поведения. Вам нужно подмножить это в столбцы слияния! - person Thomas; 03.08.2021

Если вы хотите сохранить NaN из обеих таблиц, не вырезая их, вы можете использовать метод внешнего соединения следующим образом:

pd.merge(foo, bar.dropna(), how='outer', on='id')

В основном он возвращает объединение foo и bar

person yosemite_k    schedule 11.09.2017
comment
Это плохой ответ, так как он не обобщает. dropna() удалит все строки, в которых любой из столбцов содержит значение NaN, что сильно отличается от ожидаемого поведения. Вам нужно подмножить это в столбцы слияния, - person Thomas; 03.08.2021