删除 DataFrame 中的列时,我使用:
del df['column_name']
这很好用。为什么我不能使用以下内容?
del df.column_name
由于可以将列/系列访问为df.column_name
,因此我希望这可以工作。
在 Pandas 中执行此操作的最佳方法是使用drop
:
df = df.drop('column_name', 1)
其中1
是轴号(0
对于行和1
列。)
要删除列而无需重新分配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
还使用列的“文本”语法:
df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)
注意:在v0.21.0(2017 年 10 月 27 日)中引入,drop() 方法接受索引/列关键字作为指定轴的替代方法。
所以我们现在可以这样做:
df = df.drop(columns=['column_nameA', 'column_nameB'])
如您所料,正确的语法是
del df['column_name']
del df.column_name
由于 Python 中的语法限制,很难简单地完成工作。被Pythondel df[name]
翻译成秘密。df.__delitem__(name)
采用:
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
,可以在不创建副本的情况下修改原始数据。
删除列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 魔术方法。
正如韦斯在他的回答中指出的那样,映射到在 Pandas中实现del df['column']
的 Python魔术方法 以删除列。df.__delitem__('column')
但是,正如上面关于Python 魔术方法的链接中指出的那样:
事实上,
__del__
几乎从不应该使用它,因为它被称为不稳定的环境;谨慎使用!
您可以争辩del df['column_name']
说不应该使用或鼓励,因此del df.column_name
甚至不应该考虑。
但是,理论上,del df.column_name
可以使用魔法方法在 Pandas 中实现__delattr__
。然而,这确实引入了某些问题,del df['column_name']
实施过程中已经存在的问题,但程度较轻。
如果我在名为“dtypes”或“columns”的数据框中定义一个列怎么办?
然后假设我想删除这些列。
del df.dtypes
会使__delattr__
方法混淆,就好像它应该删除“dtypes”属性或“dtypes”列一样。
.ix
,.loc
或.iloc
方法。你不能这样做del df.column_name
,因为 Pandas 的架构非常广泛,需要重新考虑,以使其用户不会出现这种认知失调。
不要使用 df.column_name。它可能很漂亮,但它会导致认知失调。
有多种删除列的方法。
应该有一种——最好只有一种——明显的方法来做到这一点。
列有时是属性,但有时不是。
特殊情况不足以打破规则。
是否del df.dtypes
删除 dtypes 属性或 dtypes 列?
面对模棱两可,拒绝猜测的诱惑。
一个不错的附加功能是仅当列存在时才删除它们。这样你可以覆盖更多的用例,它只会从传递给它的标签中删除现有的列:
只需添加errors='ignore',例如:
df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
从 0.16.1 版本开始,您可以执行
df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
始终使用该[]
符号是一个好习惯。一个原因是属性表示法 ( 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
Pandas 0.21 版对该drop
方法进行了轻微更改,以包含index
andcolumns
参数以匹配rename
andreindex
方法的签名。
df.drop(columns=['column_a', 'column_c'])
就个人而言,我更喜欢使用axis
参数来表示列或索引,因为它是几乎所有 pandas 方法中使用的主要关键字参数。但是,现在您在 0.21 版中多了一些选择。
在 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)
采用:
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)
为找到一个稍微更有效的解决方案付出了很多努力。很难在牺牲简单性的同时证明增加的复杂性是合理的df.drop(dlst, 1, errors='ignore')
df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)
序言
删除一列在语义上与选择其他列相同。我将展示一些额外的方法来考虑。
我还将重点介绍一次删除多个列并允许尝试删除不存在的列的一般解决方案。
使用这些解决方案是通用的,也适用于简单的情况。
设置
考虑pd.DataFrame
df
要删除的和列表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 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']
结果应如下所示:
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
由于我将删除一列等同于选择其他列,因此我将其分为两种类型:
我们首先制造标签列表/数组,这些标签代表我们要保留的列,而没有我们要删除的列。
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']
来自标签
的列 为了比较选择过程,假设:
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 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
我们可以构造一个用于切片的布尔数组/列表
~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]
全部评估为:
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
稳健的时序
职能
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 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')
。似乎经过所有努力,我们只能适度提高性能。
如果事实上最好的解决方案使用reindex
或reindex_axis
在 hack 上list(set(df.columns.values.tolist()).difference(dlst))
。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
我们可以通过drop()方法删除或删除指定列或指定列。
假设df是一个数据框。
要删除的列 = column0
代码:
df = df.drop(column0, axis=1)
要删除多列 col1、col2、. . . , coln, 我们必须在列表中插入所有需要删除的列。然后通过 drop() 方法删除它们。
代码:
df = df.drop([col1, col2, . . . , coln], axis=1)
如果您的原始数据框df
不是太大,您没有内存限制,并且您只需要保留几列,或者,如果您事先不知道您不需要的所有额外列的名称,那么您可能以及创建一个仅包含您需要的列的新数据框:
new_df = df[['spam', 'sausage']]
当我们有一个带有不需要值的典型列名时,使用和的iloc
函数删除列:dataframe
slicing
df = df.iloc[:,1:] # Removing an unnamed index column
这0
是默认行并且1
是第一列,因此:,1:
是我们删除第一列的参数。
点语法在 JavaScript 中有效,但在 Python 中无效。
del df['column_name']
del df['column_name']
或 del df.column_name
在 Pandas 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 获得的结果一样好。
要删除特定列之前和之后的列,您可以使用truncate方法。例如:
A B C D E
0 1 10 100 1000 10000
1 2 20 200 2000 20000
df.truncate(before='B', after='D', axis=1)
输出:
B C D
0 10 100 1000
1 20 200 2000
从一般 Python 的角度来看, 如果可以删除del obj.column_name
该属性是有意义的。column_name
它必须是常规属性 - 或具有已定义删除器的属性。
这不能转化为 Pandas 并且对 Pandas Dataframes没有意义的原因是:
df.column_name
是一个“虚拟属性”,它本身不是一个东西,它不是那个列的“座位”,它只是一种访问列的方式。很像没有删除器的属性。