如果熊猫是其他行的子集,则丢弃该行

时间:2019-04-18 02:33:44

标签: python pandas

我已经搜索了很多,但是似乎没有任何解决方法。

假设df何时:

import pandas as pd
import numpy as np

df = pd.DataFrame([['a','b','c'], ['a',np.nan,'b'], [np.nan, 'b', 'a'], ['a', 'd', 'b']])
df
     0    1  2
0    a    b  c
1    a  NaN  b
2  NaN    b  a
3    a    d  b

所需的输出是:

     0    1  2
0    a    b  c
3    a    d  b

第1行,第2行是第0行的子集,因此我想删除它们。在检查某行是否是其他任何子集时,不考虑NaN。因此,第1行变成{'a','b'},从而成为子集。

到目前为止,我一直在尝试制作set s:

df.ffill(1).bfill(1).apply(set, 1)

产生:

0    {c, a, b}
1       {a, b}
2       {a, b}
3    {d, a, b}

但是我被困在这里。 pd.DataFrame.drop_duplicates似乎对我没有帮助。

非常感谢您的帮助:)

2 个答案:

答案 0 :(得分:4)

这很难。理想情况下,您希望:

  • 坚持使用熊猫矢量化操作,而不是遍历行。 (起初,我想到了pd.Index,它的行为就像一个集合,并且具有一些类似于集合操作的方法。)
  • 尽可能使用类似哈希表的数据结构进行集合成员资格测试。

由于特定的条件,在这两种方法中都很难做到,并且时间复杂度可能因此变得很繁琐。 (我不排除答案可能比这个答案更模糊。)但是通常,一旦您从精确重复的测试转到子集测试,事情就会变得更加困难。

所有这些,您可以:

  1. 将DataFrame转换为嵌套列表-通过尽可能遍历Pandas数据结构来减少不必要的开销
  2. 在贪婪的set.issuperset调用中使用any()来查找重复的索引,以利用frozenset是可哈希的事实(由于这里的其他答案)。

复杂度仍然是N ^ 2或接近它,但是对于中等大小的数据,这可能就足够了。

>>> df = pd.DataFrame([['a','b','c'], ['a',np.nan,'b'], [np.nan, 'b', 'a'], ['a', 'd', 'b']])
>>> 
>>> seen = set()
>>> add = seen.add
>>> dupes = []
>>> 
>>> for pos, row in enumerate(df.values.tolist()):
...     vals = frozenset(i for i in row if isinstance(i, str))
...     if any(i.issuperset(vals) for i in seen):
...         dupes.append(pos)
...     add(vals)
... 
>>> dupes
[1, 2]

这使您可以通过DataFrame.drop()删除索引。

答案 1 :(得分:2)

您可以使用frozenset代替set

import pandas as pd
import numpy as np

def remove_myself_from_dict(some_dict, myself):
    _some_dict = some_dict.copy()
    _ = _some_dict.pop(myself)
    return _some_dict

df = pd.DataFrame([['a','b','c'], ['a',np.nan,'b'], [np.nan, 't', 'a'], ['a', 'd', 'b']])
df['column_set'] = df.ffill(1).bfill(1).apply(frozenset, 1)

all_set = dict(zip(df['column_set'], range(len(df))))
df['is_subset'] = df['column_set'].apply(
    lambda x: any([some_set >= x for some_set in remove_myself_from_dict(all_set, x)])
)

结果df

    0   1   2   column_set  is_subset
0   a   b   c   (b, c, a)   False
1   a   NaN b   (b, a)      True
2   NaN t   a   (t, a)      False
3   a   d   b   (b, d, a)   False