要删除DataFrame中的列,我可以成功使用:
del df['column_name']
为什么我不能使用下面的?
del df.column_name
由于可以将列/系列作为df.column_name访问,我希望这可以工作。
df.column_name
始终使用[]表示法是一种很好的做法。一个原因是属性表示法(df.column_name)不适用于编号索引:
[]
In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]]) In [2]: df[1]Out[2]:0 21 5Name: 1 In [3]: df.1File "<ipython-input-3-e4803c0d1066>", line 1df.1^SyntaxError: invalid syntax
正如你所猜到的,正确的语法是
由于Python中的语法限制,很难使del df.column_name工作。del df[name]在Python的掩护下被翻译成df.__delitem__(name)。
del df[name]
df.__delitem__(name)
在Pandas中做到这一点的最佳方法是使用#0:
df = df.drop('column_name', axis=1)
其中1是轴的数字(0表示行,1表示列)。
1
0
要删除列而无需重新分配df,您可以执行以下操作:
df
df.drop('column_name', axis=1, inplace=True)
最后,要删除第数量列而不是第标签列,请尝试删除,例如第1、第2和第4列:
df = df.drop(df.columns[[0, 1, 3]], axis=1) # df.columns is zero-based pd.Index
还使用列的“text”语法:
df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)
备注:在v0.21.0(2017年10月27日)中引入,drop()方法接受索引/列关键字作为指定轴的替代方法。
drop()
所以我们现在可以做:
df = df.drop(columns=['column_nameA', 'column_nameB'])
用途:
columns = ['Col1', 'Col2', ...]df.drop(columns, inplace=True, axis=1)
这将在原地删除一个或多个列。请注意,inplace=True是在熊猫v0.13中添加的,在旧版本上不起作用。在这种情况下,您必须将结果分配回:
inplace=True
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,以便原始可以在不创建副本的情况下修改数据。
inplace
列选择、添加、删除
删除列column-name:
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:
print df
one two threeA 1 2 3B 4 5 6C 7 8 9
df.drop(df.columns[[0]], axis=1, inplace=True)print df:
two threeA 2 3B 5 6C 8 9
three = df.pop('three')print df:
three = df.pop('three')
twoA 2B 5C 8
一个很好的补充是仅删除存在的列的能力。这样你就可以覆盖更多的用例,它只会从传递给它的标签中删除现有列:
简单地添加错误='忽略',例如:
df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
在Pandas 0.16.1+中,您只能删除每个由eiTan LaVi发布的解决方案中存在的列。在该版本之前,您可以通过条件列表理解获得相同的结果:
df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df],axis=1, inplace=True)
点语法在JavaScript中有效,但在Python中无效。
从0.16.1版本开始,您可以
df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
提出的实际问题,这里的大多数答案都错过了:
首先,我们需要了解这个问题,这需要我们深入研究Python魔法方法。
正如他的答案中的韦斯指出,del df['column']映射到Python魔术方法df.__delitem__('column'),即在Pandas中实现以删除列。
del df['column']
df.__delitem__('column')
然而,正如上面关于Python魔法方法的链接所指出的:
事实上,__del__几乎不应该被使用,因为它被调用的情况不稳定;谨慎使用!
__del__
你可以争辩说del df['column_name']不应该被使用或鼓励,因此del df.column_name甚至不应该被考虑。
然而,从理论上讲,del df.column_name可以在使用魔法方法#1的Pandas中实现。然而,这确实引入了某些问题,del df['column_name']实现已经存在的问题,但程度较小。
如果我在数据框中定义一个名为“dtype”或“列”的列怎么办?
然后假设我想删除这些列。
del df.dtypes会使__delattr__方法感到困惑,就好像它应该删除“dtype”属性或“dtype”列一样。
del df.dtypes
__delattr__
.ix
.loc
.iloc
你不能做del df.column_name,因为Pandas有一个非常疯狂增长的架构,需要重新考虑,以便这种认知失调不会发生在它的用户身上。
不要使用df.column_name。它可能很漂亮,但它会导致认知失调。
有多种方法可以删除列。
应该有一种——最好只有一种——显而易见的方法来做到这一点。
列有时是属性,但有时不是。
特殊情况不足以打破规则。
del df.dtypes是否删除dtype属性或dtype列?
面对模棱两可,拒绝猜测的诱惑。
为了找到一个稍微更有效的解决方案付出了很多努力。很难在牺牲df.drop(dlst, 1, errors='ignore')的简单性的同时证明增加的复杂性是合理的
df.drop(dlst, 1, errors='ignore')
df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)
序言删除列在语义上与选择其他列相同。我将展示一些需要考虑的其他方法。
我还将重点介绍一次删除多个列并允许尝试删除不存在的列的一般解决方案。
使用这些解决方案是通用的,也适用于简单的情况。
设置考虑pd.DataFramedf和要删除的列表dlst
pd.DataFrame
dlst
df = pd.DataFrame(dict(zip('ABCDEFGHIJ', range(1, 11))), range(3))dlst = list('HIJKLM')
df A B C D E F G H I J0 1 2 3 4 5 6 7 8 9 101 1 2 3 4 5 6 7 8 9 102 1 2 3 4 5 6 7 8 9 10
dlst ['H', 'I', 'J', 'K', 'L', 'M']
结果应如下所示:
df.drop(dlst, 1, errors='ignore') A B C D E F G0 1 2 3 4 5 6 71 1 2 3 4 5 6 72 1 2 3 4 5 6 7
由于我将删除一列等同于选择其他列,因此我将其分为两种类型:
我们首先制造标签列表/数组,这些标签代表我们要保留的列,而不代表我们要删除的列。
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')
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']
标签中的列为了比较选择过程,假设:
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)
它们都评估为:
A B C D E F G0 1 2 3 4 5 6 71 1 2 3 4 5 6 72 1 2 3 4 5 6 7
我们可以构造一个用于切片的布尔值数组/列表
~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)
来自Boolean的列为了便于比较
bools = [x not in dlst for x in df.columns.values.tolist()]
df.loc[: bools]
稳健时序
函数
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)
测试
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 1000Select Labelloc brod 0.747373 0.861979 0.891144 1.284235 3.872157columndrop 1.193983 1.292843 1.396841 1.484429 1.335733comp 0.802036 0.732326 1.149397 3.473283 25.565922comprehension 1.463503 1.568395 1.866441 4.421639 26.552276difference 1.413010 1.460863 1.587594 1.568571 1.569735in1d 0.818502 0.844374 0.994093 1.042360 1.076255isin 1.008874 0.879706 1.021712 1.001119 0.964327setdiff1d 1.352828 1.274061 1.483380 1.459986 1.466575setdifflst 1.233332 1.444521 1.714199 1.797241 1.876425ridx columndrop 0.903013 0.832814 0.949234 0.976366 0.982888comprehension 0.777445 0.827151 1.108028 3.473164 25.528879difference 1.086859 1.081396 1.293132 1.173044 1.237613setdiff1d 0.946009 0.873169 0.900185 0.908194 1.036124setdifflst 0.732964 0.823218 0.819748 0.990315 1.050910ridxa columndrop 0.835254 0.774701 0.907105 0.908006 0.932754comprehension 0.697749 0.762556 1.215225 3.510226 25.041832difference 1.055099 1.010208 1.122005 1.119575 1.383065setdiff1d 0.760716 0.725386 0.849949 0.879425 0.946460setdifflst 0.710008 0.668108 0.778060 0.871766 0.939537slc columndrop 1.268191 1.521264 2.646687 1.919423 1.981091comprehension 0.856893 0.870365 1.290730 3.564219 26.208937difference 1.470095 1.747211 2.886581 2.254690 2.050536setdiff1d 1.098427 1.133476 1.466029 2.045965 3.123452setdifflst 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')所需的时间而言的。似乎经过所有这些努力,我们只是适度地提高了性能。
如果事实上最好的解决方案在黑客list(set(df.columns.values.tolist()).difference(dlst))上使用reindex或reindex_axis。紧随其后,仍然比drop好一点的是np.setdiff1d。
reindex
reindex_axis
drop
np.setdiff1d
rs.idxmin().pipe(lambda x: pd.DataFrame(dict(idx=x.values, val=rs.lookup(x.values, x.index)),x.index)) idx val10 (ridx, setdifflst) 0.65343130 (ridxa, setdifflst) 0.746143100 (ridxa, setdifflst) 0.816207300 (ridx, setdifflst) 0.7801571000 (ridxa, setdifflst) 0.861622
Pandas 0.21版稍微改变了#0方法,包括index和columns参数,以匹配rename和reindex方法的签名。
index
columns
rename
df.drop(columns=['column_a', 'column_c'])
就个人而言,我更喜欢使用axis参数来表示列或索引,因为它是几乎所有熊猫方法中使用的主要关键字参数。但是,现在您在0.21版中增加了一些选择。
axis
在Pandas DataFrame中删除列的另一种方法
如果您不是在寻找就地删除,那么您可以通过使用DataFrame(...)函数指定列来创建一个新的DataFrame:
DataFrame(...)
my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']} df = pd.DataFrame(my_dict)
创建一个新的DataFrame作为
newdf = pd.DataFrame(df, columns=['name', 'age'])
你得到的结果和你用del/drop得到的一样好。
如果你原来的dataframe#0不是太大,你没有内存限制,你只需要保留几列,或者,如果你事先不知道你不需要的所有额外列的名称,那么你不妨创建一个新的dataframe,只包含你需要的列:
new_df = df[['spam', 'sausage']]
我们可以通过drop()方法删除或删除指定列或指定列。
假设df是一个数据帧。
要删除的列=列0
代码:
df = df.drop(column0, axis=1)
要删除多列col1、col2, . . . , Lincoln,我们必须将所有需要删除的列插入列表中。然后通过drop()方法删除它们。
df = df.drop([col1, col2, . . . , coln], axis=1)
df.drop('columnname', axis =1, inplace = True)
或者你也可以一起去
del df['colname']
根据列号删除多列
df.drop(df.iloc[:,1:3], axis = 1, inplace = True)
根据列名删除多个列
df.drop(['col1','col2',..'coln'], axis = 1, inplace = True)
当我们有一个带有不需要的值的典型列名时,使用dataframe和slicing的iloc函数删除列:
dataframe
slicing
iloc
df = df.iloc[:,1:] # Removing an unnamed index column
这里0是默认行,1是第一列,因此:,1:是删除第一列的参数。
:,1:
要删除特定列之前和之后的列,您可以使用方法截断。例如:
A B C D E0 1 10 100 1000 100001 2 20 200 2000 20000 df.truncate(before='B', after='D', axis=1)
输出:
B C D0 10 100 10001 20 200 2000
从一般Python的角度来看,如果可以删除属性column_name,则del obj.column_name是有意义的。它需要是一个常规属性-或者具有定义的删除器的属性。
column_name
del obj.column_name
这不能转化为Pandas的原因,以及没有对Pandas Dataframes有意义的原因是:
通过使用自动完成或“IntelliSense”而不是字符串文字来利用:
del df[df.column1.name] # or df.drop(df.column1.name, axis=1, inplace=True)
它适用于当前的Pandas版本。