轻松查看两个列是否与熊猫一对一

时间:2018-06-01 12:25:16

标签: python pandas one-to-one

使用pandas处理Python 3+中的数据。似乎应该有一种简单的方法来检查两列是否具有一对一的关系(无论列类型如何),但我很难想到最好的方法。

预期产出的例子:

A    B     C
0    'a'   'apple'
1    'b'   'banana'
2    'c'   'apple'

A& B是一对一的吗? TRUE

A& C是一对一的吗? FALSE

B& C是一对一的吗? FALSE

5 个答案:

答案 0 :(得分:4)

好吧,您可以创建自己的功能来检查它:

def isOneToOne(df, col1, col2):
    first = df.groupby(col1)[col2].count().max()
    second = df.groupby(col2)[col1].count().max()
    return first + second == 2

isOneToOne(df, 'A', 'B')
#True
isOneToOne(df, 'A', 'C')
#False
isOneToOne(df, 'B', 'C')
#False

如果您的数据更像是这样:

df = pd.DataFrame({'A': [0, 1, 2, 0],
                   'C': ["'apple'", "'banana'", "'apple'", "'apple'"],
                   'B': ["'a'", "'b'", "'c'", "'a'"]})
df
#   A    B         C
#0  0  'a'   'apple'
#1  1  'b'  'banana'
#2  2  'c'   'apple'
#3  0  'a'   'apple'

然后你可以使用:

def isOneToOne(df, col1, col2):
    first = df.drop_duplicates([col1, col2]).groupby(col1)[col2].count().max()
    second = df.drop_duplicates([col1, col2]).groupby(col2)[col1].count().max()
    return first + second == 2

答案 1 :(得分:1)

df.groupby(col1)[col2]\
  .apply(lambda x: x.nunique() == 1)\
  .all()

如果您希望得到正确或错误的答案,应该可以正常工作。

一种可视化具有离散/分类值的两列之间关系的好方法(如果使用的是Jupyter笔记本)是:

df.groupby([col1, col2])\
  .apply(lambda x : x.count())\
  .iloc[:,0]\
  .unstack()\
  .fillna(0)

此矩阵将告诉您两列中列值之间的对应关系。

在一对一关系的情况下,矩阵中每行只有一个非零值。

答案 2 :(得分:1)

df.groupby('A').B.nunique().max()==1 #Output: True

df.groupby('B').C.nunique().max()==1 #Output: False

在[groupby列]中的每个值内,在[other列]中计数唯一值的数量,然后检查所有此类计数的最大值是否为一个

答案 3 :(得分:0)

解决这个问题的一种方法,

df['A to B']=df.groupby('B')['A'].transform(lambda x:x.nunique()==1)
df['A to C']=df.groupby('C')['A'].transform(lambda x:x.nunique()==1)
df['B to C']=df.groupby('C')['B'].transform(lambda x:x.nunique()==1)

输出:

   A  B       C  A to B  A to C  B to C
0  0  a   apple    True   False   False
1  1  b  banana    True    True    True
2  2  c   apple    True   False   False

逐列检查:

print (df['A to B']==True).all()
print (df['A to C']==True).all()
print (df['B to C']==True).all()

True
False
False

答案 4 :(得分:0)

这是我的解决方案(仅两三行代码),用于检查任意数量的列,以查看它们是否为一对一匹配(允许重复匹配,请参见下面的示例)

cols = ['A', 'B'] # or any number of columns ['A', 'B', 'C']
res = df.groupby(cols).count()
uniqueness = [res.index.get_level_values(i).is_unique 
              for i in range(res.index.nlevels)]
all(uniqueness)

让它成为一个函数并添加一些文档:

def is_one_to_one(df, cols):
    """Check whether any number of columns are one-to-one match.

    df: a pandas.DataFrame
    cols: must be a list of columns names

    Duplicated matches are allowed:
        a - 1
        b - 2
        b - 2
        c - 3
    (This two cols will return True)
    """
    if len(cols) == 1:
        return True
        # You can define you own rules for 1 column check, Or forbid it

    # MAIN THINGs: for 2 or more columns check!
    res = df.groupby(cols).count()
    # The count number info is actually bootless.
    # What maters here is the grouped *MultiIndex*
    # and its uniqueness in each level
    uniqueness = [res.index.get_level_values(i).is_unique
                  for i in range(res.index.nlevels)]
    return all(uniqueness)

使用此功能,您可以进行一对一的匹配检查:

df = pd.DataFrame({'A': [0, 1, 2, 0],
                   'B': ["'a'", "'b'", "'c'", "'a'"],
                   'C': ["'apple'", "'banana'", "'apple'", "'apple'"],})

is_one_to_one(df, ['A', 'B'])
is_one_to_one(df, ['A', 'C'])
is_one_to_one(df, ['A', 'B', 'C'])
# Outputs:
# True
# False
# False