การลบหลายคอลัมน์ตามชื่อคอลัมน์ใน Pandas


95

ฉันมีข้อมูลบางส่วนและเมื่อฉันนำเข้าฉันจะได้รับคอลัมน์ที่ไม่จำเป็นต่อไปนี้ฉันกำลังมองหาวิธีง่ายๆในการลบสิ่งเหล่านี้ทั้งหมด

   'Unnamed: 24', 'Unnamed: 25', 'Unnamed: 26', 'Unnamed: 27',
   'Unnamed: 28', 'Unnamed: 29', 'Unnamed: 30', 'Unnamed: 31',
   'Unnamed: 32', 'Unnamed: 33', 'Unnamed: 34', 'Unnamed: 35',
   'Unnamed: 36', 'Unnamed: 37', 'Unnamed: 38', 'Unnamed: 39',
   'Unnamed: 40', 'Unnamed: 41', 'Unnamed: 42', 'Unnamed: 43',
   'Unnamed: 44', 'Unnamed: 45', 'Unnamed: 46', 'Unnamed: 47',
   'Unnamed: 48', 'Unnamed: 49', 'Unnamed: 50', 'Unnamed: 51',
   'Unnamed: 52', 'Unnamed: 53', 'Unnamed: 54', 'Unnamed: 55',
   'Unnamed: 56', 'Unnamed: 57', 'Unnamed: 58', 'Unnamed: 59',
   'Unnamed: 60'

พวกเขาถูกสร้างดัชนีโดย 0-indexing ดังนั้นฉันจึงลองทำสิ่งต่างๆเช่น

    df.drop(df.columns[[22, 23, 24, 25, 
    26, 27, 28, 29, 30, 31, 32 ,55]], axis=1, inplace=True)

แต่มันไม่ได้มีประสิทธิภาพมากนัก ฉันพยายามเขียนบางส่วนสำหรับการวนซ้ำ แต่สิ่งนี้ทำให้ฉันรู้สึกว่าเป็นพฤติกรรมของแพนด้าที่ไม่ดี ดังนั้นฉันจึงถามคำถามที่นี่

ฉันเคยเห็นตัวอย่างที่คล้ายกัน ( วางแพนด้าหลายคอลัมน์ ) แต่สิ่งนี้ไม่ตอบคำถามของฉัน


2
คุณหมายถึงอะไรมีประสิทธิภาพ? ทำงานช้าเกินไปหรือไม่? หากปัญหาของคุณคือคุณไม่ต้องการรับดัชนีของคอลัมน์ทั้งหมดที่คุณต้องการลบโปรดทราบว่าคุณสามารถdf.dropระบุชื่อคอลัมน์ได้:df.drop(['Unnamed: 24', 'Unnamed: 25', ...], axis=1)
Carsten

การย่อยคอลัมน์ที่สนใจไม่ใช่เรื่องง่ายกว่าdf = df[cols_of_interest]ไหมกล่าวคือมิฉะนั้นคุณสามารถแบ่ง df ตามคอลัมน์และรับคอลัมน์df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)
EdChum

2
ฉันหมายถึงไม่มีประสิทธิภาพในแง่ของการพิมพ์หรือ 'กลิ่นรหัสไม่ดี'
Peadar Coyle

1
อาจเป็นที่น่าสังเกตว่าในกรณีส่วนใหญ่มันง่ายกว่าเพียงแค่เก็บคอลัมน์ที่คุณต้องการจากนั้นลบคอลัมน์ที่คุณไม่ต้องการ: df = df ['col_list']
sparrow

คำตอบ:


65

ฉันไม่รู้ว่าคุณหมายถึงอะไรโดยไม่มีประสิทธิภาพ แต่ถ้าคุณหมายถึงในแง่ของการพิมพ์มันอาจจะง่ายกว่าแค่เลือก cols ที่สนใจและกำหนดกลับไปที่ df:

df = df[cols_of_interest]

ที่ไหนcols_of_interestคือรายการคอลัมน์ที่คุณดูแลเกี่ยวกับ

หรือคุณสามารถแบ่งคอลัมน์และส่งต่อไปยังdrop:

df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)

การเรียกเพื่อheadเลือก 0 แถวเนื่องจากเราสนใจเฉพาะชื่อคอลัมน์มากกว่าข้อมูล

อัพเดต

อีกวิธีหนึ่ง: การใช้บูลีนมาสก์จากstr.containsและกลับด้านเพื่อมาสก์คอลัมน์จะง่ายกว่า:

In [2]:
df = pd.DataFrame(columns=['a','Unnamed: 1', 'Unnamed: 1','foo'])
df

Out[2]:
Empty DataFrame
Columns: [a, Unnamed: 1, Unnamed: 1, foo]
Index: []

In [4]:
~df.columns.str.contains('Unnamed:')

Out[4]:
array([ True, False, False,  True], dtype=bool)

In [5]:
df[df.columns[~df.columns.str.contains('Unnamed:')]]

Out[5]:
Empty DataFrame
Columns: [a, foo]
Index: []

ฉันได้รับข้อผิดพลาดเมื่อลองทำ ~ df.columns ... (TypeError: bad operand type สำหรับ unary ~: 'str') หรือ df.columns.str.contains ... (AttributeError: 'Index' object ไม่มีแอตทริบิวต์ 'str') ความคิดใด ๆ ที่อาจเป็นเช่นนี้?
Dai

@EdChum ฉันสามารถสร้างdf = df [cols_of_interest]โดยที่cols_of_interestจะเพิ่มชื่อคอลัมน์ทุกครั้งที่มีการวนซ้ำได้หรือไม่

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

@EdChum คุณพูดถูกจริงๆ ฉันได้สร้างคำถามแล้วและฉันกำลังพยายามแก้ไขโดยค้นหาส่วนต่างๆของ SO นี่คือลิงค์ ! การมีส่วนร่วมใด ๆ จะช่วยให้stackoverflow.com/questions/48923915/…

214

วิธีการที่ง่ายที่สุดคือ:

yourdf.drop(['columnheading1', 'columnheading2'], axis=1, inplace=True)

1
ฉันใช้รูปแบบนี้กับโค้ดบางส่วนและได้SettingWithCopyWarningรับคำเตือน?
KillerSnail

2
@KillerSnail ก็บันทึกละเว้น เพื่อหลีกเลี่ยงข้อผิดพลาดลอง: df = df.drop (['colheading1', 'colheading2'], axis = 1)
Philipp Schwarz

5
คำaxisอธิบาย: stackoverflow.com/questions/22149584/… . โดยพื้นฐานแล้วaxis=0จะกล่าวว่าเป็น "คอลัมน์ที่ชาญฉลาด" และaxis=1เป็น "แถวที่ชาญฉลาด"
Rohmer

5
และinplace=Trueหมายความว่าDataFrameมีการแก้ไขในสถานที่
Rohmer

1
@Killernail ถ้าคุณไม่ต้องการคำเตือนให้ทำyourdf = yourdf.drop(['columnheading1', 'columnheading2'], axis=1)
happy_sisyphus

41

รายการโปรดส่วนตัวของฉันและง่ายกว่าคำตอบที่ฉันเห็นที่นี่ (สำหรับหลายคอลัมน์):

df.drop(df.columns[22:56], axis=1, inplace=True)

หรือการสร้างรายการสำหรับหลายคอลัมน์

col = list(df.columns)[22:56]
df.drop(col, axis=1, inplace=1)

8
นี่น่าจะเป็นคำตอบ สะอาดที่สุดอ่านง่ายที่สุดพร้อมไวยากรณ์การจัดทำดัชนีของ Pandas ที่ตรงไปตรงมา
Brent Faust

2
คำตอบนี้ควรมีเครื่องหมายถูกสีเขียวอยู่ข้างๆไม่ใช่คำตอบอื่น ๆ
Siavosh Mahboubian

1
การแก้ไขเล็กน้อย (เว้นแต่ว่าฉันเข้าใจผิด): โค้ดบล็อกที่สองควรมี 'inplace = True' แทน 'inplace = 1'
Thredolsen

20

นี่อาจเป็นวิธีที่ดีในการทำสิ่งที่คุณต้องการ จะลบคอลัมน์ทั้งหมดที่มี "ไม่มีชื่อ" ในส่วนหัว

for col in df.columns:
    if 'Unnamed' in col:
        del df[col]

สิ่งนี้for col in df.columns:สามารถทำให้ง่ายfor col in df:ขึ้นได้นอกจากนี้ OP ยังไม่ได้ระบุว่ารูปแบบการตั้งชื่อสำหรับคอลัมน์อื่น ๆ ทั้งหมดสามารถมี 'ไม่มีชื่อ' ได้นอกจากนี้ยังไม่มีประสิทธิภาพเนื่องจากจะลบคอลัมน์ทีละคอลัมน์
EdChum

มันไม่ได้มีประสิทธิภาพอย่างแน่นอน แต่ตราบใดที่เราไม่ได้ทำงานกับดาต้าเฟรมขนาดใหญ่มันจะไม่มีผลกระทบอย่างมีนัย ข้อดีของวิธีนี้คือการจำง่ายและรวดเร็วในการเขียนโค้ด - ในขณะที่การสร้างรายการคอลัมน์ที่คุณต้องการเก็บไว้อาจเป็นเรื่องที่น่าเจ็บปวด
knightofni

ฉันคิดว่านี่น่าจะมีประสิทธิภาพมากที่สุดใน df ขนาดใหญ่เพราะคุณไม่ต้องทำสำเนาในเครื่องด้วยinplace = True
Matt

13

คุณสามารถทำได้ในบรรทัดเดียวและครั้งเดียว:

df.drop([col for col in df.columns if "Unnamed" in col], axis=1, inplace=True)

ซึ่งเกี่ยวข้องกับการเคลื่อนย้าย / คัดลอกวัตถุน้อยกว่าวิธีแก้ปัญหาข้างต้น


11

ถ้าไม่แน่ใจว่าวิธีการแก้ปัญหานี้ได้รับการกล่าวถึงทุกที่เลย pandas.Index.differenceแต่วิธีหนึ่งที่จะทำคือการเป็น

>>> df = pd.DataFrame(columns=['A','B','C','D'])
>>> df
Empty DataFrame
Columns: [A, B, C, D]
Index: []
>>> to_remove = ['A','C']
>>> df = df[df.columns.difference(to_remove)]
>>> df
Empty DataFrame
Columns: [B, D]
Index: []

4

คุณสามารถส่งชื่อคอลัมน์เป็นรายการโดยระบุแกนเป็น 0 หรือ 1

  • แกน = 1: ตามแถว
  • แกน = 0: ตามคอลัมน์
  • โดยแกนเริ่มต้น = 0

    data.drop(["Colname1","Colname2","Colname3","Colname4"],axis=1)


4

ง่ายและสะดวก ลบคอลัมน์ทั้งหมดหลังจากวันที่ 22

df.drop(columns=df.columns[22:]) # love it

หากต้องการแก้ไขdfในสถานที่ให้เพิ่มธงinplace=TrueSo thatdf.drop(columns=df.columns[22:], inplace=True)
arilwan

1

ด้านล่างใช้ได้ผลสำหรับฉัน:

for col in df:
    if 'Unnamed' in col:
        #del df[col]
        print col
        try:
            df.drop(col, axis=1, inplace=True)
        except Exception:
            pass

0

df = df[[col for col in df.columns if not ('Unnamed' in col)]]


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