Як зберегти індекс при використанні злиття панд


126

Я хотів би об'єднати два DataFramesта зберегти індекс із першого кадру як індекс на зведеному наборі даних. Однак, коли я зливаю, отриманий DataFrame має цілий індекс. Як я можу вказати, що я хочу зберегти індекс у лівому кадрі даних?

In [4]: a = pd.DataFrame({'col1': {'a': 1, 'b': 2, 'c': 3}, 
                          'to_merge_on': {'a': 1, 'b': 3, 'c': 4}})

In [5]: b = pd.DataFrame({'col2': {0: 1, 1: 2, 2: 3}, 
                          'to_merge_on': {0: 1, 1: 3, 2: 5}})

In [6]: a
Out[6]:
   col1  to_merge_on
a     1            1
b     2            3
c     3            4

In [7]: b
Out[7]:
   col2  to_merge_on
0     1            1
1     2            3
2     3            5

In [8]: a.merge(b, how='left')
Out[8]:
   col1  to_merge_on  col2
0     1            1   1.0
1     2            3   2.0
2     3            4   NaN

In [9]: _.index
Out[9]: Int64Index([0, 1, 2], dtype='int64')

EDIT: Переключення на приклад коду, який можна легко відтворити


2
якщо ви об'єднаєтесь у певний стовпець, не зрозуміло, які індекси використовувати (якщо вони обидва різні).
bonobo

Відповіді:


161
In [5]: a.reset_index().merge(b, how="left").set_index('index')
Out[5]:
       col1  to_merge_on  col2
index
a         1            1     1
b         2            3     2
c         3            4   NaN

Примітка: для деяких лівих операцій злиття ви можете в кінцевому підсумку з великою кількістю рядків , якщо є кілька відповідностей між aі bі ви повинні Дедупліціровать ( документацію для дедуплікаціі ). Ось чому панди не зберігають індекс для вас.


4
Дуже розумний. a.merge (b, how = "зліва"). set_index (a.index) також працює, але він здається менш надійним (оскільки перша його частина втрачає значення індексу до a, перш ніж скидає їх.)
DanB

11
У цьому конкретному випадку вони є рівнозначними. Але для багатьох операцій з об'єднання отриманий кадр має не таку ж кількість рядків, що й вихідний aкадр. reset_index переміщує індекс у звичайний стовпець, а set_index з цього стовпця після злиття також дбає про те, що рядки a дублюються / видаляються через операцію злиття.
Wouter Overmeire

1
@Wouter Я хотів би знати, чому ліве злиття заново заново встановиться. Де я можу дізнатися більше?
Метью

7
Приємно! Щоб явно не вказати ім'я індексу, яке я використовую a.reset_index().merge(b, how="left").set_index(a.index.names).
Трулс

3
Панди погано подумали, що API повторюється.
Генрі Генрінсон

7

Ви можете зробити копію індексу на лівій рамці даних і зробити об'єднання.

a['copy_index'] = a.index
a.merge(b, how='left')

Я вважав цей простий метод дуже корисним під час роботи з великими рамками даних та використання pd.merge_asof()(або dd.merge_asof()).

Цей підхід був би найкращим, коли скидання індексу є дорогим (великий кадр даних).


1
Це найкраща відповідь. Є багато причин, чому ви хочете зберегти свої старі індекси під час злиття (а прийнята відповідь не зберігає індекси, вона просто їх скидає). Це допомагає, коли ви намагаєтеся об'єднати більше двох фреймів даних і так далі ...
Марси

2
Прекрасне рішення, оскільки воно зберігає (оригінальну) назву індексу
Martien Lubberink

прихильне, але просто будьте обережні, за умови використання мультиіндексу ваші індекси зберігатимуться як кортеж в одній колонці під назвою [copy_index]
geekidharsh

6

Існує не pd.merge рішення. Використання mapтаset_index

In [1744]: a.assign(col2=a['to_merge_on'].map(b.set_index('to_merge_on')['col2']))
Out[1744]:
   col1  to_merge_on  col2
a     1            1   1.0
b     2            3   2.0
c     3            4   NaN

І не вводить фіктивну indexназву для індексу.


1
Це здається вищим за прийнятий відповідь, оскільки, ймовірно, краще працюватиме з крайніми справами, такими як мультиіндекси. Хтось може прокоментувати це?
BallpointBen

1
питання, що, якщо вам потрібно призначити кілька стовпців, чи працював би такий підхід або він обмежений лише одним полем?
Юка

@Yuca: Можливо, це не працюватиме з кількома стовпцями, оскільки коли ви підмножили кілька стовпців, ви закінчуєте а, pd.Dataframeа не a pd.Series. .map()Метод визначено тільки для pd.Series. Це означає, що: a[['to_merge_on_1', 'to_merge_on_2']].map(...)не буде працювати.
Dataman

4
df1 = df1.merge(
        df2, how="inner", left_index=True, right_index=True
    )

Це дозволяє зберегти індекс df1


Це схоже на роботу, але коли я використовую його on=list_of_cols], це суперечить документації: If joining columns on columns, the DataFrame indexes *will be ignored*. Чи має перевагу одне із використання індексів та стовпців?
Ітамар Кац

0

Подумайте, я придумав інше рішення. Я приєднував ліву таблицю за значенням індексу та праву таблицю за значенням стовпця на основі індексу лівої таблиці. Те, що я зробив, було нормальним злиттям:

First10ReviewsJoined = pd.merge(First10Reviews, df, left_index=True, right_on='Line Number')

Потім я отримав нові індексні номери з об'єднаної таблиці і помістив їх у новий стовпець під назвою Номер рядка надіслання:

First10ReviewsJoined['Sentiment Line Number']= First10ReviewsJoined.index.tolist()

Потім я вручну повертаю індекс до початкового лівого індексу таблиці на основі попереднього стовпця під назвою Номер рядка (значення стовпця, до якого я приєднався з індексу лівої таблиці):

First10ReviewsJoined.set_index('Line Number', inplace=True)

Потім видаліть ім'я індексу номера рядка, щоб він залишався порожнім:

First10ReviewsJoined.index.name = None

Можливо, трохи зламати, але, здається, працює добре і порівняно просто. Також здогадуйтесь, що це зменшує ризик дублікатів / псування ваших даних. Сподіваємось, що все має сенс.


0

Ще один простий варіант - перейменувати індекс на той, що був раніше:

a.merge(b, how="left").set_axis(a.index)

Злиття зберігає порядок у кадрі даних 'a', але просто скидає індекс, щоб зберегти для використання set_axis

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.