Подтвердить что ты не робот

Pandas Слева Outer Join результаты в таблице больше, чем левая таблица

Из того, что я понимаю о левом внешнем соединении, в результирующей таблице никогда не должно быть больше строк, чем в левой таблице... Пожалуйста, дайте мне знать, если это неправильно...

Моя левая таблица - 192572 строки и 8 столбцов.

Моя правая таблица - 42160 строк и 5 столбцов.

В моей левой таблице есть поле с именем 'id', которое соответствует столбцу в моей правой таблице с именем 'key'.

Поэтому я объединять их как таковые:

combined = pd.merge(a,b,how='left',left_on='id',right_on='key')

Но тогда объединенная форма 236569.

Что я не понимаю?

4b9b3361

Ответ 1

Вы можете ожидать, что это увеличится, если ключи соответствуют более одной строке в другом DataFrame:

In [11]: df = pd.DataFrame([[1, 3], [2, 4]], columns=['A', 'B'])

In [12]: df2 = pd.DataFrame([[1, 5], [1, 6]], columns=['A', 'C'])

In [13]: df.merge(df2, how='left')  # merges on columns A
Out[13]: 
   A  B   C
0  1  3   5
1  1  3   6
2  2  4 NaN

Чтобы избежать этого поведения удалить дубликаты в df2:

In [21]: df2.drop_duplicates(subset=['A'])  # you can use take_last=True
Out[21]: 
   A  C
0  1  5

In [22]: df.merge(df2.drop_duplicates(subset=['A']), how='left')
Out[22]: 
   A  B   C
0  1  3   5
1  2  4 NaN

Ответ 2

Есть также стратегии, которые вы можете использовать, чтобы избежать такого поведения, которое не предполагает потерю дублированных данных, если, например, не все столбцы дублируются. Если у вас есть

In [1]: df = pd.DataFrame([[1, 3], [2, 4]], columns=['A', 'B'])

In [2]: df2 = pd.DataFrame([[1, 5], [1, 6]], columns=['A', 'C'])

Один из способов - взять среднее значение дубликата (можно также взять сумму и т.д.)

In [3]: df3 = df2.groupby('A').mean().reset_index()

In [4]: df3
Out[4]: 
     C
A     
1  5.5

In [5]: merged = pd.merge(df,df3,on=['A'], how='outer')

In [6]: merged
Out[204]: 
   A  B    C
0  1  3  5.5
1  2  4  NaN

В качестве альтернативы, если у вас есть нечисловые данные, которые нельзя преобразовать с помощью pd.to_numeric() или если вы просто не хотите принимать среднее значение, вы можете изменить переменную слияния, перечислив дубликаты. Однако эта стратегия применима, когда дубликаты существуют в обоих наборах данных (что может вызвать такое же проблемное поведение, а также является общей проблемой):

In [7]: df = pd.DataFrame([['a', 3], ['b', 4],['b',0]], columns=['A', 'B'])

In [8]: df2 = pd.DataFrame([['a', 3], ['b', 8],['b',5]], columns=['A', 'C'])

In [9]: df['count'] = df.groupby('A')['B'].cumcount()

In [10]: df['A'] = np.where(df['count']>0,df['A']+df['count'].astype(str),df['A'].astype(str))

In[11]: df
Out[11]: 
    A  B  count
0   a  3      0
1   b  4      0
2  b1  0      1

Сделайте то же самое для df2, отбросьте переменные count в df и df2 и добавьте "A":

In [16]: merged
Out[16]: 
    A  B  C
0   a  3  3        
1   b  4  8        
2  b1  0  5        

Пара заметок. В этом последнем случае я использую .cumcount() вместо .duplicated, потому что это может быть случай, когда у вас есть более одного дубликата для данного наблюдения. Кроме того, я использую .astype(str) для преобразования значений счетчика в строки, потому что я использую команду np.where(), но использование pd.concat() или что-то еще может позволить для других приложений.

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

Ответ 3

Небольшое дополнение к данным ответам заключается в том, что существует параметр с именем validate, который можно использовать для выдачи ошибки, если в правой таблице совпадают идентификаторы:

combined = pd.merge(a,b,how='left',left_on='id',right_on='key', validate = 'm:1')