【问题标题】:Remove Rows from pandas.Dataframe Based on Entries根据条目从 pandas.Dataframe 中删除行
【发布时间】:2025-12-22 18:25:11
【问题描述】:

给定一个pandas.DataFrame

    | Col_A | Col_B | Other_Columns
0   | A0    | B0    | …
1   | A1    | B1    | …
2   | A2    | B2    | …
3   | A3    | B3    | …
…   | …     | …     | …

我一直在尝试保留 DataFrame 的一个子集:删除 AB 条目都是唯一的行(例如,如果在第 6 行,两个值 A6B6不要出现在DataFrame 的其他任何地方,我们要删除此行)

我不想删除重复项。另外,我不想获得唯一值(如果我理解得很好,这类似于将列表转换为集合,对吗?),而是只出现一次的值。

在这一点上,这就是我得到的:

counts = df[['Col_A','Col_B']].stack().value_counts(ascending=True)
myList = [0] + [item for item in counts[counts.values == 1].index]
toRemove = []
for i in df.index:
    if (df.at[i,'Col_A'] and df.at[i, 'Col_B']) in myList:
        toRemove.append(i)
final_df = df[~df.index.isin(toRemove)]

这不是很有效(数据框很大>10M行)必须有一个更pythonic的策略,涉及pandas的内置功能,对吧? 另外,我不太确定第一行是否正确:通过堆叠两列,我是否确保对两列的条目进行计数?

如果您需要更多信息或我的文字对您来说不清楚,请不要犹豫。

非常感谢您抽出宝贵时间:-)

【问题讨论】:

  • @unutbu,IMO 不是重复的。 OP 希望保留 either 列中的值不唯一的行
  • @MaxU:我的错;感谢您重新打开。

标签: python pandas dataframe


【解决方案1】:

这样的事情怎么样:

In [75]: df = pd.DataFrame(np.random.randint(0,100,size=(10, 3)), columns=list('abc'))

In [76]: df
Out[76]:
    a   b   c
0  37  85  17
1  19   0  11
2  51  20  65
3  59  92  65
4  48  15  91
5  21  50  44
6  61  94  49
7  51   6  88
8  89  72  40
9   5  51  79

In [77]: c = df[['a','b']].stack().value_counts()

In [78]: c
Out[78]:
51    3
94    1
15    1
37    1
6     1
72    1
50    1
21    1
5     1
48    1
61    1
19    1
20    1
85    1
89    1
59    1
92    1
0     1
dtype: int64

In [79]: c[c>1]
Out[79]:
51    3
dtype: int64

In [80]: vals = c[c>1].index

In [81]: df[(df['a'].isin(vals)) | (df['b'].isin(vals))]
Out[81]:
    a   b   c
2  51  20  65
7  51   6  88
9   5  51  79

更新:

当您执行if (df.at[i,'Col_A'] and df.at[i, 'Col_B']) in myList: 检查时,您检查的不是很正确...

这是正在发生的事情:

In [90]: df.at[0, 'a'], df.at[0, 'b']
Out[90]: (37, 85)

In [91]: (df.at[0, 'a'] and df.at[0, 'b'])
Out[91]: 85

所以你不能这样检查

【讨论】:

  • 非常感谢 MaxU,您的建议答案很明确,您的代码也很快。我一直在玩它,但仍有一个疑问:如果我尝试使用循环数据帧索引的慢速方法来完成它,我会得到完全不同的输出:keepIndex = []for i in df.index: if df.at[i,’a’] or df.at[i,’b’] in vals: keepIndex.append(i)final_df = df[df.index.isin(keepIndex)]我的代码是否完全别的东西?我错过了什么吗?
  • @UniversalTraveller,请阅读我的回答中的“更新:”部分
  • 好的,非常感谢您的澄清 :-) 你知道为什么吗?
  • @UniversalTraveller,很高兴为您提供帮助。当您运行1 or 3 时,python 将检查是否至少 一个数字为真(即 !=0 ),因此它将返回1。如果您执行1 and 3,python 将检查 both 数字是否为 True (!= 0),因此它将返回最后一个 - 3。当您执行if (df.at[i,’a’] or df.at[i,’b’]) 时会发生这种情况 - 基本上它将被转换为if (<first_number != 0>)。我建议你玩一下:print(3 or 5); print(3 and 5)