วิธีเก็บดัชนีเมื่อใช้แพนด้าผสาน


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')

แก้ไข: เปลี่ยนเป็นโค้ดตัวอย่างที่สามารถทำซ้ำได้ง่าย


2
หากคุณรวมในคอลัมน์ใดคอลัมน์หนึ่งจะไม่ชัดเจนว่าจะใช้ดัชนีใด (ในกรณีที่ทั้งสองต่างกัน)
bonobo

คำตอบ:


162
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 = "left") set_index (a.index) ก็ใช้ได้เช่นกัน แต่ดูเหมือนว่าจะมีประสิทธิภาพน้อยกว่า (เนื่องจากส่วนแรกสูญเสียค่าดัชนีไปเป็นค่าก่อนที่จะรีเซ็ต)
DanB

11
สำหรับกรณีนี้จะเทียบเท่า แต่สำหรับการดำเนินการผสานจำนวนมากเฟรมผลลัพธ์จะมีจำนวนแถวไม่เท่ากันกับaเฟรมเดิม reset_index ย้ายดัชนีไปยังคอลัมน์ปกติและ set_index จากคอลัมน์นี้หลังจากการผสานยังดูแลเมื่อแถวของ a ซ้ำ / ลบออกเนื่องจากการดำเนินการผสาน
Wouter Overmeire

1
@ เราเตอร์ฉันอยากรู้ว่าทำไมการผสานด้านซ้ายจะ reindex โดยค่าเริ่มต้น ฉันจะเรียนรู้เพิ่มเติมได้ที่ไหน?
Matthew

7
ดี! เพื่อหลีกเลี่ยงการระบุชื่อดัชนีที่ฉันใช้a.reset_index().merge(b, how="left").set_index(a.index.names)อย่างชัดเจน
Truls

3
นุ่นคิดร้าย API นัดหยุดงานอีกครั้ง
Henry Henrinson

7

คุณสามารถสร้างสำเนาดัชนีบนดาต้าเฟรมด้านซ้ายและทำการผสาน

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

ฉันพบว่าวิธีง่ายๆนี้มีประโยชน์มากในขณะที่ทำงานกับดาต้าเฟรมขนาดใหญ่และใช้pd.merge_asof()(หรือdd.merge_asof())

วิธีนี้จะดีกว่าเมื่อการรีเซ็ตดัชนีมีราคาแพง (ดาต้าเฟรมขนาดใหญ่)


1
นี่คือคำตอบที่ดีที่สุด มีสาเหตุหลายประการที่คุณต้องการเก็บรักษาดัชนีเก่าของคุณไว้ในระหว่างการผสาน (และคำตอบที่ยอมรับจะไม่เก็บดัชนี แต่เพียงแค่รีเซ็ตดัชนีเท่านั้น) ช่วยได้เมื่อคุณพยายามรวมมากกว่า 2 ดาต้าเฟรมและอื่น ๆ ...
Marses

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
สิ่งนี้ดูเหมือนจะดีกว่าคำตอบที่ได้รับการยอมรับเนื่องจากอาจทำงานได้ดีกว่ากับ edge case เช่น multi index ใครสามารถแสดงความคิดเห็นเกี่ยวกับเรื่องนี้?
BallpointBen

1
คำถามถ้าคุณต้องการกำหนดหลายคอลัมน์วิธีนี้จะใช้ได้ผลหรือไม่หรือ จำกัด เพียง 1 ช่อง?
Yuca

@Yuca: สิ่งนี้อาจใช้ไม่ได้กับหลายคอลัมน์เนื่องจากเมื่อคุณย่อยหลายคอลัมน์คุณจะจบลงด้วย a 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*หนึ่งในการใช้ดัชนีเทียบกับคอลัมน์มีความสำคัญหรือไม่?
Itamar Katz

0

คิดว่าฉันคิดวิธีแก้ปัญหาที่แตกต่างออกไป ฉันเข้าร่วมตารางด้านซ้ายกับค่าดัชนีและตารางด้านขวาบนค่าคอลัมน์ที่อิงจากดัชนีของตารางด้านซ้าย สิ่งที่ฉันทำคือการผสานปกติ:

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

จากนั้นฉันดึงหมายเลขดัชนีใหม่จากตารางที่ผสานและใส่ไว้ในคอลัมน์ใหม่ชื่อ Sentiment Line Number:

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

จากนั้นฉันตั้งค่าดัชนีกลับไปที่ดัชนีตารางด้านซ้ายด้วยตนเองโดยอิงจากคอลัมน์ที่มีอยู่แล้วที่เรียกว่า Line Number (ค่าคอลัมน์ที่ฉันเข้าร่วมจากดัชนีตารางด้านซ้าย):

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

จากนั้นลบชื่อดัชนีของ Line Number ออกเพื่อให้ว่างเปล่า:

First10ReviewsJoined.index.name = None

อาจจะเป็นการแฮ็กเล็กน้อย แต่ดูเหมือนว่าจะทำงานได้ดีและค่อนข้างง่าย นอกจากนี้เดาว่าจะช่วยลดความเสี่ยงของการซ้ำ / การทำให้ข้อมูลของคุณยุ่งเหยิง หวังว่าทุกอย่างจะสมเหตุสมผล


0

อีกทางเลือกง่ายๆคือการเปลี่ยนชื่อดัชนีเป็นสิ่งที่เคยมีมาก่อน:

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

merge รักษาคำสั่งที่ dataframe 'a' แต่เพียงแค่รีเซ็ตดัชนีดังนั้นจึงบันทึกเพื่อใช้ set_axis

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.