【问题标题】:Listing relations between columns列出列之间的关系
【发布时间】:2020-06-17 23:36:48
【问题描述】:

我在下面有这个数据框:

df=pd.DataFrame({'cnpj':[410000132,410000132,4830624000197,4830624000197,4830624000197],'Nome Pessoa':['EUGENIO LUPORINI NETO','JUAN MATIAS SERAGOPIAN','EUGENIO LUPORINI NETO','SIMONE FANKHAUSER','ALEX SOUZA']})
print(df)

            cnpj             Nome Pessoa
0      410000132   EUGENIO LUPORINI NETO
1      410000132  JUAN MATIAS SERAGOPIAN
2  4830624000197   EUGENIO LUPORINI NETO
3  4830624000197       SIMONE FANKHAUSER
4  4830624000197              ALEX SOUZA

每个cnpj 都是一家公司。每个Nome Pessoa 都是一个人。我想列出每个Nome Pessoa,其他人与他出现相同的cnpj(最好没有重复)。换句话说,我将使用cnpj 作为键来列出人们之间的关系,df 看起来像这样(或至少接近它):

            cnpj             Nome Pessoa   Relations
0      410000132   EUGENIO LUPORINI NETO   ['JUAN MATIAS SERAGOPIAN','SIMONE FANKHAUSER','ALEX SOUZA']
1      410000132  JUAN MATIAS SERAGOPIAN   ['EUGENIO LUPORINI NETO']
2  4830624000197   EUGENIO LUPORINI NETO   ['JUAN MATIAS SERAGOPIAN','SIMONE FANKHAUSER','ALEX SOUZA']
3  4830624000197       SIMONE FANKHAUSER   ['EUGENIO LUPORINI NETO','ALEX SOUZA']
4  4830624000197              ALEX SOUZA   ['EUGENIO LUPORINI NETO','SIMONE FANKHAUSER']

比如df['Relations'][0] = ['JUAN MATIAS SERAGOPIAN','SIMONE FANKHAUSER','ALEX SOUZA']就是这样,因为JUAN MATIAS SERAGOPIAN和EUGENIO LUPORINI NETO (410000132)出现在同一个cnpj中,而SIMONE FANKHAUSER和ALEX SOUZA和EUGENIO (4830624000197)一起出现在另一个cnpj中

我想这可能是 groupby 区域中的一些东西,但不知道如何实现它。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    您可以使用apply 和其中的查询并将结果附加到DataFrame:

    def get_relations(row, df):
      row_cnpj = row['cnpj']
      row_name = row['Nome Pessoa']
      query = df.query('cnpj == @row_cnpj and `Nome Pessoa` != @row_name')
      row['Relations'] = query['Nome Pessoa'].values
      return row
    
    df = df.apply(lambda x: get_relations(x, df), axis=1)
    

    【讨论】:

      【解决方案2】:

      以下作品:

      In[0]:
      
      def add_relations(row):
          current_name = row['Nome Pessoa']
          cnpjs = df[df['Nome Pessoa'] == current_name]['cnpj']
          relations = df['cnpj'].isin(cnpjs)
          output = df[relations]['Nome Pessoa'][df['Nome Pessoa'] != current_name]
          return list(output)
      
      df['Relations'] = df.apply(add_relations, axis=1)
      df
      
      Out[0]:
                  cnpj             Nome Pessoa  \
      0      410000132   EUGENIO LUPORINI NETO   
      1      410000132  JUAN MATIAS SERAGOPIAN   
      2  4830624000197   EUGENIO LUPORINI NETO   
      3  4830624000197       SIMONE FANKHAUSER   
      4  4830624000197              ALEX SOUZA   
      
                                                 Relations  
      0  [JUAN MATIAS SERAGOPIAN, SIMONE FANKHAUSER, AL...  
      1                            [EUGENIO LUPORINI NETO]  
      2  [JUAN MATIAS SERAGOPIAN, SIMONE FANKHAUSER, AL...  
      3                [EUGENIO LUPORINI NETO, ALEX SOUZA]  
      4         [EUGENIO LUPORINI NETO, SIMONE FANKHAUSER]
      
      

      这使用apply,因此不是最佳选择,但根据您拥有的数据量可能没问题。

      更新:我也尝试使用groupby 制作一些东西,并提出了以下方法,它也可以使用,但感觉并不理想,因为它使用了groupby 2x 并且有一个非常讨厌的列表理解。我觉得有更好的答案,但它让我望而却步....

      num_to_name = df.groupby('cnpj')['Nome Pessoa'].apply(list)
      name_to_num = df.groupby('Nome Pessoa')['cnpj'].apply(list)
      
      df['Relations'] = df['Nome Pessoa'].map(name_to_num)
      df['Relations'] = [[x for x in num_to_name.loc[df.loc[i,'Relations']].values.sum()
                          if x != df.loc[i, 'Nome Pessoa']] for i in df.index]
      

      感谢this answer 提供上述帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-23
        • 2014-04-19
        • 2018-02-21
        • 2017-03-19
        • 2011-11-03
        • 1970-01-01
        • 2017-11-01
        • 1970-01-01
        相关资源
        最近更新 更多