df.drop 如果存在

ZJA*_*JAY 44 python pandas

下面是一个函数,它接受一个文件并删除列名“row_num”、“start_date”、“end_date”。

问题是不是每个文件都有这些列名,所以函数返回一个错误。

我的目标是更改代码,以便在这些列存在时删除这些列,但如果该列不存在则不返回错误。

def read_df(file):
    df = pd.read_csv(file, na_values=['', ' '])
    # Drop useless junk and fill empty values with zero 
    df = df.drop(['row_num','start_date','end_date','symbol'], axis=1).fillna(0)
    df=df[df!=0][:-1].dropna().append(df.iloc[-1])
    return df
Run Code Online (Sandbox Code Playgroud)

jez*_*ael 102

将参数添加errorsDataFrame.drop

错误:{'ignore', 'raise'},默认为 'raise'

如果为“忽略”,则抑制错误并仅删除现有标签。

df = df.drop(['row_num','start_date','end_date','symbol'], axis=1, errors='ignore')
Run Code Online (Sandbox Code Playgroud)

样品

df = pd.DataFrame({'row_num':[1,2], 'w':[3,4]})
df = df.drop(['row_num','start_date','end_date','symbol'], axis=1, errors='ignore')
print (df)
   w
0  3
1  4
Run Code Online (Sandbox Code Playgroud)


Tim*_*art 31

只需使用 Pandas Filter,Pythonic 方式

奇怪的是,没有答案使用pandas数据框filter method

thisFilter = df.filter(drop_list)
df.drop(thisFilter, inplace=True, axis=1)
Run Code Online (Sandbox Code Playgroud)

drop_list这将从中创建一个过滤器df,然后thisFilterdf inplace中删除axis=1

即,删除与 匹配的列drop_list,如果它们不存在也不会出错


tdy*_*tdy 11

用于df.columns.intersection速度

df.columns.intersection是排除缺失列的内置方法:

existing_cols = df.columns.intersection(["foo", "bar", "baz"])
df = df.drop(columns=existing_cols)
Run Code Online (Sandbox Code Playgroud)

即使缺失列的数量不断增加,删除 via 的速度df.columns.intersection非常快:

时序图

计时数据:

df = pd.DataFrame(np.random.random((10_000, 200)), columns=range(-200, 0))
cols = range(-100, n)  # 100 dropped columns, n missing columns
Run Code Online (Sandbox Code Playgroud)


amq*_*ack 6

在我的测试中,以下内容至少与任何给定答案一样快:

candidates=['row_num','start_date','end_date','symbol']
df = df.drop([x for x in candidates if x in df.columns], axis=1)
Run Code Online (Sandbox Code Playgroud)

它具有可读性的优点,并且(通过对代码进行小幅调整)能够准确记录哪些列在何时存在/被删除。

这可能比以前的解决方案更可取的一些原因:

  • 循环遍历项目并单独删除每列(如果存在)是有效的,但速度很慢(请参阅下面的基准测试)。
  • jezrael 的回答非常好,但一开始让我很紧张(忽略错误感觉很糟糕!)。进一步查看文档使它听起来好像没问题,并且只是忽略不存在的列的错误(不是其他可能不希望忽略的错误)。我的解决方案可能更具可读性,尤其是对于那些不太熟悉 Pandas 中可选 kwargs 的人。

基准测试结果:

![基准结果

基准测试代码(归功于此问题中有关如何创建此类基准的答案):

import math
from simple_benchmark import benchmark
import pandas as pd

# setting up the toy df:
def df_creator(length):
    c1=list(range(0,10))
    c2=list('a,b,c,d,e'.split(','))
    c3=list(range(0,5))
    c4=[True,False]
    lists=[c1,c2,c3,c4]
    df=pd.DataFrame()
    count=0
    for x in lists:
        count+=1
        df['col'+str(count)]=x*math.floor(length/len(x))
    return df

# setting up benchmark test:
def list_comp(df,candidates=['col1','col2','col5','col8']):
    return df.drop([x for x in candidates if x in df.columns], axis=1)

def looper(df,candidates=['col1','col2','col5','col8']):
    for col in candidates:
        if col in df.columns:
            out = df.drop(columns=col, axis=1)
    return out

def ignore_error(df,candidates=['col1','col2','col5','col8']):
    return df.drop(candidates, axis=1, errors='ignore')

functions=[list_comp,looper,ignore_error]

args={n : df_creator(n) for n in [10,100,1000,10000,100000]}
argname='df_length'
b=benchmark(functions,args,argname)
b.plot()
Run Code Online (Sandbox Code Playgroud)