【问题标题】:How can I create binary label from two tables如何从两个表创建二进制标签
【发布时间】:2017-08-25 05:15:38
【问题描述】:

我正在尝试分析我使用 Pandas 获得的数据的趋势。我有两个表,如果该行中的 UID 和 PID 存在于另一个表中,我想在一个表中创建一个新的二进制列。我目前拥有的表格示例如下:

>>> df_a = pd.DataFrame({"UID": [123, 456, 789, 012], "PID": [12, 55, 56, 89], "TIM": [76, 54, 21, 25]})
>>> df_a 
   PID  TIM  UID
0   12   76  123
1   55   54  456
2   56   21  789
3   89   25  010

>>> df_b = pd.DataFrame({'UID': [221, 012, 653, 456], 'PID': [17, 89, 51, 55], 'FOO': [2347, 32447, 3234, 7999]})
>>> df_b
     FOO  PID  UID
0   2347   17  221
1  32447   89  010
2   3234   51  653
3   7999   55  456

我希望最终结果是:

>>> df_a
   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25  010    1

但我不知道该怎么做。我认为left join 将是要走的路,但我也很难做到这一点。任何帮助将不胜感激

【问题讨论】:

  • 是的,你想做一个左连接(在 pandas 中称为合并)

标签: python python-2.7 pandas join


【解决方案1】:

您可以将左连接与joinmerge 一起使用,然后测试FOO 列,如果不是NaN,则将boolean mask 转换为astype 转换为0,1

df_a['PUR'] = df_a.join(df_b.set_index(['PID','UID']), on=['PID','UID'])['FOO']
                  .notnull().astype(int)
print (df_a)
   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25   12    1

df_a['PUR'] = pd.merge(df_a, df_b, how='left', on=['PID','UID'])['FOO'].notnull().astype(int)
print (df_a)
   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25   12    1

另一个解决方案是isin

df_a['PUR']  = df_a.set_index('PID')['UID'].isin(df_b.set_index('PID')['UID'])
                   .astype(int).values
print (df_a)
   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25   12    1

编辑:

两列似乎都需要drop_duplicates

#added duplicates
df_b = pd.DataFrame({'UID': [221, 12, 456, 456], 
                     'PID': [17, 89, 55, 55], 
                     'FOO': [2347, 32447, 3234, 7999]})
print (df_b)
     FOO  PID  UID
0   2347   17  221
1  32447   89   12
2   3234   55  456 <-duplicates by both columns
3   7999   55  456 <-duplicates by both columns

df_b = df_b.drop_duplicates(['PID','UID'])
df_a['PUR'] = df_a.join(df_b.set_index(['PID','UID']), on=['PID','UID'])['FOO']
                  .notnull().astype(int)
print (df_a)
   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25   12    1

【讨论】:

  • 感谢您的回答。当我尝试这个时,我得到一个ValueError: cannot reindex from a duplicate axis。结果发现我感兴趣的列中有重复项,因此检查并确保删除了所有重复项,但是当我尝试 join 时仍然出现此错误
  • 我通过将.values 附加到join 的末尾来解决这个问题,但现在我遇到了一个奇怪的问题,即连接以某种方式创建的元素比原来的元素多43 个数据框,返回一个ValueError: Length of values does not match length of index 异常
  • 请检查已编辑的答案 - 我认为问题在 df_b 的两列中重复。
【解决方案2】:

mergeindicator=True 几乎可以让你到达那里

df_a.merge(df_b[['PID', 'UID']], how='left', indicator=True)

   PID  TIM  UID     _merge
0   12   76  123  left_only
1   55   54  456       both
2   56   21  789  left_only
3   89   25  012       both

使用map 进行调整

m = dict(left_only=0, both=1)
df_a.assign(
    PUR=df_a.merge(df_b[['PID', 'UID']], how='left', indicator=True)._merge.map(m))

   PID  TIM  UID  PUR
0   12   76  123    0
1   55   54  456    1
2   56   21  789    0
3   89   25  012    1

【讨论】:

    【解决方案3】:

    你可以使用 numpy 的 in1d()。您也可以使用它来实现其他情况,其中左连接可能会失败

        import pandas as pd
        import numpy as np
    
        df_a = pd.DataFrame({"UID": [123, 456, 789, 012], "PID": [12, 55, 56, 89], "TIM": [76, 54, 21, 25]})
    
        df_b = pd.DataFrame({'UID': [221, 012, 653, 456], 'PID': [17, 89, 51, 55], 'FOO': [2347, 32447, 3234, 7999]})
    
        UID_a = df_a['UID'].values
        UID_b = df_b['UID'].values
        PID_a = df_a['PID'].values
        PID_b = df_b['PID'].values
    
        x = np.in1d(UID_a, UID_b)
        y = np.in1d(PID_a, PID_b)
    
        PUR = x + y
    
        df_a['PUR'] = PUR
        df_b['PUR'] = PUR
    

    【讨论】:

      【解决方案4】:

      你可以用左连接来做到这一点,但如果你想得到那个结果,它会有点奇怪。

      df_b['PUR'] = 1
      df_a = pd.merge(df_a, df_b, how='left', on=['PID', 'UID'])
      df_a['PUR'] = df_a['PUR'].apply(lambda x: 1 if pd.notnull(x) else 0)
      df_a = df_a.drop('FOO', axis=1)
      

      我建议改用纯 apply

      df_a['PUR'] = df_a.apply(lambda x: int(x['UID'] in df_b['UID'].values or
                                             x['PID'] in df_b['PID'].values), axis=1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-19
        • 1970-01-01
        • 2012-08-14
        • 1970-01-01
        • 2017-11-08
        • 1970-01-01
        • 2016-07-29
        • 2019-07-28
        相关资源
        最近更新 更多