根据另一个数据帧中的数据量删除数据帧的行

时间:2018-01-13 16:11:26

标签: python pandas

我有两个pandas数据框ABB是A的子集。

我想删除A中的所有数字,如果它在B中,如果一个数字在A中出现两次,在B中出现1次,那么它只会删除1次出现的数字来自A的数字。

以下是我的示例数据集:

df_A                df_B
[Test]              [Test]
1                   1
2                   2         
3                   5 
2                   5 
4
5
5

操作后我想要新的数据框c为

df_C
[Test]
3
2
4

你能建议怎么做吗?

如果A中存在Bsuggested duplicate将删除public abstract class ClassA { private int m_number; protected ClassA() { m_number = GetNumber() } protected abstract int GetNumber(); } public class ClassB : ClassA { public ClassB() : base() { } protected override int GetNumber() { return 10; } } 中的所有匹配项,而不仅仅是前N次出现。

3 个答案:

答案 0 :(得分:2)

如果您创建一些包含每个值的出现次数的中间值,则可以使用pandas.Series.isin()创建要排除的数据帧的哪些行的逻辑索引,如:

代码:

from collections import Counter

def occurrences_number(column):

    def occurrence_number(value, accumulator):
        """ tuple of value and occurrence number of value """
        accumulator[value] += 1
        return value, accumulator[value]

    occurrences = Counter()
    return column.apply(lambda x: occurrence_number(x, occurrences))

def find_not_in_by_occurrence_number(data, not_in):
    not_in_indices = ~occurrences_number(data).isin(occurrences_number(not_in))
    return data[not_in_indices].reset_index()

测试代码:

import pandas as pd

dfA = pd.DataFrame({'A': [1, 2, 3, 2, 4, 5, 5]})
dfB = pd.DataFrame({'B': [1, 2, 5, 5]})
print(dfA)
print(dfB)

dfC = find_not_in_by_occurrence_number(dfA.A, dfB.B).A

print (dfC)

结果:

   A
0  1
1  2
2  3
3  2
4  4
5  5
6  5

   B
0  1
1  2
2  5
3  5

0    3
1    2
2    4
Name: A, dtype: int64

答案 1 :(得分:2)

我可能会做某事(窃取SR的设置):

dfA = pd.DataFrame({'A': [1, 2, 3, 2, 4, 5, 5]})
dfB = pd.DataFrame({'B': [1, 2, 5, 5]})

counts = dfA.groupby('A').cumcount()
limits = dfB['B'].value_counts().reindex(dfA.A).fillna(0).values
dfC = dfA.loc[counts >= limits]

给了我

In [121]: dfC
Out[121]: 
   A
2  3
3  2
4  4

这可以通过使用groupby来获得之前看到A中给定值的次数:

In [124]: dfA.groupby('A').cumcount()
Out[124]: 
0    0
1    0
2    0
3    1
4    0
5    0
6    1
dtype: int64

并使用value_counts获取限制,然后重新索引以匹配计数:

In [139]: dfB['B'].value_counts()
Out[139]: 
5    2
2    1
1    1
Name: B, dtype: int64

In [140]: dfB['B'].value_counts().reindex(dfA.A)
Out[140]: 
A
1    1.0
2    1.0
3    NaN
2    1.0
4    NaN
5    2.0
5    2.0
Name: B, dtype: float64

答案 2 :(得分:1)

在此问题中,您可以使用Counterdrop。对于drop,您需要知道要丢弃的行的索引。

import itertools
from collections import Counter
df = pd.DataFrame({'Test': {0: 1, 1: 2, 2: 3, 3: 2, 4: 4, 5: 5, 6: 5}})
df2 = pd.DataFrame({'Test': {0: 1, 1: 2, 2: 5, 3: 5}})
c_df2 = Counter(df2.Test)

indexes_to_remove_2d = [df.index[df['Test'] == k].tolist()[:v] 
                        for k, v in c_df2.items()]
# [[0], [1], [5, 6]]
merged = list(itertools.chain(*indexes_to_remove_2d))
# [0, 1, 5, 6]
df.drop(merged)

    Test
2   3
3   2
4   4

indexes_2d生成符合k计数器值df.index[df['Test'] == k]的索引,并且[:v]限制我们从中获取的索引的大小。

然后,我们将这些indexesitertools.chain合并。最后删除带有这些索引的行。

感谢Stephan Ranch指出订单问题。