首页 > 解决方案 > 以最快的方式从数据框中删除值

问题描述

我有一个超过 500 万行的数据框。我还有一个要从数据框中删除的值列表。假设我的列表名称是a,我的数据框名称是df。下面是我用来检查 item ina是否存在于的代码df,然后将其从中删除df

 if len(a) > 0:
       for i in tqdm(a):
             indexName = df[ df['id'] == i ].index
             df.drop(indexName , inplace=True)

上面的代码需要 5 分钟。虽然它有效,但我很确定有一种更有效的方法。如果您有任何想法,请分享!

标签: pythonpython-3.xpandas

解决方案


for循环调用df.drop多次,效率不高。您可以使用Series.isin.

考虑:

values_to_delete = [5, 6, 7]
df = pd.DataFrame({'a': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})
df.drop(df[df['a'].isin(values_to_delete)].index, inplace=True)
print(df)

输出

    a
0   1
1   2
2   3
3   4
7   8
8   9
9  10

适应您的代码:

df.drop(df[df['id'].isin(tqdm(a))].index , inplace=True)


更快的替代方案

(见下面的时间)

可以为您想要的值过滤数据框,而不是删除您不想要的值:

df = df[~df['id'].isin(tqdm(a))]  # note the ~ which acts as NOT operator

计时

from timeit import Timer
import numpy as np

values_to_delete = [5, 6, 7]

def create_df():
    return pd.DataFrame({'a': np.random.randint(1, 10, 500000)})

def drop_loop():
    df = create_df()
    for i in values_to_delete:
        indexName = df[df['a'] == i].index
        df.drop(indexName, inplace=True)

def drop_single_call():
    df = create_df()
    df.drop(df[df['a'].isin(values_to_delete)].index, inplace=True)

def filtering():
    df = create_df()
    df[~df['a'].isin(values_to_delete)]


print(min(Timer(drop_loop).repeat(5, 5)))
print(min(Timer(drop_single_call).repeat(5, 5)))
print(min(Timer(filtering).repeat(5, 5)))

输出

1.0248285
0.5842238000000002
0.24234719999999932

(基本上)对于具有 500,000 行的示例数据帧,每种方法(OP、单次调用和过滤的丢弃)尝试 5 次。过滤方法通常快 75%。


推荐阅读