Een kolom verwijderen uit een Pandas DataFrame

Bij het verwijderen van een kolom in een DataFrame gebruik ik:

del df['column_name']

En dit werkt geweldig. Waarom kan ik het volgende niet gebruiken?

del df.column_name

Aangezien het mogelijk is om toegang te krijgen tot de kolom/Serie als df.column_name, verwachtte ik dat dit zou werken.


Antwoord 1, autoriteit 100%

Zoals je al geraden hebt, is de juiste syntaxis

del df['column_name']

Het is moeilijk om del df.column_name eenvoudig te laten werken als gevolg van syntactische beperkingen in Python. del df[name] wordt vertaald naar df.__delitem__(name) onder de dekens door Python.


Antwoord 2, autoriteit 227%

De beste manier om dit in Panda’s te doen, is door drop:

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

waarbij 1 het as-nummer is (0 voor rijen en 1 voor kolommen.)

Als u de kolom wilt verwijderen zonder df opnieuw toe te wijzen, kunt u het volgende doen:

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

Ten slotte, om per kolom nummer te plaatsen in plaats van per kolom label, probeer dit te verwijderen, b.v. de 1e, 2e en 4e kolom:

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

Ook werken met "tekst" syntaxis voor de kolommen:

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

Opmerking: geïntroduceerd in v0.21.0 (27 oktober 2017), accepteert de methode drop() index-/kolomsleutelwoorden als alternatief voor het specificeren van de as.

Dus we kunnen nu gewoon doen:

df = df.drop(columns=['column_nameA', 'column_nameB'])

Antwoord 3, autoriteit 24%

Gebruik:

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

Hiermee worden een of meer kolommen op hun plaats verwijderd. Merk op dat inplace=True is toegevoegd in pandas v0.13 en niet werkt op oudere versies. In dat geval moet u het resultaat opnieuw toewijzen:

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

Antwoord 4, autoriteit 11%

Naar index

Eerste, tweede en vierde kolom verwijderen:

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

Eerste kolom verwijderen:

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

Er is een optionele parameter inplace zodat de originele
gegevens kunnen worden gewijzigd zonder een kopie te maken.

Geknald

Kolomselectie, toevoeging, verwijdering

Kolom column-name verwijderen:

df.pop('column-name')

Voorbeelden:

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

Antwoord 5, autoriteit 7%

De eigenlijke vraag die hier wordt gesteld, gemist door de meeste antwoorden, is:

Waarom kan ik del df.column_name niet gebruiken?

Eerst moeten we het probleem begrijpen, waarvoor we ons moeten verdiepen in Python-magiemethoden.

Zoals Wes aangeeft in zijn antwoord , del df['column'] verwijst naar de Python magische methode df.__delitem__('column') die geïmplementeerd in Panda’s om de kolom weg te laten.

Echter, zoals aangegeven in de bovenstaande link over Python-magiemethoden:

In feite zou __del__ bijna nooit moeten worden gebruikt vanwege de precaire omstandigheden waaronder het wordt aangeroepen; gebruik het met de nodige voorzichtigheid!

Je zou kunnen stellen dat del df['column_name'] niet mag worden gebruikt of aangemoedigd, en dat daarom del df.column_name niet eens in overweging moet worden genomen.

In theorie zou del df.column_name echter kunnen worden geïmplementeerd om in Panda’s te werken met behulp van de magische methode __delattr__. Dit introduceert echter bepaalde problemen, problemen die de del df['column_name'] implementatie al heeft, maar in mindere mate.

Voorbeeld probleem

Wat als ik een kolom definieer in een dataframe met de naam "dtypes" of “kolommen”?

Ga er dan vanuit dat ik deze kolommen wil verwijderen.

del df.dtypes zou de __delattr__ methode verwarrend maken alsof het de "dtypes" attribuut of de "dtypes" kolom.

Architecturale vragen achter dit probleem

  1. Is een dataframe een verzameling kolommen?
  2. Is een dataframe een verzameling van rijen?
  3. Is een kolom een ​​attribuut van een dataframe?

Panda’s antwoorden:

  1. Ja, in alle opzichten
  2. Nee, maar als je dat wilt, kun je de methoden .ix, .loc of .iloc gebruiken.
  3. li>

  4. Misschien wilt u gegevens lezen? Dan ja, tenzij de naam van het attribuut al is ingenomen door een ander attribuut dat bij het dataframe hoort. Wilt u gegevens wijzigen? Dan nee.

TLDR;

Je kunt del df.column_name niet doen, omdat Pandas een behoorlijk wild gegroeide architectuur heeft die heroverwogen moet worden om te voorkomen dat dit soort cognitieve dissonantie optreedt. zijn gebruikers.

Pro-tip:

Gebruik df.column_name niet. Het is misschien mooi, maar het veroorzaakt cognitieve dissonantie.

Zen van Python-citaten die hier passen:

Er zijn meerdere manieren om een ​​kolom te verwijderen.

Er zou één – en bij voorkeur maar één – voor de hand liggende manier moeten zijn om het te doen.

Kolommen zijn soms attributen, maar soms ook niet.

Speciale gevallen zijn niet speciaal genoeg om de regels te overtreden.

Verwijdert del df.dtypes het kenmerk dtypes of de kolom dtypes?

Weiger bij onduidelijkheid de verleiding om te raden.


Antwoord 6, autoriteit 6%

Een leuke toevoeging is de mogelijkheid om kolommen alleen te verwijderen als ze bestaan. Op deze manier kun je meer gebruiksscenario’s dekken en worden alleen de bestaande kolommen verwijderd van de labels die eraan zijn doorgegeven:

Voeg eenvoudig errors=’ignore’ toe, bijvoorbeeld.:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Dit is nieuw vanaf panda’s 0.16.1. Documentatie is hier.

Antwoord 7, autoriteit 4%

Vanaf versie 0.16.1 kunt u dit doen

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

Antwoord 8, autoriteit 3%

Het is een goede gewoonte om altijd de notatie [] te gebruiken. Een reden is dat attribuutnotatie (df.column_name) niet werkt voor genummerde indices:

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

Antwoord 9, autoriteit 2%

Panda’s 0.21+ antwoord

Pandas versie 0.21 heeft de drop-methode iets om zowel de parameters index als columns op te nemen om overeen te komen met de handtekening van de rename en reindex methoden.

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

Persoonlijk gebruik ik liever de parameter axis om kolommen of indexen aan te duiden, omdat dit de belangrijkste sleutelwoordparameter is die in bijna alle panda-methoden wordt gebruikt. Maar nu heb je wat extra keuzes in versie 0.21.


Antwoord 10, autoriteit 2%

In Pandas 0.16.1+ kunt u alleen kolommen verwijderen als ze bestaan ​​per de oplossing gepost door eiTan LaVi. Voorafgaand aan die versie kunt u hetzelfde resultaat bereiken via een conditioneel lijstbegrip:

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

Antwoord 11, autoriteit 2%

Gebruik:

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

Anders kun je mee gaan

del df['colname']

Meerdere kolommen verwijderen op basis van kolomnummers

df.drop(df.iloc[:,1:3], axis = 1, inplace = True)

Meerdere kolommen verwijderen op basis van kolomnamen

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

Antwoord 12

TL;DR

Veel moeite om een ​​iets efficiëntere oplossing te vinden. Moeilijk om de toegevoegde complexiteit te rechtvaardigen terwijl de eenvoud van df.drop(dlst, 1, errors='ignore')

wordt opgeofferd

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

Preambule
Het verwijderen van een kolom is semantisch hetzelfde als het selecteren van de andere kolommen. Ik zal een paar extra methoden laten zien om te overwegen.

Ik zal me ook concentreren op de algemene oplossing om meerdere kolommen tegelijk te verwijderen en de poging om kolommen die niet aanwezig zijn toe te staan.

Het gebruik van deze oplossingen is algemeen en werkt ook voor het eenvoudige geval.


Instellen
Overweeg het pd.DataFrame df en de lijst om dlst

te verwijderen

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

Het resultaat zou er als volgt uit moeten zien:

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

Omdat ik het verwijderen van een kolom gelijkstel aan het selecteren van de andere kolommen, verdeel ik het in twee typen:

  1. Labelselectie
  2. Booleaanse selectie

Labelselectie

We beginnen met het maken van de lijst/array van labels die de kolommen vertegenwoordigen die we willen behouden en zonder de kolommen die we willen verwijderen.

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

Kolommen van labels
Neem om het selectieproces te vergelijken:

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

Dan kunnen we evalueren

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

Die allemaal leiden tot:

   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

Booleaans segment

We kunnen een array/lijst met booleans maken om te slicen

  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)

Kolommen van Boolean
Ter vergelijking

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

Die allemaal leiden tot:

   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

Robuuste timing

Functies

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)

Testen

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

Dit is relatief ten opzichte van de tijd die nodig is om df.drop(dlst, 1, errors='ignore') uit te voeren. Het lijkt erop dat we na al die moeite de prestaties slechts bescheiden verbeteren.

voer hier de afbeeldingsbeschrijving in

In feite gebruiken de beste oplossingen reindex of reindex_axis op de hack list(set(df.columns.values.tolist()).difference(dlst)). Een goede tweede en nog steeds zeer marginaal beter dan drop is 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

Antwoord 13

We kunnen een opgegeven kolom of opgegeven kolommen verwijderen of verwijderen met de methode drop().

Stel dat df een dataframe is.

Kolom die moet worden verwijderd = kolom0

Code:

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

Om meerdere kolommen col1, col2, . . . , coln, we moeten alle kolommen die verwijderd moesten worden in een lijst invoegen. Verwijder ze vervolgens met de drop()-methode.

Code:

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

Antwoord 14

Als uw originele dataframe df niet te groot is, heeft u geen geheugenbeperkingen en hoeft u maar een paar kolommen te behouden, of, als u dat niet doet ken vooraf de namen van alle extra kolommen die je niet nodig hebt, dan kun je net zo goed een nieuw dataframe maken met alleen de kolommen die je nodig hebt:

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

Antwoord 15

De puntsyntaxis werkt in JavaScript, maar niet in Python.

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

Antwoord 16

Een kolom verwijderen met de functie iloc van dataframe en slicing, wanneer we een typische kolomnaam hebben met ongewenste waarden:

df = df.iloc[:,1:] # Removing an unnamed index column

Hier is 0 de standaardrij en 1 is de eerste kolom, vandaar dat :,1: onze parameter is voor het verwijderen van de eerste kolom .


Antwoord 17

Een andere manier om een ​​kolom in een Pandas DataFrame te verwijderen

Als u niet op zoek bent naar in-place verwijdering, kunt u een nieuw DataFrame maken door de kolommen op te geven met de functie DataFrame(...) als:

my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}
df = pd.DataFrame(my_dict)

Maak een nieuw DataFrame als

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

Je krijgt een resultaat dat net zo goed is als wat je krijgt met del / drop.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

2 × five =

Other episodes