Python 按多个类别对重复项进行分组

Python 按多个类别对重复项进行分组,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,鉴于此示例数据集,我试图提醒各公司,它们在我们的数据库中存在重复项,以便它们能够相互通信并确定此人所属的公司: Name SSN Company Smith, John 1234 A Smith, John 1234 B Jones, Mary 4567 C Jones, Mary 4567 D Williams, Joe 1212 A Williams, Joe 1212 C

鉴于此示例数据集,我试图提醒各公司,它们在我们的数据库中存在重复项,以便它们能够相互通信并确定此人所属的公司:

Name            SSN      Company
Smith, John     1234     A
Smith, John     1234     B
Jones, Mary     4567     C
Jones, Mary     4567     D
Williams, Joe   1212     A
Williams, Joe   1212     C
理想的输出是向每个公司提供一个数据框,提醒他们注意数据中的重复项,以及声称是分配给他们的同一个人的另一家公司的身份。大概是这样的:

A公司数据帧

Name             SSN      Company
Smith, John      1234     A
Smith, John      1234     B
Williams, Joe    1212     A
Williams, Joe    1212     C
Name             SSN      Company
Jones, Mary      4567     C
Jones, Mary      4567     D
Williams, Joe    1212     A
Williams, Joe    1212     C
C公司数据帧

Name             SSN      Company
Smith, John      1234     A
Smith, John      1234     B
Williams, Joe    1212     A
Williams, Joe    1212     C
Name             SSN      Company
Jones, Mary      4567     C
Jones, Mary      4567     D
Williams, Joe    1212     A
Williams, Joe    1212     C
因此,尝试了groupby['Company',],但是,当然,如果只将所有公司结果分组到一个组中,那么它会忽略另一个具有重复人员和SSN的公司。groupby的某些版本(深入到该版本的逻辑中)似乎应该可以工作,但是按多个列分组,不完全可以。输出将按公司分组,但包含与该公司组中所有值关联的重复值。一个谜,因此我的帖子


可能是按公司分组,然后在“名称”列中将每个公司组与其他组连接起来?

首先,我们关注
公司
,以便轻松查看多个公司的员工:

df2 = pd.pivot_table(df.assign(count = 1), index = ['Name','SSN'], columns='Company', values='count', aggfunc = 'count')
产生

    Company             A   B   C   D
Name            SSN             
Jones,Mary      4567    NaN NaN 1.0 1.0
Smith,John      1234    1.0 1.0 NaN NaN
Williams,Joe    1212    1.0 NaN 1.0 NaN
其中values是该公司员工的计数,NaN表示他不在该公司

现在我们可以为不同的公司提取有用的视图。例如,我们可以说“拉住A公司和任何其他公司的所有人”:

dfA = df2[(~df2['A'].isna()) & (~df2[['B','C','D']].isna()).any(axis=1) ].dropna(how = 'all', axis=1)
dfA
这就产生了

    Company              A  B   C
Name            SSN         
Smith,John      1234    1.0 1.0 NaN
Williams,Joe    1212    1.0 NaN 1.0
注意,我们在这里通过
dropna(…)
删除了不相关的公司,在本例中是D,因为A和D之间没有重叠。D列有所有的N

我们可以很容易地编写一个函数来为任何公司生成报告

def report_for(company_name):
    companies = df2.columns
    other_companies = [c for c in companies if c != company_name]
    return (df2[(~df2[company_name].isna()) 
              & (~df2[other_companies].isna()).any(axis=1) ]
              .loc[:,[company_name] + other_companies]
              .dropna(how = 'all', axis=1)
              )
注意:我们还对列进行了重新排序,以便公司“B”的表首先有列“B”:

report_for('B')
产生

    Company         B   A
Name        SSN     
Smith,John  1234    1.0 1.0

为什么没有公司B数据帧?@danimesjo。哦,为了简单起见,就不提了。希望每个公司都会有一个数据框架。非常感谢您的回复和详细解释。这里有很多东西需要学习,这些步骤和背后的策略非常有效。@JohnTaylor真棒,很高兴它起到了作用!仅供参考,我进一步扩展了这一步骤,并将1值替换为列名,这样我就可以为每一行中的每个人生成具有人员和关联公司名称的每个公司的数据。再次感谢。@JohnTaylor听起来是个有用的补充。如果您愿意,请随意编辑答案以包含该步骤