Я хотел бы объединить два DataFram, содержащих два общих столбца. У них одинаковое количество строк, и я знаю, что порядок в обоих столбцах одинаков, поэтому они уже выровнены. Моя проблема в том, что после их слияния у меня осталось больше строк, чем было изначально.
Есть ли способ объединить эти два кадра данных и сохранить исходное число строк?
df1 = pd.DataFrame(
[
{"col1": 1, "col2": 1, "unique_df1_val": "value1"},
{"col1": 2, "col2": 2, "unique_df1_val": "value2"},
{"col1": 2, "col2": 2, "unique_df1_val": "value3"},
]
)
df2 = pd.DataFrame(
[
{"col1": 1, "col2": 1, "unique_df2_val": "value4"},
{"col1": 2, "col2": 2, "unique_df2_val": "value5"},
{"col1": 2, "col2": 2, "unique_df2_val": "value6"},
]
)
### Do some merge of the two ###
# Expected DataFrame
col1 col2 unique_df1_val unique_df2_val
0 1 1 value1 value4
1 2 2 value2 value5
2 2 2 value3 value6
Я пытался использовать df1.merge(df2, how="outer"), но это не дает мне правильного результата.
df1.merge(df2, how = "outer")
# Returns
col1 col2 unique_df1_val unique_df2_val
0 1 1 value1 value4
1 2 2 value2 value5
2 2 2 value2 value6
3 2 2 value3 value5
4 2 2 value3 value6
Это была опечатка, спасибо, что заметили!
Имеет ли значение порядок? Если вы переместите строку 2 из df2
в последнюю позицию, должен ли вывод быть таким же или значение3 должно идти со значением4?
Они сортируются и выравниваются так, чтобы строки 1 в df1 и df2 были соединены и так далее для каждой строки.
Тогда используйте df1['unique_df2_val'] = df2['unique_df2_val']
;)
Используйте pd.concat вместо merge
. Если ваши данные выровнены, вы можете просто объединить столбец/столбцы, которые вы хотите, в финале кадра данных.
pd.concat([df1, df2['unique_df2_val']], axis=1)
Вывод:
col1 col2 unique_df1_val unique_df2_val
0 1 1 value1 value4
1 2 2 value2 value5
2 2 2 value3 value6
Если все они имеют одинаковую длину и предварительно отсортированы с одинаковым количеством наблюдений на столбец 1 и столбец 2, рассмотрите возможность использования соединения вместо слияния. Однако будьте осторожны, так как операция выполняется с индексами (по умолчанию), а не со значениями столбцов:
Соедините столбцы с другим DataFrame либо по индексу, либо по ключевому столбцу. Эффективно объединяйте несколько объектов DataFrame по индексу одновременно, передавая список.
df1.join(df2,lsuffix='drop').drop(columns=[x+'drop' for x in df1.columns if x in df2.columns])
Вывод:
unique_df1_val col1 col2 unique_df2_val
0 value1 1 1 value4
1 value2 2 2 value5
2 value3 2 2 value6
Если операция слияния не нужна, потому что данные всегда будут идеально выровнены, то просто рассмотрите возможность определения нового столбца:
df1['unique_df2_val'] = df2['unique_df2_val']
На самом деле это не merge
, это предполагает, что строки уже выровнены (в этом случае было бы лучше простое объединение или присваивание)
Последний вариант тоже сработал, со второй попытки :D
Для эффективного решения и настоящего слияния выполните дедупликацию перед слиянием:
cols = ['col1', 'col2']
out = (df1.merge(df2, left_on=[df1.groupby(cols).cumcount(), *cols],
right_on=[df1.groupby(cols).cumcount(), *cols])
.drop(columns='key_0')
)
Вывод:
col1 col2 unique_df1_val unique_df2_val
0 1 1 value1 value4
1 2 2 value2 value5
2 2 2 value3 value6
Ударь меня. Дополнительное пояснение: здесь дедуплицируется каждая комбинация столбцов col1 и col2 путем введения третьего столбца, в котором ведется подсчет этих дубликатов.
Если вы внимательно посмотрите, col1 не имеет 3 в качестве третьего значения, вместо этого 2. Либо ваши входные данные неверны, либо то, чего вы пытаетесь достичь, невозможно (как при создании 3)