使用python del从pandas DataFrame中删除列
当删除DataFrame中的一列时,我使用:
del df['column_name']
这工作很好。 为什么我不能使用:
del df.column_name
正如你可以访问列/系列作为df.column_name
,我期望这个工作。
由于Python中的语法限制,很难使del df.column_name
正常工作。 del df[name]
被Python翻译为df.__delitem__(name)
在pandas做这个最好的方法是使用drop :
df = df.drop('column_name', 1)
其中1
是轴号( 0
表示行, 1
表示列)。
要删除列而不必重新分配df
你可以这样做:
df.drop('column_name', axis=1, inplace=True)
最后,要按列号而不是列标签来删除,例如第一列,第二列和第四列:
df.drop(df.columns[[0, 1, 3]], axis=1) # df.columns is zero-based pd.Index
columns = ['Col1', 'Col2', ...] df.drop(columns, inplace=True, axis=1)
这将在原地删除一列或多列。 请注意, inplace=True
是在pandas v0.13中添加的,不适用于旧版本,那么在这种情况下您是否必须重新分配结果:
df = df.drop(columns, axis=1)
按指数下降
删除第一,第二和第四列:
df.drop(df.columns[[0,1,3]], axis=1, inplace=True)
删除第一列:
df.drop(df.columns[[0]], axis=1, inplace=True)
有一个可选参数inplace
以便原始数据可以被修改而不创build一个副本。
膨化
列select,添加,删除
删除列的column-name
:
df.pop('column-name')
例子:
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
提出的实际问题,在这里大部分答案错过了:
为什么我不能使用del df.column_name
?
首先,我们需要了解这个问题,这就要求我们深入研究python的魔法方法 。
正如Wes在他的回答del df['column']
指出的那样,映射到python 魔术方法 df.__delitem__('column')
,这是在pandas中实现的,
不过,正如上面关于python魔术方法的链接所指出的那样:
事实上,由于所谓的岌岌可危的情况, del应该几乎不会被使用。 谨慎使用它!
你可能会争辩说del df['column_name']
不应该被使用或鼓励,因此del df.column_name
甚至不应该被考虑。
然而,从理论上讲, del df.column_name
可以使用magic方法__delattr__
来实现在pandas中工作。 然而,这却引入了某些问题, del df['column_name']
实现已经存在的问题,但程度较低。
示例问题
如果我在一个名为“dtypes”或“columns”的数据框中定义一个列,该怎么办?
然后假设我想删除这些列。
del df.dtypes
会使__delattr__
方法混淆,就像它应该删除“dtypes”属性或“dtypes”列一样。
这个问题背后的build筑问题
- 数据框是一列的集合吗?
- 数据框是行的集合吗?
- 列是数据框的属性吗?
pandas答案:
- 是的,在所有方面
- 不,但如果你想要的话,你可以使用
.ix
,.loc
或.iloc
方法。 - 也许,你想读取数据? 那么是的 , 除非属性的名称已经被属于该dataframe的另一个属性占用。 你想修改数据吗? 那么没有 。
TLDR;
你不能做del df.column_name
因为pandas有一个相当疯狂的架构,需要重新考虑,以避免这种认知失调发生在用户del df.column_name
。
普罗蒂普:
不要使用df.column_name,它可能很漂亮,但会导致认知失调
Python的引号适合在这里:
有多种删除列的方法。
应该有一个 – 最好只有一个 – 明显的方法来做到这一点。
列有时是属性,但有时不是。
特例不足以打破规则。
del df.dtypes
是否删除dtypes属性或dtypes列?
面对歧义,拒绝猜测的诱惑。
从版本0.16.1你可以做
df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
一个不错的添加就是只有在存在的情况下才能删除列 ,这样就可以覆盖更多的用例,并且只会删除传递给它的标签中的现有列:
只需添加错误=“忽略” ,例如:
df.drop(['col_name_1','col_name_2',...,'col_name_N'],inplace=True,axis=1,errors='ignore')
- 这是从pandas0.16.1新,文档在这里
总是使用[]
表示法是一个好习惯,一个原因是属性表示法( df.column_name
)不适用于编号索引:
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
在pandas0.16.1+中,只有在每个由@eiTanLaVi发布的解决scheme存在的情况下,才能删除列。 在该版本之前,您可以通过有条件的列表理解达到相同的结果:
df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], axis=1, inplace=True)
你应该使用drop() 。 假设你的数据框名称是df 。
#for dropping single column df = df.drop('your_column', axis=1) #for dropping multiple columns df = df.drop(['col_1','col_2','col_3'], axis=1)
TL; DR
很多努力find一个边缘更有效的解决scheme。 牺牲df.drop(dlst, 1, errors='ignore')
的简单性df.drop(dlst, 1, errors='ignore')
难以certificate增加的复杂性
df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)
前言
删除列在语义上与select其他列相同。 我将展示一些其他的方法来考虑。
我还将专注于一次删除多个列的一般解决scheme,并允许尝试删除不存在的列。
使用这些解决scheme是一般的,并且也适用于简单的情况。
build立
考虑使用pd.DataFrame
df
和list来删除dlst
df = pd.DataFrame(dict(zip('ABCDEFGHIJ', range(1, 11))), range(3)) dlst = list('HIJKLM')
df ABCDEFGHIJ 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']
结果应该如下所示:
df.drop(dlst, 1, errors='ignore') ABCDEFG 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7
由于我相当于删除一列到select其他列,我将它分成两种types:
- 标签select
- 布尔select
标签select
我们首先制造代表我们想要保留的列的标签的列表/数组,并且没有我们想要删除的列。
-
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']
标签中的列
为了比较select过程,假定:
cols = [x for x in df.columns.values.tolist() if x not in dlst]
然后我们可以评估
-
df.loc[:, cols]
-
df[cols]
-
df.reindex(columns=cols)
-
df.reindex_axis(cols, 1)
这全部评估为:
ABCDEFG 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7
布尔切片
我们可以构build一个用于切片的布尔值数组/列表
-
~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)
来自布尔的列
为了比较
bools = [x not in dlst for x in df.columns.values.tolist()]
-
df.loc[: bools]
这全部评估为:
ABCDEFG 0 1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 1 2 3 4 5 6 7
强健的时机
function
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)
testing
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()
这是相对于运行df.drop(dlst, 1, errors='ignore')
花费的时间。 看起来毕竟这样的努力,我们只是谦虚地提高业绩。
如果事实上最好的解决scheme使用reindex_axis
list(set(df.columns.values.tolist()).difference(dlst))
上的reindex
或reindex_axis
list(set(df.columns.values.tolist()).difference(dlst))
。 接近第二,仍然非常好,比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
点语法工作在JS中,但不是在Python中 。
Python :del df ['column_name']
JS :del df ['column_name'] OR del df.column_name
pandas0.21+答案
Pandas 0.21版本稍微改变了drop方法,以包括index
和columns
参数,以匹配rename
和reindex
方法的签名。
df.drop(columns=['column_a', 'column_c'])
就个人而言,我更喜欢使用axis
参数来表示列或索引,因为它几乎是所有pandas方法中使用的主要关键字参数。 但是,现在在版本0.21中有一些额外的select。
您也可以先将colum的所有值设置为NaN,然后使用dropna()下一次删除NaN值
df["column"]=np.NaN df.dropna(axis=1,inplace=True)