Python 在数据帧中查找列违反一对一映射的行

Python 在数据帧中查找列违反一对一映射的行,python,pandas,Python,Pandas,我有一个类似这样的数据帧: | index | col_1 | col_2 | | 0 | A | 11 | | 1 | B | 12 | | 2 | B | 12 | | 3 | C | 13 | | 4 | C | 13 | | 5 | C | 14 | 其中,由于数据损坏,col_1和col_2可能并不总是一对一的 如何使用Pandas确定哪些行具有违反此一

我有一个类似这样的数据帧:

| index | col_1 | col_2 |
| 0     | A     | 11    |
| 1     | B     | 12    |
| 2     | B     | 12    |
| 3     | C     | 13    |
| 4     | C     | 13    |
| 5     | C     | 14    |
其中,由于数据损坏,
col_1
col_2
可能并不总是一对一的

如何使用Pandas确定哪些行具有违反此一对一关系的
col_1
col_2


在这种情况下,它将是最后三行,因为C可以映射到13或14。

我将使用一个
collections.Counter
,因为列中每个项的多个实例违反了一对一映射:

>>> import pandas
>>> import numpy
>>> import collections
>>> df = pandas.DataFrame(numpy.array([['a', 1],['b', 2], ['b', 3], ['c', 3]]))
>>> df
   0  1
0  a  1
1  b  2
2  b  3
3  c  3
>>> collections.Counter(df[0])
Counter({'b': 2, 'a': 1, 'c': 1})
>>> violations1 = [k for k, v in collections.Counter(df[0]).items() if v > 1]
>>> violations2 = [k for k, v in collections.Counter(df[1]).items() if v > 1]
>>> violations1
['b']
>>> violations2
['3']

可以使用变换,计算每个组中唯一对象的长度。首先查看这些列的子集,然后按单个列分组:

In [11]: g = df[['col1', 'col2']].groupby('col1')

In [12]: counts = g.transform(lambda x: len(x.unique()))

In [13]: counts
Out[13]:
  col2
0    1
1    1
2    1
3    2
4    2
5    2
其余列的列(如果不是全部)


我对python非常陌生,但找到了一种方法,将所有唯一的分组收集到一个列表中,并过滤掉那些没有唯一映射的分组:

data = pd.DataFrame({'Col_1': ['A', 'B', 'B', 'C', 'C', 'C'], 'Col_2': [11,12,12,13,13,14]})
combos = []
for x, y in enumerate(range(len(data['Col_1']))):
    combo = '%s_%s' %(data['Col_1'][x], data['Col_2'][x])
    combos.append(combo)
data.index = data['Col_1']
for item in combos:
    if len([comb for comb in combos if item[2:] in comb[2:]]) != len([comb for comb in combos if item[0] in comb[0]]):
        data = data.drop(item[0])
data.reset_index(drop=True)
我测试了g.transform(lambda x:len(x.unique())),它工作得很好,但速度很慢,尤其是在有很多组的情况下。下面的代码运行得更快,所以我把它放在这里

data = pd.DataFrame({'Col_1': ['A', 'B', 'B', 'C', 'C', 'C'], 'Col_2': [11,12,12,13,13,14]})
combos = []
for x, y in enumerate(range(len(data['Col_1']))):
    combo = '%s_%s' %(data['Col_1'][x], data['Col_2'][x])
    combos.append(combo)
data.index = data['Col_1']
for item in combos:
    if len([comb for comb in combos if item[2:] in comb[2:]]) != len([comb for comb in combos if item[0] in comb[0]]):
        data = data.drop(item[0])
data.reset_index(drop=True)
df2 = pd.DataFrame(df[['col1', 'col2']].groupby(['col1','col2']).size(),columns=['count'])
df2.reset_index(inplace=True)
df3 = pd.DataFrame(df2.groupby('col1').size(), columns=['count'])
df4 = df3[df3['count']>1]
df_copy = df.copy()
df_copy.set_index('col1', inplace=True)
df_outlier = df_copy.ix[df4.index]