pandas 删除列表中包含的数据框行(不使用循环)

aurhwmvo  于 2023-09-29  发布在  其他
关注(0)|答案(5)|浏览(101)

问题说明

我有一个数据框,其中有两列'A''B'。我还有一个元组列表,其中元组的第一个元素是列'A'中的元素,第二个元素是列'B'中的元素。我想删除所有行的dataframe符合元组。
当然,我可以只使用循环,但我想要一个更聪明的解决方案,更快,更干净。

最小工作示例

import pandas as pd
df = pd.DataFrame(
    {
        'A': ['a', 'b', 'c', 'd', 'a', 'd', 'a', 'c'],
        'B': [4, 2, 2, 1, 3, 4, 3, 2],
    }
)
rows_to_remove = [('a', 4), ('c', 2), ('d', 4), ('a', 3)]
sf6xfgos

sf6xfgos1#

我会使用 boolean indexingpandas.Series.isin

m = df.agg(tuple, axis=1).isin(rows_to_remove)

df = df.loc[~m]

输出量:

print(df)

   A  B
1  b  2
3  d  1
wz3gfoph

wz3gfoph2#

您可以使用带有指示器的merge

out = (df.merge(pd.DataFrame(rows_to_remove, columns=['A', 'B']), indicator=True, how='left')
         .query('_merge == "left_only"')
         #.drop(columns='_merge') # commented to see the logic
       )

输出量:

A  B     _merge
1  b  2  left_only
3  d  1  left_only

或者,与drop结合使用:

idx = (df.merge(pd.DataFrame(rows_to_remove, columns=['A', 'B']), how='left', indicator=True)
         .query('_merge == "both"').index
      )

out = df.drop(idx)

输出量:

A  B
1  b  2
3  d  1
bvjxkvbb

bvjxkvbb3#

如果您import numpy as np,您可以:

df[~(df.values==np.array(rows_to_remove, dtype=object)[:,None]).any(0).all(-1)]

它很有趣,但也很有用,因为我在google-colab上测试过,性能是274 µs ± 11.6 µs与@Timeless的解决方案中的1.44 ms ± 37.7µs,我认为这是最好的,这是我一读到问题就想到的同一个。
如果能看到更大的 Dataframe 之间的差异,那将是一件很有趣的事情。

hzbexzde

hzbexzde4#

您可以从rows_to_remove创建一个嵌套框架,然后附加到原始嵌套框架并删除重复项:

>>> (pd.concat([df, pd.DataFrame(rows_to_remove, columns=['A', 'B'])])
       .drop_duplicates(['A', 'B'], keep=False))

   A  B
1  b  2
3  d  1
9nvpjoqh

9nvpjoqh5#

希望这对你有帮助。你可以使用'df.drop'按索引删除行/列。请看下面提到的:
DataFrame.drop(labels=None,*,axis=0,index=None,columns=None,level=None,inplace=False,errors='raise')[https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop.html]

相关问题