Pandas: ปล่อยระดับจากดัชนีคอลัมน์หลายระดับ?


242

หากฉันมีดัชนีคอลัมน์หลายระดับ:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> pd.DataFrame([[1,2], [3,4]], columns=cols)
    
   --- + -
    b | ค
- + --- + -
0 | 1 | 2
1 | 3 | 4

ฉันจะวางระดับ "a" ของดัชนีนั้นได้อย่างไรดังนั้นฉันจึงจบลงด้วย:

    b | ค
- + --- + -
0 | 1 | 2
1 | 3 | 4

3
มันจะดีถ้ามี DataFrame วิธีที่ทำทั้งดัชนีและคอลัมน์ อาจเป็นการดร็อปหรือเลือกระดับดัชนี
Sören

@ Sörenตรวจสอบstackoverflow.com/a/56080234/3198568 ผลงานที่สามารถทำงานได้ทั้งดัชนีหลายระดับหรือคอลัมน์ผ่านพารามิเตอร์droplevel axis
irene

คำตอบ:


306

คุณสามารถใช้MultiIndex.droplevel:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> df = pd.DataFrame([[1,2], [3,4]], columns=cols)
>>> df
   a   
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]
>>> df.columns = df.columns.droplevel()
>>> df
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]

55
อาจเป็นการดีที่สุดที่จะพูดอย่างชัดเจนว่าระดับใดที่กำลังถูกดร็อป ระดับเป็นจุดเริ่มต้น 0 ดัชนีจากด้านบน >>> df.columns = df.columns.droplevel(0)
Ted Petrou

6
หากดัชนีที่คุณพยายามวางอยู่ทางด้านซ้าย (แถว) ไม่ใช่ด้านบน (คอลัมน์) คุณสามารถเปลี่ยน "คอลัมน์" เป็น "ดัชนี" และใช้วิธีการเดียวกัน:>>> df.index = df.index.droplevel(1)
Idodo

7
ใน Panda รุ่น 0.23.4 df.columns.droplevel()ไม่มีให้บริการอีกต่อไป
yoonghm

8
@yoonghm มันอยู่ที่นั่นคุณอาจจะแค่เรียกมันในคอลัมน์ที่ไม่มีดัชนีหลายตัว
matt harrison

1
ฉันมีสามระดับลึกและต้องการที่จะเลื่อนลงไปเพียงระดับกลาง ฉันพบว่าการลดระดับต่ำสุด (ระดับ [2]) และระดับสูงสุด (ระดับ [0]) นั้นดีที่สุด >>>df.columns = df.columns.droplevel(2) >>>df.columns = df.columns.droplevel(0)
Kyle C

65

อีกวิธีในการดร็อปดัชนีคือการใช้ list comprehension:

df.columns = [col[1] for col in df.columns]

   b  c
0  1  2
1  3  4

กลยุทธ์นี้ยังมีประโยชน์หากคุณต้องการรวมชื่อจากทั้งสองระดับเช่นในตัวอย่างด้านล่างซึ่งระดับล่างประกอบด้วยสอง 'y's:

cols = pd.MultiIndex.from_tuples([("A", "x"), ("A", "y"), ("B", "y")])
df = pd.DataFrame([[1,2, 8 ], [3,4, 9]], columns=cols)

   A     B
   x  y  y
0  1  2  8
1  3  4  9

การลดระดับบนสุดจะทำให้คอลัมน์สองคอลัมน์มีดัชนี 'y' ที่สามารถหลีกเลี่ยงได้โดยการเข้าร่วมชื่อกับรายการความเข้าใจ

df.columns = ['_'.join(col) for col in df.columns]

    A_x A_y B_y
0   1   2   8
1   3   4   9

นั่นเป็นปัญหาที่ฉันมีหลังจากทำกลุ่มโดยใช้เวลาสักครู่เพื่อค้นหาคำถามอื่นที่แก้ไข ฉันปรับแก้ปัญหานั้นให้ตรงกับกรณีเฉพาะที่นี่


2
[col[1] for col in df.columns]df.columns.get_level_values(1)มีมากขึ้นโดยตรง
Eric O Lebigot

2
มีความต้องการที่คล้ายกันซึ่งบางคอลัมน์มีค่าระดับว่าง ใช้สิ่งต่อไปนี้:[col[0] if col[1] == '' else col[1] for col in df.columns]
Logan

43

อีกวิธีหนึ่งในการทำเช่นนี้คือการกำหนดใหม่dfโดยอ้างอิงจาก cross section ของdfโดยใช้วิธี. xs

>>> df

    a
    b   c
0   1   2
1   3   4

>>> df = df.xs('a', axis=1, drop_level=True)

    # 'a' : key on which to get cross section
    # axis=1 : get cross section of column
    # drop_level=True : returns cross section without the multilevel index

>>> df

    b   c
0   1   2
1   3   4

1
ใช้ได้เฉพาะเมื่อใดก็ตามที่มีป้ายกำกับเดียวสำหรับระดับคอลัมน์ทั้งหมด
Ted Petrou

1
ไม่ทำงานเมื่อคุณต้องการเลื่อนระดับที่สอง
Sören

นี่เป็นทางออกที่ดีถ้าคุณต้องการแบ่งและวางในระดับเดียวกัน หากคุณต้องการฝานในระดับที่สอง (พูดb) จากนั้นให้เลื่อนระดับนั้นและปล่อยให้อยู่ในระดับแรก ( a) สิ่งต่อไปนี้จะใช้ได้:df = df.xs('b', axis=1, level=1, drop_level=True)
Tiffany G. Wilson

27

ตั้งแต่ Pandas 0.24.0เราสามารถใช้DataFrame.droplevel () :

cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
df = pd.DataFrame([[1,2], [3,4]], columns=cols)

df.droplevel(0, axis=1) 

#   b  c
#0  1  2
#1  3  4

สิ่งนี้มีประโยชน์มากถ้าคุณต้องการเก็บ DataFrame method-chain rolling


นี่เป็นวิธีการแก้ปัญหา "บริสุทธิ์ที่สุด" ที่ DataFrame ใหม่ถูกส่งคืนแทนที่จะแก้ไข "ในตำแหน่ง"
EliadL

16

คุณสามารถทำได้โดยเปลี่ยนชื่อคอลัมน์:

df.columns = ['a', 'b']

สิ่งนี้เกี่ยวข้องกับขั้นตอนแบบแมนนวล แต่อาจเป็นตัวเลือกโดยเฉพาะอย่างยิ่งหากคุณต้องการเปลี่ยนชื่อเฟรมข้อมูลของคุณในที่สุด


นี่เป็นสิ่งสำคัญที่คำตอบแรกของมิ้นท์ทำ ตอนนี้นอกจากนี้ยังมีไม่จำเป็นต้องระบุรายชื่อ (ซึ่งเป็นเรื่องปกติที่น่าเบื่อ) df.columns.get_level_values(1)ขณะที่มันถูกให้กับคุณโดย
Eric O Lebigot

13

เคล็ดลับเล็ก ๆ ที่ใช้sum กับ level = 1 (ทำงานเมื่อ level = 1 เป็นค่าเฉพาะทั้งหมด)

df.sum(level=1,axis=1)
Out[202]: 
   b  c
0  1  2
1  3  4

วิธีแก้ปัญหาทั่วไปเพิ่มเติม get_level_values

df.columns=df.columns.get_level_values(1)
df
Out[206]: 
   b  c
0  1  2
1  3  4

4

ฉันดิ้นรนกับปัญหานี้เพราะฉันไม่รู้ว่าทำไมฟังก์ชั่นหยดน้ำ () ของฉันจึงไม่ทำงาน ทำงานหลายอย่างและเรียนรู้ว่า 'a' ในตารางของคุณคือชื่อคอลัมน์และ 'b', 'c' เป็นดัชนี ทำเช่นนี้จะช่วย

df.columns.name = None
df.reset_index() #make index become label

1
นี่จะไม่ทำซ้ำเอาต์พุตที่ต้องการเลย
Eric O Lebigot

ขึ้นอยู่กับวันที่ที่โพสต์นี้ระดับการดร็อปอาจไม่ได้รวมอยู่ใน Pandas เวอร์ชันของคุณ (ถูกเพิ่มในเวอร์ชันเสถียร, 24.0, ในเดือนมกราคม 2019)
LinkBerest
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.