查看 Pandas 中两列是否一对一的简单方法
Easy Way to See if Two Columns are One-to-One in Pandas
与 pandas 一起使用 Python 3+ 中的数据。似乎应该有一种简单的方法来检查两列是否具有一对一关系(无论列类型如何),但我正在努力想出最好的方法。
预期输出示例:
A B C
0 'a' 'apple'
1 'b' 'banana'
2 'c' 'apple'
A & B 是一对一的?真
A和C是一对一的?错误
B和C是一对一的?错误
嗯,你可以创建自己的函数来检查它:
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
解决这个问题的一种方法,
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
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)
这个矩阵会告诉你两列中列值的对应关系。
在一对一关系的情况下,矩阵中每行只有一个非零值。
这是我的解决方案(只有两三行代码)检查任意数量的列以查看它们是否一对一匹配(允许重复匹配,请参阅下面的示例)。
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)
通过使用此函数,您可以进行 one-to-one 匹配检查:
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
df.groupby('A').B.nunique().max()==1 #Output: True
df.groupby('B').C.nunique().max()==1 #Output: False
在 [groupby 列] 的每个值中,计算 [other 列] 中唯一值的数量,然后检查所有此类计数的最大值是否为一个
与 pandas 一起使用 Python 3+ 中的数据。似乎应该有一种简单的方法来检查两列是否具有一对一关系(无论列类型如何),但我正在努力想出最好的方法。
预期输出示例:
A B C
0 'a' 'apple'
1 'b' 'banana'
2 'c' 'apple'
A & B 是一对一的?真
A和C是一对一的?错误
B和C是一对一的?错误
嗯,你可以创建自己的函数来检查它:
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
解决这个问题的一种方法,
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
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)
这个矩阵会告诉你两列中列值的对应关系。
在一对一关系的情况下,矩阵中每行只有一个非零值。
这是我的解决方案(只有两三行代码)检查任意数量的列以查看它们是否一对一匹配(允许重复匹配,请参阅下面的示例)。
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)
通过使用此函数,您可以进行 one-to-one 匹配检查:
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
df.groupby('A').B.nunique().max()==1 #Output: True
df.groupby('B').C.nunique().max()==1 #Output: False
在 [groupby 列] 的每个值中,计算 [other 列] 中唯一值的数量,然后检查所有此类计数的最大值是否为一个