Pandas数据框比较两个分组列的字符串值

3

我有一个数据集,看起来像这样-

ID        Search    Provider
1           Yes     A
1           Yes     B
1           No      B
1           No      C
2           Yes     D
2           Yes     A
2           Yes     B
2           No      B
2           No      C

我想找出的是对于给定的ID,如果提供商为“Search == Yes”是否与“Search == No”不同。例如,“ID 1”,'Search = No'前往提供商B、C,而'Search = Yes'前往提供商A、B。因此,提供商A是ID 1的新提供商。
我知道我可以使用“isin”函数来识别两个列表之间的唯一值。但是,如何在多行ID和Search上执行此操作?并且,如何将提供商值编译到由ID和Search定义的每个子组的列表中?我猜我需要使用嵌套循环,但无法编写代码。如果有人能帮助我,我会非常感激。

1
不是很确定您需要的输出,但似乎您想要分离,然后可以使用 outer merge 并带有指示器来找出哪些提供商存在于两者中,只有“是”或只有“否”。请参见 https://dev59.com/sFQJ5IYBdhLWcg3wiWab - ALollz
3个回答

1
与其编译成列表,您可能希望考虑使用集合。从一般意义上讲,这可能更有用,因为我认为顺序和冗余并不重要。而且,确定哪个提供者属于一个集合而不属于另一个集合更容易。您可以使用 pivot_table 重新排列数据框来实现这一点:
df_new = df.pivot_table(index='ID', columns='Search', aggfunc=set).droplevel(0, axis=1)

结果:

Search      No        Yes
ID                       
1       {C, B}     {A, B}
2       {C, B}  {D, A, B}

使用这个新的数据框,你可以轻松地比较具有相同“ID”的值:
# df_new['No'] == df_new['Yes']   # If providers are the same between "yes" and "no"
df_new['Yes'] - df_new['No']      # Providers that are in "yes" but not "no"

结果(用于集合差异):
ID
1       {A}
2    {D, A}
dtype: object

太棒了!这正是我所需要的。非常感谢! - Rubaiya Islam

0

这可以通过几个步骤完成。首先,按ID和搜索进行分组,然后使用value_counts获取唯一值。

>>> df1 = df.groupby(['ID', 'Search']).Provider.value_counts()
ID  Search  Provider
1   No      B           1
            C           1
    Yes     A           1
            B           1
2   No      B           1
            C           1
    Yes     A           1
            B           1
            D           1

针对每个ID/提供者组合,您可以获取Yes/No搜索次数的计数。
>>> df2 = df1.unstack(level='Search', fill_value=0)
Search       No  Yes
ID Provider         
1  A          0    1
   B          1    1
   C          1    0
2  A          0    1
   B          1    1
   C          1    0
   D          0    1

从这里,您可以获取具有“是”或“否”但不是两者的提供商/ID组合列表

>>> df2 = df1.query('Yes != No')
Search       No  Yes
ID Provider         
1  A          0    1
   C          1    0
2  A          0    1
   C          1    0
   D          0    1

0

方法一

您可以先使用 groupby.agg(set),然后再使用 groupby.diff

dfg = df.groupby(['ID', 'Search']).agg(set).reset_index()
dfg.groupby('ID')['Provider'].diff().dropna()

1       {A}
3    {A, D}
Name: Provider, dtype: object`

方法二

将数据集分成,然后使用groupby.set

yes = df.loc[df['Search'] == 'Yes']
no  = df.loc[df['Search'] == 'No']

yes_agg = yes.groupby('ID')['Provider'].agg(set)
no_agg = no.groupby('ID')['Provider'].agg(set)

# get the difference between the sets
yes_agg - no_agg

ID
1       {A}
2    {A, D}
Name: Provider, dtype: object

谢谢,这对我很有用!非常感激! - Rubaiya Islam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接