Pandas Dataframe,更简单的语法可以按值的条件删除行

new*_*ost 3 python performance filtering dataframe pandas

考虑一个 Pandas 数据框,例如:

df = pd.DataFrame([[0,2],[1,0],[7,99]],index=[3,4,8], columns = ["R1","R2"])
Run Code Online (Sandbox Code Playgroud)

给予:

   R1  R2
3   0   2
4   1   0
8   7  99
Run Code Online (Sandbox Code Playgroud)

当我想通过某个值的条件删除一行时,我要么使用

df = df.drop(df[df["R1"] == 1].index)
Run Code Online (Sandbox Code Playgroud)

或者

df = df.drop(df.index[np.where(df["R1"] == 1)[0]])
Run Code Online (Sandbox Code Playgroud)

或者

df = df.drop(df.loc[df['R1'] == 1].index)
Run Code Online (Sandbox Code Playgroud)

两个都超级麻烦。您知道实现此目的的更简单的语法吗?

例如,如果有类似 idrop 函数的东西,第二个选项会更易读:

df = df.idrop(np.where(df["R1"] == 1)[0])
Run Code Online (Sandbox Code Playgroud)

编辑:

我原以为这比df = df[df['R1'] != 1]仅仅删除一行的性能要低。(庞大的数据库...)

jez*_*ael 7

不,布尔索引更快drop,如果需要提高性能,请使用numexpr

在此处输入图片说明

import perfplot, numexpr

def bi1(df):
    return df[df['R1'].values != 1]

def bi2(df):
    return df[df['R1'] != 1]

def drop1(df):
    return df.drop(df[df["R1"] == 1].index)

def drop2(df):
    return df.drop(df.index[df["R1"] == 1])

def drop3(df):
    return df.drop(df.loc[df['R1'] == 1].index)

def drop4(df):
    return df.drop(np.where(df["R1"] == 1)[0])


def ne(x):
    x = x['R1'].values
    return x[numexpr.evaluate('(x != 1)')]

def q(x):
    return x.query('R1 != 1')

def ev(x):
    return x[x.eval('R1 != 1')]


def make_df(n):
    df = pd.DataFrame({'R1':np.random.randint(100, size=n)})
    return df
Run Code Online (Sandbox Code Playgroud)
perfplot.show(
    setup=make_df,
    kernels=[bi1, bi2,drop1,drop2,drop3,drop4,ne,q,ev],
    n_range=[2**k for k in range(2, 25)],
    logx=True,
    logy=True,
    equality_check=False,
    xlabel='len(df)')
Run Code Online (Sandbox Code Playgroud)