Перечисление отношений между столбцами - PullRequest
1 голос
/ 17 июня 2020

У меня есть этот фрейм данных ниже:

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 появляется в том же cnpj, что и EUGENIO LUPORINI NETO (410000132), а SIMONE FANKHAUSER и ALEX SOUZA появляются в другом cnpj вместе с EUGENIO (4830624000197)

Я полагаю, это может быть что-то но не знаю, как этого добиться.

Ответы [ 2 ]

2 голосов
/ 17 июня 2020

Вы можете использовать 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)
1 голос
/ 17 июня 2020

Работает следующее:

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]

Спасибо этому ответу за помощь с вышеуказанным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...