如何从 Pandas 数据框中删除行列表?
Posted
技术标签:
【中文标题】如何从 Pandas 数据框中删除行列表?【英文标题】:How to drop a list of rows from Pandas dataframe? 【发布时间】:2013-01-17 16:11:23 【问题描述】:我有一个数据框 df :
>>> df
sales discount net_sales cogs
STK_ID RPT_Date
600141 20060331 2.709 NaN 2.709 2.245
20060630 6.590 NaN 6.590 5.291
20060930 10.103 NaN 10.103 7.981
20061231 15.915 NaN 15.915 12.686
20070331 3.196 NaN 3.196 2.710
20070630 7.907 NaN 7.907 6.459
然后我想删除列表中指示的具有某些序列号的行,假设这里是[1,2,4],
然后离开:
sales discount net_sales cogs
STK_ID RPT_Date
600141 20060331 2.709 NaN 2.709 2.245
20061231 15.915 NaN 15.915 12.686
20070630 7.907 NaN 7.907 6.459
如何或什么功能可以做到这一点?
【问题讨论】:
只是澄清一下,这个问题是关于删除具有特定索引值的行。他们使用 [1,2,4] 是指向 left over 之后的行下降。下面有答案。 【参考方案1】:正如Dennis Golomazov's answer 建议的那样,使用drop
删除行。您可以选择保留行。假设您有一个名为indices_to_drop
的要删除的行索引列表。您可以将其转换为掩码,如下所示:
mask = np.ones(len(df), bool)
mask[indices_to_drop] = False
你可以直接使用这个索引:
df_new = df.iloc[mask]
这种方法的好处是mask
可以来自任何来源:它可以是涉及许多列的条件,或其他。
真正的好处是,你根本不需要原始 DataFrame 的索引,所以索引是否唯一无关紧要。
缺点当然是不能用这种方法就地放置。
【讨论】:
【参考方案2】:要删除索引为 1、2、4 的行,您可以使用:
df[~df.index.isin([1, 2, 4])]
波浪号运算符~
否定isin
方法的结果。另一种选择是删除索引:
df.loc[df.index.drop([1, 2, 4])]
【讨论】:
【参考方案3】:看下面的数据框df
df
column1 column2 column3
0 1 11 21
1 2 12 22
2 3 13 23
3 4 14 24
4 5 15 25
5 6 16 26
6 7 17 27
7 8 18 28
8 9 19 29
9 10 20 30
让我们删除 column1 中所有奇数的行
创建column1中所有元素的列表,并只保留那些偶数元素(你不想删除的元素)
keep_elements = [x for x in df.column1 if x%2==0]
column1 中值为[2, 4, 6, 8, 10]
的所有行都将被保留或不被删除。
df.set_index('column1',inplace = True)
df.drop(df.index.difference(keep_elements),axis=0,inplace=True)
df.reset_index(inplace=True)
我们将 column1 作为索引并删除所有不需要的行。然后我们重新设置索引。
df
column1 column2 column3
0 2 12 22
1 4 14 24
2 6 16 26
3 8 18 28
4 10 20 30
【讨论】:
【参考方案4】:我以更简单的方式解决了这个问题 - 只需 2 个步骤。
用不需要的行/数据制作一个数据框。
使用此不需要的数据帧的索引从原始数据帧中删除行。
示例: 假设您有一个数据框 df ,其中包含许多列,其中包括整数“年龄”。现在假设您要删除所有以“年龄”为负数的行。
df_age_negative = df[ df['Age'] < 0 ] # Step 1
df = df.drop(df_age_negative.index, axis=0) # Step 2
希望这更简单,对您有所帮助。
【讨论】:
+1,这是告诉您如何删除选择与第一列不同的列的行的唯一答案。 这是我正在寻找的答案。谢谢 Krishnaprasad garu【参考方案5】:考虑一个示例数据框
df =
index column1
0 00
1 10
2 20
3 30
我们想要删除第 2 和第 3 个索引行。
方法一:
df = df.drop(df.index[2,3])
or
df.drop(df.index[2,3],inplace=True)
print(df)
df =
index column1
0 00
3 30
#This approach removes the rows as we wanted but the index remains unordered
方法 2
df.drop(df.index[2,3],inplace=True,ignore_index=True)
print(df)
df =
index column1
0 00
1 30
#This approach removes the rows as we wanted and resets the index.
【讨论】:
【参考方案6】:仅使用索引 arg 删除行:-
df.drop(index = 2, inplace = True)
对于多行:-
df.drop(index=[1,3], inplace = True)
【讨论】:
【参考方案7】:这里有一个具体的例子,我想展示一下。假设您的某些行中有许多重复条目。如果您有字符串条目,您可以轻松地使用字符串方法来查找要删除的所有索引。
ind_drop = df[df['column_of_strings'].apply(lambda x: x.startswith('Keyword'))].index
现在使用它们的索引删除这些行
new_df = df.drop(ind_drop)
【讨论】:
【参考方案8】:如上所述从布尔值确定索引,例如
df[df['column'].isin(values)].index
可能比使用此方法确定索引更占用内存
pd.Index(np.where(df['column'].isin(values))[0])
这样申请
df.drop(pd.Index(np.where(df['column'].isin(values))[0]), inplace = True)
此方法在处理大型数据帧和有限内存时很有用。
【讨论】:
【参考方案9】:如果我想删除索引为x
的行,我会执行以下操作:
df = df[df.index != x]
如果我想删除多个索引(假设这些索引在列表 unwanted_indices
中),我会这样做:
desired_indices = [i for i in len(df.index) if i not in unwanted_indices]
desired_df = df.iloc[desired_indices]
【讨论】:
这符合我的要求,谢谢!删除除索引 X 以外的所有行。 df = df[df.index == 'x']【参考方案10】:您也可以将标签本身(而不是索引标签系列)传递给DataFrame.drop:
In[17]: df
Out[17]:
a b c d e
one 0.456558 -2.536432 0.216279 -1.305855 -0.121635
two -1.015127 -0.445133 1.867681 2.179392 0.518801
In[18]: df.drop('one')
Out[18]:
a b c d e
two -1.015127 -0.445133 1.867681 2.179392 0.518801
相当于:
In[19]: df.drop(df.index[[0]])
Out[19]:
a b c d e
two -1.015127 -0.445133 1.867681 2.179392 0.518801
【讨论】:
df.drop(df.index[0]) 也可以。我的意思是,不需要双 square_brackets(至少使用 pandas 0.18.1)【参考方案11】:如果 DataFrame 很大,并且要删除的行数也很大,那么简单的按索引删除 df.drop(df.index[])
会花费太多时间。
就我而言,我有一个带有100M rows x 3 cols
的浮点数的多索引DataFrame,我需要从中删除10k
行。我发现的最快的方法是,非常违反直觉,take
剩余的行。
让indexes_to_drop
成为要删除的位置索引数组(问题中的[1, 2, 4]
)。
indexes_to_keep = set(range(df.shape[0])) - set(indexes_to_drop)
df_sliced = df.take(list(indexes_to_keep))
在我的情况下,这占用了20.5s
,而简单的df.drop
占用了5min 27s
并消耗了大量内存。生成的 DataFrame 是一样的。
【讨论】:
仅仅否定一个掩码而不是创建一个集合不是更便宜吗?m = np.ones(len(df), bool); m[indices_to_drop] = False
之类的东西?【参考方案12】:
在对@theodros-zelleke 的回答的评论中,@j-jones 询问了如果索引不是唯一的该怎么办。我不得不处理这样的情况。我所做的是在调用drop()
之前重命名索引中的重复项,唉:
dropped_indexes = <determine-indexes-to-drop>
df.index = rename_duplicates(df.index)
df.drop(df.index[dropped_indexes], inplace=True)
rename_duplicates()
是我定义的一个函数,它遍历索引的元素并重命名重复项。我使用了与pd.read_csv()
在列上使用的相同重命名模式,即"%s.%d" % (name, count)
,其中name
是行的名称,count
是它之前出现的次数。
【讨论】:
【参考方案13】:请注意,当您想要进行插入时,使用“inplace”命令可能很重要。
df.drop(df.index[[1,3]], inplace=True)
因为您的原始问题没有返回任何内容,所以应该使用此命令。 http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.drop.html
【讨论】:
【参考方案14】:使用DataFrame.drop 并传递一系列索引标签:
In [65]: df
Out[65]:
one two
one 1 4
two 2 3
three 3 2
four 4 1
In [66]: df.drop(df.index[[1,3]])
Out[66]:
one two
one 1 4
three 3 2
【讨论】:
+1 另外,删除最后一行 df.drop(df.tail(1).index) 此答案仅在 df.index.unique() 与 df.index 相同时才有效,这不是 Pandas DataFrame 的要求。当 df.index 值不能保证是唯一的时,有人有解决方案吗? 这不允许您对索引名称本身进行索引 伙计们,在例子中,如果你想清楚,请不要对行和列使用相同的字符串。对于那些真正了解自己的东西的人来说,这很好。让那些试图学习的人感到沮丧。 python 新手:请注意,如果您想删除这些行并将它们保存在同一个数据框中(就地),您还需要添加axis=0
(0 = 行,1 = 列)和inplace=True
与 df.drop(df.index[[1,3]], axis=0, inplace=True)
相同。 @mezzanaccio,如果您特别知道要替换哪些索引(并且还使用您的 0 到 n 示例):df.drop(df.index[range(0, n)], axis=0, inplace=True)
以上是关于如何从 Pandas 数据框中删除行列表?的主要内容,如果未能解决你的问题,请参考以下文章
Python Pandas:如何从包含列表中值的数据框中删除所有列?