【问题标题】:pandas data frame comparing string values for 2 group by columns熊猫数据框按列比较2组的字符串值
【发布时间】:2020-02-19 02:34:07
【问题描述】:

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

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

我想知道Search==Yes 的提供者是否与给定ID 的Search==No 不同。例如 - 'ID 1'、'Search=No' 发给提供商 B、C,而 'Search=Yes' 发给提供商 A、B。所以提供者 A 对于 ID 1 来说是新的。

我知道我可以使用isin 函数来识别两个列表之间的唯一值。但是,如何跨多行 ID 和 Search 执行此操作?以及如何将 Provider 值编译到由 ID 和 Search 定义的每个子组的列表中?我想我将需要使用嵌套循环但无法编写代码。如果有人可以帮助我,我将不胜感激。

【问题讨论】:

标签: python pandas loops dataframe


【解决方案1】:

这可以通过几个步骤完成。首先,按 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/提供者组合,您可以获得是/否搜索次数的计数

>>> 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

【讨论】:

    【解决方案2】:

    您可能需要考虑集合,而不是编译成列表。在一般意义上,这可能更有用,因为我认为顺序和冗余并不重要。此外,更容易确定哪些提供者在一组而不是另一组。您可以使用 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
    

    【讨论】:

    • 太棒了!这正是我所需要的。真的很感激!
    【解决方案3】:

    方法一

    您可以先使用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`
    

    方法二

    将数据集拆分为yesno 然后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
    

    【讨论】:

    • 谢谢你这对我有用!真的很感激!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2017-03-28
    • 2021-08-11
    相关资源
    最近更新 更多