关于python:如何从Pandas数据框中删除行列表?

How to drop a list of rows from Pandas dataframe?

我有一个数据帧df:

1
2
3
4
5
6
7
8
9
>>> 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],,然后向左:

1
2
3
4
5
                  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

如何或什么功能可以做到这一点?


使用dataframe.drop并传递一系列索引标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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


请注意,当您要执行放置行时,使用"inplace"命令可能很重要。

1
df.drop(df.index[[1,3]], inplace=True)

因为原始问题没有返回任何内容,所以应该使用此命令。http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.dataframe.drop.html


您还可以传递到dataframe.drop标签本身(而不是一系列索引标签):

1
2
3
4
5
6
7
8
9
10
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

相当于:

1
2
3
4
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[])进行简单的删除会花费太多时间。

在我的例子中,我有一个带有100M rows x 3 cols的多索引浮点数据帧,我需要从中删除10k行。我发现最快的方法是,相当反直觉地,对take其余的行。

indexes_to_drop作为要删除的位置索引数组(问题中的[1, 2, 4])。

1
2
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,消耗了大量的内存。生成的数据帧是相同的。


我用一种简单的方法解决了这个问题——只需两步。

步骤1:首先用不需要的行/数据形成一个数据帧。

步骤2:使用此不需要的数据帧的索引从原始数据帧中删除行。

例子:

假设您有一个数据帧df,它包含许多列,其中"age"是一个整数。现在假设您要删除所有"年龄"为负数的行。

步骤1:df_age_negative=df[df[‘age’]<0]

第二步:df=df.drop(df_age_negative.index,axis=0)

希望这简单多了,对你有帮助。


如果我要删除一行,比如索引x,我将执行以下操作:

1
df = df[df.index != x]

如果我想删除多个指数(假设这些指数在unwanted_indices列表中),我会这样做:

1
2
desired_indices = [i for i in len(df.index) if i not in unwanted_indices]
desired_df = df.iloc[desired_indices]


下面是一个有点具体的例子,我想展示一下。假设在某些行中有许多重复条目。如果您有字符串条目,可以很容易地使用字符串方法查找要删除的所有索引。

1
ind_drop = df[df['column_of_strings'].apply(lambda x: x.startswith('Keyword'))].index

现在使用索引删除这些行

1
new_df = df.drop(ind_drop)

在对@theodros zelleke答案的评论中,@j-jones询问了如果索引不唯一该怎么做。我不得不应付这种情况。我所做的是在调用drop(),一个la:

1
2
3
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是以前发生过的次数。


根据上述布尔值确定索引,例如

1
df[df['column'].isin(values)].index

可能比使用此方法确定索引更占用内存

1
pd.Index(np.where(df['column'].isin(values))[0])

像这样应用

1
df.drop(pd.Index(np.where(df['column'].isin(values))[0]), inplace = True)

这种方法在处理大型数据帧和有限内存时很有用。