Hapus kolom dari panda DataFrame

1332

Saat menghapus kolom dalam DataFrame yang saya gunakan:

del df['column_name']

Dan ini bekerja dengan baik. Mengapa saya tidak bisa menggunakan yang berikut ini?

del df.column_name

Karena dimungkinkan untuk mengakses kolom / Seri sebagai df.column_name, saya berharap ini berfungsi.

John
sumber
2
Perhatikan pertanyaan ini sedang dibahas di Meta .
RM

Jawaban:

860

Seperti yang sudah Anda tebak, sintaks yang tepat adalah

del df['column_name']

Sulit untuk membuat del df.column_namepekerjaan hanya sebagai hasil dari keterbatasan sintaksis dalam Python. del df[name]diterjemahkan ke df.__delitem__(name)bawah selimut oleh Python.

Wes McKinney
sumber
25
Saya menyadari ini adalah "jawaban" yang sangat lama, tetapi keingintahuan saya terguncang - mengapa itu adalah batasan sintaksis Python? class A(object): def __init__(self): self.var = 1membuat kelas, lalu a = A(); del a.varbekerja dengan baik ...
dwanderson
14
@dwanderson perbedaannya adalah bahwa ketika sebuah kolom akan dihapus, DataFrame perlu memiliki penanganan sendiri untuk "bagaimana melakukannya". Dalam hal ini del df[name], itu akan diterjemahkan df.__delitem__(name)yang merupakan metode yang DataFrame dapat menerapkan dan memodifikasi untuk kebutuhannya. Dalam kasus del df.name, variabel anggota dihapus tanpa peluang untuk menjalankan kode kustom. Pertimbangkan contoh Anda sendiri - dapatkah Anda del a.varmenghasilkan cetakan "menghapus variabel"? Jika Anda bisa, tolong beri tahu saya caranya. Saya tidak bisa :)
Yonatan
8
@Yonatan Anda dapat menggunakan docs.python.org/3/reference/datamodel.html#object.__delattr__ atau deskriptor untuk itu: docs.python.org/3/howto/descriptor.html
Eugene Pakhomov
5
Komentar @Yonatan Eugene berlaku untuk Python 2 juga; deskriptor telah ada di Python 2 sejak 2.2 dan itu sepele untuk memenuhi kebutuhan Anda;)
CS
1
Jawaban ini tidak benar - pandaspengembang tidak , tetapi itu tidak berarti sulit untuk dilakukan.
wizzwizz4
2186

Cara terbaik untuk melakukan ini dalam panda adalah dengan menggunakan drop:

df = df.drop('column_name', 1)

di mana 1adalah sumbu nomor ( 0untuk baris dan 1untuk kolom.)

Untuk menghapus kolom tanpa harus ditugaskan kembali, dfAnda dapat melakukan:

df.drop('column_name', axis=1, inplace=True)

Terakhir, untuk menghapus dengan nomor kolom alih-alih dengan label kolom , coba ini untuk menghapus, misalnya kolom 1, 2 dan 4:

df = df.drop(df.columns[[0, 1, 3]], axis=1)  # df.columns is zero-based pd.Index 

Juga bekerja dengan sintaks "teks" untuk kolom:

df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)
LondonRob
sumber
79
Apakah ini direkomendasikan delkarena beberapa alasan?
beardc
20
Meskipun metode penghapusan ini memiliki kelebihan, jawaban ini tidak benar-benar menjawab pertanyaan yang diajukan.
Paul
109
Benar @ Paul, tetapi karena judul pertanyaan, kebanyakan orang yang tiba di sini akan melakukannya dengan mencoba mencari cara menghapus kolom.
LondonRob
24
@beardc keuntungan lain dari dropatas deladalah bahwa dropmemungkinkan Anda untuk drop beberapa kolom sekaligus, melakukan inplace operasi atau tidak, dan catatan juga menghapus sepanjang sumbu (terutama berguna untuk matriks 3-D atau Panel)
kompor
8
Keuntungan lain dari dropover deladalah bahwa drop adalah bagian dari API panda dan berisi dokumentasi.
modulitos
242

Menggunakan:

columns = ['Col1', 'Col2', ...]
df.drop(columns, inplace=True, axis=1)

Ini akan menghapus satu atau lebih kolom di tempat. Catatan yang inplace=Trueditambahkan dalam panda v0.13 dan tidak akan berfungsi pada versi yang lebih lama. Anda harus menetapkan hasilnya kembali dalam kasus itu:

df = df.drop(columns, axis=1)
Krishna Sankar
sumber
3
Catatan tentang jawaban ini: jika 'daftar' digunakan, tanda kurung siku harus dijatuhkan:df.drop(list,inplace=True,axis=1)
edesz
1
jawaban ini harus benar-benar diterima, karena memperjelas keunggulan metode ini del- dapat menjatuhkan lebih dari satu kolom sekaligus.
dbliss
111

Drop by index

Hapus kolom pertama, kedua, dan keempat:

df.drop(df.columns[[0,1,3]], axis=1, inplace=True)

Hapus kolom pertama:

df.drop(df.columns[[0]], axis=1, inplace=True)

Ada parameter opsional inplacesehingga data asli dapat dimodifikasi tanpa membuat salinan.

Muncul

Pemilihan kolom, penambahan, penghapusan

Hapus kolom column-name:

df.pop('column-name')

Contoh:

df = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6]), ('C', [7,8, 9])], orient='index', columns=['one', 'two', 'three'])

print df:

   one  two  three
A    1    2      3
B    4    5      6
C    7    8      9

df.drop(df.columns[[0]], axis=1, inplace=True) print df:

   two  three
A    2      3
B    5      6
C    8      9

three = df.pop('three') print df:

   two
A    2
B    5
C    8
jezrael
sumber
1
Bagaimana saya bisa memunculkan baris dalam panda?
Kennet Celeste
2
@Yugi Anda dapat menggunakan kerangka data yang telah diubah untuk itu. ex - df.T.pop('A')
Jam Slave
@ClockSlave Itu tidak mengubah yang asli df. Anda bisa melakukannya df = df.T; df.pop(index); df = df.Ttetapi ini tampaknya berlebihan.
cs95
Bukannya df.drop(df.columns[[0]], axis=1, inplace=True)tidak cukup untuk digunakan df.drop([0], axis=1)?
Anirban Mukherjee
1
@Anirban Mukherjee Tergantung. Jika ingin menghapus nama kolom 0, maka df.drop(0, axis=1)berfungsi dengan baik. Tetapi jika tidak tahu nama kolom dan perlu menghapus kolom pertama maka perlu df.drop(df.columns[[0]], axis=1, inplace=True), itu memilih kolom pertama dengan posisi dan menjatuhkannya.
jezrael
71

Pertanyaan aktual yang diajukan, terlewatkan oleh sebagian besar jawaban di sini adalah:

Kenapa saya tidak bisa menggunakan del df.column_name?

Pada awalnya kita perlu memahami masalahnya, yang mengharuskan kita untuk menyelami metode sulap python .

Seperti yang Wes tunjukkan dalam jawabannya del df['column']memetakan metode sulap python df.__delitem__('column')yang diimplementasikan dalam panda untuk menjatuhkan kolom

Namun, seperti yang ditunjukkan pada tautan di atas tentang metode sulap python :

Bahkan, __del__hampir tidak boleh digunakan karena keadaan genting di mana ia disebut; gunakan dengan hati-hati!

Anda bisa berargumen bahwa del df['column_name']tidak boleh digunakan atau didorong, dan dengan demikian del df.column_nameseharusnya tidak dipertimbangkan.

Namun, dalam teori, del df.column_namedapat implemeted untuk bekerja di panda menggunakan satu metode magic__delattr__ . Namun hal ini menimbulkan masalah-masalah tertentu, masalah-masalah yang del df['column_name']sudah dimiliki oleh implementasi, tetapi pada tingkat yang lebih rendah.

Contoh Masalah

Bagaimana jika saya mendefinisikan kolom dalam kerangka data yang disebut "dtypes" atau "kolom".

Kemudian anggap saya ingin menghapus kolom ini.

del df.dtypesakan membuat __delattr__metode bingung seolah-olah harus menghapus atribut "dtypes" atau kolom "dtypes".

Pertanyaan arsitektur di balik masalah ini

  1. Apakah dataframe merupakan kumpulan kolom ?
  2. Apakah dataframe merupakan kumpulan baris ?
  3. Apakah kolom atribut dari dataframe?

Jawaban Panda:

  1. Ya, dengan segala cara
  2. Tidak, tetapi jika Anda menginginkannya, Anda dapat menggunakan .ix, .locatau .ilocmetode.
  3. Mungkin, apakah Anda ingin membaca data? Maka ya , kecuali nama atribut sudah diambil oleh atribut lain yang termasuk dalam bingkai data. Apakah Anda ingin mengubah data? Lalu tidak .

TLDR;

Anda tidak dapat melakukannya del df.column_namekarena panda memiliki arsitektur yang tumbuh sangat liar yang perlu dipertimbangkan kembali agar disonansi kognitif semacam ini tidak terjadi pada penggunanya.

Protip:

Jangan gunakan df.column_name, Ini mungkin cukup, tetapi menyebabkan disonansi kognitif

Kutipan Zen dari Python yang cocok di sini:

Ada beberapa cara menghapus kolom.

Harus ada satu - dan lebih disukai hanya satu - cara yang jelas untuk melakukannya.

Kolom terkadang atribut tetapi terkadang tidak.

Kasus khusus tidak cukup istimewa untuk melanggar aturan.

Apakah del df.dtypesmenghapus atribut dtypes atau kolom dtypes?

Dalam menghadapi ambiguitas, tolak godaan untuk menebak.

firelynx
sumber
"Sebenarnya, __del__seharusnya hampir tidak pernah digunakan karena keadaan genting di mana ia dipanggil; gunakan dengan hati-hati!" sama sekali tidak relevan di sini, karena metode yang digunakan di sini adalah __delattr__.
pppery
1
@pperry Anda salah mengutip. itu adalah delbuiltin yang dimaksud, bukan .__del__metode instance. The delbuiltin adalah pemetaan untuk __delattr__dan __delitem__yang adalah apa yang saya membangun argumen saya. Jadi mungkin Anda ingin membaca kembali apa yang saya tulis.
firelynx
1
__... __diinterpretasikan sebagai markup tebal oleh StackExchange
pppery
2
"Jangan gunakan df.column_name, Ini mungkin cantik, tapi itu menyebabkan disonansi kognitif" Apa artinya ini? Saya bukan psikolog jadi saya harus mencari tahu apa maksud Anda. Juga, mengutip Zen tidak ada artinya karena ada ratusan cara yang sah untuk melakukan hal yang sama dalam panda.
cs95
58

Tambahan yang bagus adalah kemampuan untuk menjatuhkan kolom hanya jika ada . Dengan cara ini Anda dapat mencakup lebih banyak kasus penggunaan, dan itu hanya akan menjatuhkan kolom yang ada dari label yang diteruskan ke sana:

Cukup tambahkan kesalahan = 'abaikan' , misalnya .:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Ini baru dari panda 0.16.1 dan seterusnya. Dokumentasi ada di sini .
eiTan LaVi
sumber
41

dari versi 0.16.1 dapat Anda lakukan

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
sushmit
sumber
3
Dan ini juga mendukung menjatuhkan beberapa kolom, beberapa di antaranya tidak perlu ada (yaitu tanpa meningkatkan kesalahan errors= 'ignore') df.drop(['column_1','column_2'], axis=1 , inplace=True,errors= 'ignore'), jika aplikasi seperti itu diinginkan!
muon
31

Ini praktik yang baik untuk selalu menggunakan []notasi. Salah satu alasannya adalah bahwa notasi atribut ( df.column_name) tidak berfungsi untuk indeks bernomor:

In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]])

In [2]: df[1]
Out[2]:
0    2
1    5
Name: 1

In [3]: df.1
  File "<ipython-input-3-e4803c0d1066>", line 1
    df.1
       ^
SyntaxError: invalid syntax
Andy Hayden
sumber
26

Panda 0,21+ menjawab

Pandas versi 0.21 telah dropsedikit mengubah metode untuk memasukkan kedua parameter indexdan columnsuntuk mencocokkan tanda tangan renamedan reindexmetode.

df.drop(columns=['column_a', 'column_c'])

Secara pribadi, saya lebih suka menggunakan axisparameter untuk menunjukkan kolom atau indeks karena itu adalah parameter kata kunci utama yang digunakan di hampir semua metode panda. Tapi, sekarang Anda memiliki beberapa pilihan tambahan di versi 0.21.

Ted Petrou
sumber
1
df.drop (['column_a', 'column_c'], sumbu = 1) | itu bekerja untuk saya untuk saat ini
YouAreAwesome
21

Di panda 0.16.1+ Anda dapat menjatuhkan kolom hanya jika ada per solusi yang diposting oleh @eiTanLaVi. Sebelum versi itu, Anda dapat mencapai hasil yang sama melalui pemahaman daftar bersyarat:

df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], 
        axis=1, inplace=True)
Alexander
sumber
14

TL; DR

Banyak upaya untuk menemukan solusi yang sedikit lebih efisien. Sulit untuk membenarkan kerumitan yang ditambahkan sambil mengorbankan kesederhanaandf.drop(dlst, 1, errors='ignore')

df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)

Pembukaan
Menghapus kolom secara semantik sama dengan memilih kolom lainnya. Saya akan menunjukkan beberapa metode tambahan untuk dipertimbangkan.

Saya juga akan fokus pada solusi umum menghapus beberapa kolom sekaligus dan memungkinkan upaya untuk menghapus kolom yang tidak ada.

Menggunakan solusi ini bersifat umum dan akan berfungsi untuk kasus sederhana juga.


Pengaturan
Pertimbangkan pd.DataFrame dfdan daftar untuk dihapusdlst

df = pd.DataFrame(dict(zip('ABCDEFGHIJ', range(1, 11))), range(3))
dlst = list('HIJKLM')

df

   A  B  C  D  E  F  G  H  I   J
0  1  2  3  4  5  6  7  8  9  10
1  1  2  3  4  5  6  7  8  9  10
2  1  2  3  4  5  6  7  8  9  10

dlst

['H', 'I', 'J', 'K', 'L', 'M']

Hasilnya harus seperti:

df.drop(dlst, 1, errors='ignore')

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Karena saya menyamakan menghapus kolom untuk memilih kolom lainnya, saya akan memecahnya menjadi dua jenis:

  1. Pemilihan label
  2. Temukan Boolean

Pemilihan Label

Kita mulai dengan membuat daftar / array label yang mewakili kolom yang ingin kita pertahankan dan tanpa kolom yang ingin kita hapus.

  1. df.columns.difference(dlst)

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
  2. np.setdiff1d(df.columns.values, dlst)

    array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
  3. df.columns.drop(dlst, errors='ignore')

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
  4. list(set(df.columns.values.tolist()).difference(dlst))

    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
  5. [x for x in df.columns.values.tolist() if x not in dlst]

    ['A', 'B', 'C', 'D', 'E', 'F', 'G']

Kolom dari Label
Demi membandingkan proses seleksi, asumsikan:

 cols = [x for x in df.columns.values.tolist() if x not in dlst]

Maka kita bisa mengevaluasi

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. df.reindex_axis(cols, 1)

Yang semuanya dievaluasi untuk:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Boolean Slice

Kita dapat membuat array / daftar boolean untuk diiris

  1. ~df.columns.isin(dlst)
  2. ~np.in1d(df.columns.values, dlst)
  3. [x not in dlst for x in df.columns.values.tolist()]
  4. (df.columns.values[:, None] != dlst).all(1)

Kolom dari Boolean
Demi perbandingan

bools = [x not in dlst for x in df.columns.values.tolist()]
  1. df.loc[: bools]

Yang semuanya dievaluasi untuk:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Pengaturan waktu yang kuat

Fungsi

setdiff1d = lambda df, dlst: np.setdiff1d(df.columns.values, dlst)
difference = lambda df, dlst: df.columns.difference(dlst)
columndrop = lambda df, dlst: df.columns.drop(dlst, errors='ignore')
setdifflst = lambda df, dlst: list(set(df.columns.values.tolist()).difference(dlst))
comprehension = lambda df, dlst: [x for x in df.columns.values.tolist() if x not in dlst]

loc = lambda df, cols: df.loc[:, cols]
slc = lambda df, cols: df[cols]
ridx = lambda df, cols: df.reindex(columns=cols)
ridxa = lambda df, cols: df.reindex_axis(cols, 1)

isin = lambda df, dlst: ~df.columns.isin(dlst)
in1d = lambda df, dlst: ~np.in1d(df.columns.values, dlst)
comp = lambda df, dlst: [x not in dlst for x in df.columns.values.tolist()]
brod = lambda df, dlst: (df.columns.values[:, None] != dlst).all(1)

Pengujian

res1 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc slc ridx ridxa'.split(),
        'setdiff1d difference columndrop setdifflst comprehension'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res2 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc'.split(),
        'isin in1d comp brod'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res = res1.append(res2).sort_index()

dres = pd.Series(index=res.columns, name='drop')

for j in res.columns:
    dlst = list(range(j))
    cols = list(range(j // 2, j + j // 2))
    d = pd.DataFrame(1, range(10), cols)
    dres.at[j] = timeit('d.drop(dlst, 1, errors="ignore")', 'from __main__ import d, dlst', number=100)
    for s, l in res.index:
        stmt = '{}(d, {}(d, dlst))'.format(s, l)
        setp = 'from __main__ import d, dlst, {}, {}'.format(s, l)
        res.at[(s, l), j] = timeit(stmt, setp, number=100)

rs = res / dres

rs

                          10        30        100       300        1000
Select Label                                                           
loc    brod           0.747373  0.861979  0.891144  1.284235   3.872157
       columndrop     1.193983  1.292843  1.396841  1.484429   1.335733
       comp           0.802036  0.732326  1.149397  3.473283  25.565922
       comprehension  1.463503  1.568395  1.866441  4.421639  26.552276
       difference     1.413010  1.460863  1.587594  1.568571   1.569735
       in1d           0.818502  0.844374  0.994093  1.042360   1.076255
       isin           1.008874  0.879706  1.021712  1.001119   0.964327
       setdiff1d      1.352828  1.274061  1.483380  1.459986   1.466575
       setdifflst     1.233332  1.444521  1.714199  1.797241   1.876425
ridx   columndrop     0.903013  0.832814  0.949234  0.976366   0.982888
       comprehension  0.777445  0.827151  1.108028  3.473164  25.528879
       difference     1.086859  1.081396  1.293132  1.173044   1.237613
       setdiff1d      0.946009  0.873169  0.900185  0.908194   1.036124
       setdifflst     0.732964  0.823218  0.819748  0.990315   1.050910
ridxa  columndrop     0.835254  0.774701  0.907105  0.908006   0.932754
       comprehension  0.697749  0.762556  1.215225  3.510226  25.041832
       difference     1.055099  1.010208  1.122005  1.119575   1.383065
       setdiff1d      0.760716  0.725386  0.849949  0.879425   0.946460
       setdifflst     0.710008  0.668108  0.778060  0.871766   0.939537
slc    columndrop     1.268191  1.521264  2.646687  1.919423   1.981091
       comprehension  0.856893  0.870365  1.290730  3.564219  26.208937
       difference     1.470095  1.747211  2.886581  2.254690   2.050536
       setdiff1d      1.098427  1.133476  1.466029  2.045965   3.123452
       setdifflst     0.833700  0.846652  1.013061  1.110352   1.287831

fig, axes = plt.subplots(2, 2, figsize=(8, 6), sharey=True)
for i, (n, g) in enumerate([(n, g.xs(n)) for n, g in rs.groupby('Select')]):
    ax = axes[i // 2, i % 2]
    g.plot.bar(ax=ax, title=n)
    ax.legend_.remove()
fig.tight_layout()

Ini relatif terhadap waktu yang diperlukan untuk menjalankan df.drop(dlst, 1, errors='ignore'). Sepertinya setelah semua upaya itu, kami hanya meningkatkan kinerja secara sederhana.

masukkan deskripsi gambar di sini

Jika faktanya solusi terbaik gunakan reindexatau reindex_axisdi retas list(set(df.columns.values.tolist()).difference(dlst)). Yang kedua dekat dan masih sangat sedikit lebih baik dari dropitu np.setdiff1d.

rs.idxmin().pipe(
    lambda x: pd.DataFrame(
        dict(idx=x.values, val=rs.lookup(x.values, x.index)),
        x.index
    )
)

                      idx       val
10     (ridx, setdifflst)  0.653431
30    (ridxa, setdifflst)  0.746143
100   (ridxa, setdifflst)  0.816207
300    (ridx, setdifflst)  0.780157
1000  (ridxa, setdifflst)  0.861622
piRquared
sumber
2

Sintaks dot berfungsi dalam JavaScript, tetapi tidak dalam Python.

  • Python: del df['column_name']
  • JavaScript: del df['column_name'] atau del df.column_name
Dokter
sumber
2

Jika kerangka data asli Anda dftidak terlalu besar, Anda tidak memiliki kendala memori, dan Anda hanya perlu menyimpan beberapa kolom maka Anda mungkin juga membuat kerangka data baru dengan hanya kolom yang Anda butuhkan:

new_df = df[['spam', 'sausage']]
ccpizza
sumber
2

Kita dapat menghapus atau menghapus kolom yang ditentukan atau kolom yang ditandai dengan metode drop () .

Misalkan df adalah kerangka data.

Kolom yang akan dihapus = kolom0

Kode:

df = df.drop(column0, axis=1)

Untuk menghapus beberapa kolom, col1, col2,. . . , coln, kita harus memasukkan semua kolom yang perlu dihapus dalam daftar. Kemudian hapus dengan metode drop ().

Kode:

df = df.drop([col1, col2, . . . , coln], axis=1)

Saya harap ini akan membantu.

Littin Rajan
sumber
df = df.drop([col1, col2, . . . , coln], axis=1)ini tidak berfungsi jika saya menentukan nama variabel di tempat col1, col2 dll. Saya mendapatkan kolom kesalahan tidak dalam sumbu ketika pasti hadir. @Littin Bisakah Anda membantu?
RSM
1

Cara lain Menghapus Kolom di Pandas DataFrame

jika Anda tidak mencari penghapusan In-Place maka Anda dapat membuat DataFrame baru dengan menentukan kolom menggunakan DataFrame(...)fungsi sebagai

my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}

df = pd.DataFrame(my_dict)

Buat DataFrame baru sebagai

newdf = pd.DataFrame(df, columns=['name', 'age'])

Anda mendapatkan hasil sebagus apa yang Anda dapatkan dengan del / drop

Daksh
sumber
1
Secara teknis ini benar tetapi tampaknya konyol harus membuat daftar setiap kolom untuk disimpan, bukan hanya satu (atau beberapa) kolom yang ingin Anda hapus.
cs95