Panda DataFrame'den sütun sil


1328

Ben DataFrame bir sütun silerken kullanıyorum:

del df['column_name']

Ve bu harika çalışıyor. Aşağıdakileri neden kullanamıyorum?

del df.column_name

/ Serisine sütun olarak erişmek mümkün olduğundan df.column_name, bunun çalışmasını bekledim.


2
Üzerinde görüşülmekte olan bu soruyu Not Meta .
RM

Yanıtlar:


858

Tahmin ettiğiniz gibi, doğru sözdizimi

del df['column_name']

del df.column_namePython'daki sözdizimsel sınırlamaların bir sonucu olarak çalışmak zor . Python tarafından örtü altına del df[name]çevrilir df.__delitem__(name).


25
Bunun çok eski bir "cevap" olduğunu fark ettim, ama merakım hafifledi - bu neden Python'un sözdizimsel bir kısıtlaması? class A(object): def __init__(self): self.var = 1bir sınıf kurar, sonra iyi a = A(); del a.varçalışır ...
dwanderson

13
@dwanderson farkı, bir sütun kaldırıldığında, DataFrame'in "nasıl yapılır" için kendi işleyişine sahip olması gerektiğidir. Durumunda del df[name], bu için tercüme df.__delitem__(name)DataFrame uygulamak ve ihtiyaçlarına değiştirebileceğiniz bir yöntemdir ki. Durumunda, del df.nameüye değişkeni herhangi bir özel kod çalıştırma şansı olmadan kaldırılır. Kendi örneğinizi düşünün - del a.var"değişkenin silinmesi" baskısına neden olabilir misiniz ? Yapabilirsen, lütfen bana nasıl olduğunu söyle. Yapamam :)
Yonatan


5
@Yonatan Eugene'nin yorumu Python 2 için de geçerlidir; tanımlayıcılar 2.2'den beri Python 2'de bulunmaktadır ve gereksiniminizi karşılamak önemsizdir;)
CS

1
Bu cevap gerçekten doğru değil - pandasgeliştiriciler yapmadı , ancak bu yapmanın zor olduğu anlamına gelmiyor.
wizzwizz4

2184

Pandalarda bunu yapmanın en iyi yolu kullanmaktır drop:

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

burada 1bir eksen numarası ( 0satır ve 1sütunlar için).

Yeniden atamak zorunda kalmadan sütunu silmek için dfşunları yapabilirsiniz:

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

Son olarak, sütun etiketi yerine sütun numarasına göre bırakmak için, örneğin 1., 2. ve 4. sütunları silmeyi deneyin:

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

Ayrıca sütunlar için "metin" sözdizimi ile çalışma:

df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)

79
Bu delbir nedenle öneriliyor mu?
beardc

20
Bu silme yönteminin yararları olsa da, bu cevap sorulan soruya gerçekten cevap vermiyor.
Paul

109
True @Paul, ancak sorunun başlığı nedeniyle, buraya gelen çoğu kişi bunu bir sütunun nasıl silineceğini çözmeye çalışarak yapacak.
LondonRob

24
@beardc bir başka avantajı dropüzerinde delolduğunu drop(özellikle 3-boyutlu bir matrisin için faydalı veya herhangi bir eksen boyunca işlem INPLACE ya da değil, aynı zamanda silme kayıtları, bir kerede çok sayıda sütun damla gerçekleştirmek için olanak sağlar Panel)
ocak

8
Bir diğer avantajı dropüzerinde delolmasıdır damla pandalar API parçasıdır ve belgeler içerir.
Modüller

241

kullanın:

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

Bu, bir veya daha fazla sütunu yerinde siler. Not inplace=Truepandalar eklendi v0.13 ve daha eski sürümlerinde çalışma olmaz. Bu durumda sonucu yeniden atamanız gerekir:

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

3
Bu cevap hakkında bir not: Eğer bir 'liste' kullanılıyorsa, köşeli parantezler düşürülmelidir:df.drop(list,inplace=True,axis=1)
edesz

1
bu gerçekten kabul edilen cevap olmalı, çünkü bu yöntemin üstünlüğünü açıkça ortaya koyuyor del- aynı anda birden fazla sütunu düşürebilir.
dbliss

111

Dizine göre bırak

Birinci, ikinci ve dördüncü sütunları silin:

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

İlk sütunu sil:

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

inplaceOrijinal verilerin bir kopya oluşturmadan değiştirilebilmesi için isteğe bağlı bir parametre vardır .

attı

Sütun seçimi, toplama, silme

Sütunu sil column-name:

df.pop('column-name')

Örnekler:

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

1
Pandalarda nasıl bir sıra patlatabilirim?
Kennet Celeste

2
@Yugi Bunun için aktarılmış bir veri çerçevesi kullanabilirsiniz. eski - df.T.pop('A')
Saat Köle

@ClockSlave Orijinali değiştirmez df. Sen olabilir yapmak df = df.T; df.pop(index); df = df.Tama bu aşırı görünüyor.
cs95

Bunun yerine df.drop(df.columns[[0]], axis=1, inplace=True)kullanmak yeterli olmaz df.drop([0], axis=1)mı?
Anirban Mukherjee

1
@Anirban Mukherjee Değişir. Sütun adını silmek istiyorsanız 0, o zaman df.drop(0, axis=1)iyi çalışıyor. Ancak sütun adını bilmiyorsanız ve sonra ilk sütunu kaldırmanız gerekiyorsa df.drop(df.columns[[0]], axis=1, inplace=True), ilk sütunu konuma göre seçin ve bırakın.
jezrael

71

Burada cevaplanan çoğu soru tarafından cevaplanan asıl soru:

Neden kullanamıyorum del df.column_name?

İlk önce python büyülü yöntemlerine dalmamızı gerektiren sorunu anlamamız gerekiyor .

Wes işaret ettiği gibi onun cevabı içinde del df['column']piton eşleştiren sihirli yöntemine df.__delitem__('column') olan sütun bırakın pandalar uygulanan

Bununla birlikte, yukarıdaki bağlantıda python magic yöntemleri hakkında belirtildiği gibi :

Aslında, __del__adı verilen tehlikeli koşullar nedeniyle neredeyse hiç kullanılmamalıdır; dikkatli kullanın!

Bunun del df['column_name']kullanılmaması veya teşvik del df.column_nameedilmemesi gerektiğini ve bu nedenle bile dikkate alınmaması gerektiğini iddia edebilirsiniz .

Ancak, teoride, del df.column_name sihirli yöntem kullanılarak pandalarda çalışmak için uygulanabilir__delattr__ . Ancak bu, bazı problemleri, del df['column_name']uygulamanın halihazırda sahip olduğu sorunları , ancak daha az derecede ortaya çıkarır.

Örnek Problem

Bir veri çerçevesinde "dtypes" veya "column" adlı bir sütun tanımlarsam ne olur?

Sonra bu sütunları silmek istediğimi varsayalım.

del df.dtypes yapacak __delattr__ yöntem "dtypes" özelliğini veya "dtypes" sütunu silmek gerekir sanki karıştı.

Bu sorunun arkasındaki mimari sorular

  1. Bir veri çerçevesi sütun mu?
  2. Bir veri çerçevesi satır mu?
  3. Sütun bir özelliktir midir?

Pandalar cevaplar:

  1. Evet, her bakımdan
  2. Hayır, ancak olmasını istiyorsanız .ix, .locveya.iloc yöntemlerini kullanabilirsiniz.
  3. Belki de verileri okumak ister misiniz ? Sonra evet , sürece özelliğin adı zaten dataframe ait başka özelliğiyle alınır. Verileri değiştirmek istiyor musunuz ? Sonra hayır .

TLDR;

Sen yapamaz del df.column_namepandalar ihtiyaçlar bu tür sırayla tekrar değerlendirilmesini ki oldukça çılgınca büyümüş bir mimariye sahiptir, çünkü bilişsel uyumsuzluğa kullanıcılarına oluşmaya değil.

PROTIP:

Df.column_name kullanmayın, güzel olabilir, ancak neden olur bilişsel uyumsuzluğa

Buraya uyan Python'dan alıntılar:

Bir sütunu silmenin birden çok yolu vardır.

Bunu yapmanın tek ve tercihen tek bir yolu olmalı.

Sütunlar bazen niteliktir, bazen de değildir.

Özel durumlar kuralları ihlal edecek kadar özel değildir.

Does del df.dtypesdtypes Özellik veya dtypes sütun silmek?

Belirsizlik karşısında, tahmin etme isteğini reddet.


"Aslında, __del__adı verilen tehlikeli koşullar nedeniyle neredeyse hiç kullanılmamalıdır; dikkatli kullanın!" burada kullanılan yöntem olduğu gibi, burada tamamen önemsizdir __delattr__.
pppery

1
@ppperry özledim-alıntı yapıyorsun. öyle delkastedilmektedir yerleşik değil, .__del__örnek yöntemi. delBuiltin için haritasını çıkarıyor __delattr__ve __delitem__ayağımda argüman inşa ediyorum budur. Belki de yazdıklarımı tekrar okumak istersiniz.
firelynx

1
__... __StackExchange
pppery

2
"Df.column_name kullanmayın, Güzel olabilir, ama bilişsel uyumsuzluğa neden olur" Bu ne anlama geliyor? Ben bir psikolog değilim, ne demek istediğini anlamak için buna bakmalıyım. Ayrıca, Zen'den alıntı yapmak anlamsızdır, çünkü pandalarda aynı şeyi yapmanın yüzlerce geçerli yolu vardır.
cs95

58

İyi bir ekleme, sütunları yalnızca varsa bırakma yeteneğidir . Bu şekilde daha fazla kullanım senaryosunu kapsayabilirsiniz ve mevcut sütunları yalnızca kendisine iletilen etiketlerden bırakır:

Basitçe hataları ekleyin = 'yoksay' , örneğin:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Bu panda 0.16.1'den itibaren yeni. Belgeler burada .

41

0.16.1 sürümünden yapabilirsiniz

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')

3
Ve bu da , böyle bir uygulama istenirse , bazılarının var olması gerekmeyen (yani hata yaratmadan errors= 'ignore') birden fazla sütunun bırakılmasını destekler df.drop(['column_1','column_2'], axis=1 , inplace=True,errors= 'ignore')!
muon

31

[]Notasyonu her zaman kullanmak iyi bir uygulamadır . Bunun bir nedeni, notation ( df.column_name) özelliğinin numaralandırılmış dizinlerde çalışmamasıdır:

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

26

Pandalar 0.21+ cevap

Pandalar sürüm 0.21, ve yöntemlerinin imzasına uyacak şekilde drophem indexve columnsparametrelerini içerecek şekilde yöntemi biraz değiştirmiştir .renamereindex

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

Şahsen, axisneredeyse tüm panda yöntemlerinde kullanılan baskın anahtar kelime parametresi olduğu için sütunları veya dizini belirtmek için parametreyi kullanmayı tercih ederim . Ancak, şimdi 0.21 sürümünde bazı ek seçenekler var.


1
df.drop (['sütun_a', 'sütun_c'], eksen = 1) | şimdilik benim için çalışıyor
YouAreAwesome

21

Pandalar 0.16.1 ve sonraki sürümlerinde sütunları yalnızca @eiTanLaVi tarafından gönderilen çözüm uyarınca varsa bırakabilirsiniz. Bu sürümden önce, bir koşullu liste kavrayışı ile aynı sonucu elde edebilirsiniz:

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

14

TL; DR

Marjinal olarak daha verimli bir çözüm bulmak için çok çaba. Basitliği feda ederken, eklenen karmaşıklığı haklı çıkarmak zordf.drop(dlst, 1, errors='ignore')

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

Önsöz
Bir sütunun silinmesi anlamsal olarak diğer sütunları seçmekle aynıdır. Dikkate alınması gereken birkaç ek yöntem daha göstereceğim.

Aynı anda birden fazla sütunu silme ve mevcut olmayan sütunları silme girişimine izin verme genel çözümüne de odaklanacağım.

Bu çözümleri kullanmak geneldir ve basit durumlar için de işe yarayacaktır.


Kurulum Silinecek ve listeyi
düşününpd.DataFrame dfdlst

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

Sonuç şöyle görünmelidir:

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

Bir sütunu diğer sütunları seçmek için sildiğim için, onu iki türe ayırırım:

  1. Etiket seçimi
  2. Boole seçimi

Etiket Seçimi

Saklamak istediğimiz sütunları temsil eden ve silmek istediğimiz sütunlar olmadan etiket listesini / etiket dizisini üreterek başlıyoruz.

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

Etiketlerden Sütunlar
Seçim sürecini karşılaştırmak için:

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

Sonra değerlendirebiliriz

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

Tüm bunlar aşağıdakileri değerlendirir:

   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

Boole Dilimi

Dilimleme için bir dizi / booleans listesi oluşturabiliriz

  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)

Boolean sütunlar
kıyaslamalar için

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

Tüm bunlar aşağıdakileri değerlendirir:

   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

Sağlam Zamanlama

Fonksiyonlar

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)

Test yapmak

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

Bu, çalıştırmak için geçen süreye göredir df.drop(dlst, 1, errors='ignore'). Tüm bu çabalardan sonra, performansı sadece mütevazı bir şekilde geliştiriyoruz gibi görünüyor.

resim açıklamasını buraya girin

Aslında en iyi çözümler reindexveya reindex_axiskesmek üzerinde kullanın list(set(df.columns.values.tolist()).difference(dlst)). Yakın bir ikinci ve hala çok marjinal daha iyi dropolduğunu 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

2

Nokta sözdizimi JavaScript'te çalışır, ancak Python'da çalışmaz.

  • Python: del df['column_name']
  • JavaScript: del df['column_name'] veya del df.column_name

2

Orijinal veri çerçeveniz dfçok büyük değilse, bellek sınırlamanız yoktur ve yalnızca birkaç sütun tutmanız gerekir, yalnızca ihtiyacınız olan sütunlarla yeni bir veri çerçevesi de oluşturabilirsiniz:

new_df = df[['spam', 'sausage']]

2

Biz yapabilirsiniz kaldırın veya silme belirtilen bir sütun ya da sprcified sütunları damla () yöntemiyle.

Varsayalım df bir dataframe olduğunu.

Kaldırılacak sütun = sütun0

Kod:

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

Birden çok sütunu kaldırmak için col1, col2,. . . , coln, kaldırılması gereken tüm sütunları bir listeye eklememiz gerekiyor. Ardından drop () yöntemiyle kaldırın.

Kod:

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

Umarım faydalı olur.


df = df.drop([col1, col2, . . . , coln], axis=1)Eğer col1, col2 vb yerine bir değişken adı belirtirseniz bu çalışmaz. Kesinlikle mevcut olduğunda ekseninde değil hata sütunu olsun. @Littin Yardımcı olabilir misiniz?
RSM

1

Panda DataFrame'de bir Sütunu Silmenin başka bir yolu

Yerinde silme aramıyorsanız, DataFrame(...)işlevi aşağıdaki gibi kullanarak sütunları belirterek yeni bir DataFrame oluşturabilirsiniz

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

df = pd.DataFrame(my_dict)

Yeni bir DataFrame oluştur

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

Del / drop ile elde ettiğiniz kadar iyi bir sonuç elde edersiniz


1
Bu teknik olarak doğrudur, ancak silmek istediğiniz bir (veya birkaç) sütun yerine saklamak için her sütunu listelemek aptalca görünmektedir.
cs95
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.