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
- Is een dataframe een verzameling kolommen?
- Is een dataframe een verzameling van rijen?
- Is een kolom een attribuut van een dataframe?
Panda’s antwoorden:
- Ja, in alle opzichten
- Nee, maar als je dat wilt, kun je de methoden
.ix
,.loc
of.iloc
gebruiken. - 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.
li>
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:
- Labelselectie
- 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.
-
df.columns.difference(dlst)
Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
-
np.setdiff1d(df.columns.values, dlst)
array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
-
df.columns.drop(dlst, errors='ignore')
Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
-
list(set(df.columns.values.tolist()).difference(dlst))
# does not preserve order ['E', 'D', 'B', 'F', 'G', 'A', 'C']
-
[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
df.loc[:, cols]
df[cols]
df.reindex(columns=cols)
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
~df.columns.isin(dlst)
~np.in1d(df.columns.values, dlst)
[x not in dlst for x in df.columns.values.tolist()]
(df.columns.values[:, None] != dlst).all(1)
Kolommen van Boolean
Ter vergelijking
bools = [x not in dlst for x in df.columns.values.tolist()]
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.
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']
ofdel 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.