поиск транзитивной связи между двумя столбцами в pandas

У меня есть фрейм данных pandas с двумя столбцами - user1 и user2 что-то вроде этого

Теперь я хочу сделать транзитивное отношение таким образом, что если A связано с B, а B связано с C, а C связано с D, то я хочу, чтобы вывод был в виде списка, например «A-B-C-D» в одной группе и «E-F-G» в другой группе .

Спасибо


person Naman Doshi    schedule 07.06.2018    source источник
comment
Пожалуйста, не портите свои посты. Если вы считаете, что ваш вопрос бесполезен или больше не нужен, его следует удалить вместо того, чтобы редактировать все данные, которые фактически делают его вопросом. Размещая в сети Stack Exchange, вы предоставляете SE безотзывное право на распространение этого контента (в соответствии с лицензией CC BY-SA 3.0). Согласно политике SE, любой вандализм будет пресекаться.   -  person Filnor    schedule 21.06.2018
comment
Вау, хотел посмотреть, как быстро вы это обнаружите. Вы молодцы!   -  person Naman Doshi    schedule 21.06.2018


Ответы (2)


Если у вас всего 2 группы, можно поступить таким образом. Но это работает только для 2 групп, и нельзя обобщать:

x = []
y = []
x.append(df['user1'][0])
x.append(df['user2'][0])

for index, i in enumerate(df['user1']):
    if df['user1'][index] in x:
        x.append(df['user2'][index])
    else:
        y.append(df['user1'][index])
        y.append(df['user2'][index])
x = set(x)
y = set(y)
person Joe    schedule 07.06.2018
comment
Их более 2 групп. Что еще я могу сделать? - person Naman Doshi; 07.06.2018
comment
Вы заранее знаете количество групп? - person Joe; 07.06.2018

Если вы хотите найти все транзитивные отношения, то, скорее всего, вам нужно выполнить рекурсию. Возможно, этот следующий фрагмент кода может помочь:

import pandas as pd
data={'user1':['A','A','B', 'C', 'E', 'F'],
      'user2':['B', 'C','C','D','F','G']}
df=pd.DataFrame(data)

print(df)

# this method is similar to the commnon table expression (CTE) in SQL                                                                    
def cte(df_anchor,df_ref,level):
    if (level==0):
        df_anchor.insert(0, 'user_root',df_anchor['user1'])
        df_anchor['level']=0
        df_anchor['relationship']=df_anchor['user1']+'-'+df_anchor['user2']
        _df_anchor=df_anchor
    if (level>0):
        _df_anchor=df_anchor[df_anchor.level==level]
    _df=pd.merge(_df_anchor, df_ref , left_on='user2', right_on='user1', how='inner', suffixes=('', '_x'))

    if not(_df.empty):
        _df['relationship']=_df['relationship']+'-'+_df['user2_x']
        _df['level']=_df['level']+1
        _df=_df[['user_root','user1_x', 'user2_x', 'level','relationship']].rename(columns={'user1_x': 'user1', 'user2_x': 'user2'})
        df_anchor_new=pd.concat([df_anchor, _df])
        return cte(df_anchor_new, df_ref, level+1)
    else:
        return df_anchor

df_rel=cte(df, df, 0)
print("\nall relationship=\n",df_rel)

print("\nall relationship related to A=\n", df_rel[df_rel.user_root=='A'])

 user1 user2
0     A     B
1     A     C
2     B     C
3     C     D
4     E     F
5     F     G

all relationship=
   user_root user1 user2  level relationship
0         A     A     B      0          A-B
1         A     A     C      0          A-C
2         B     B     C      0          B-C
3         C     C     D      0          C-D
4         E     E     F      0          E-F
5         F     F     G      0          F-G
0         A     B     C      1        A-B-C
1         A     C     D      1        A-C-D
2         B     C     D      1        B-C-D
3         E     F     G      1        E-F-G
0         A     C     D      2      A-B-C-D

all relationship related to A=
   user_root user1 user2  level relationship
0         A     A     B      0          A-B
1         A     A     C      0          A-C
0         A     B     C      1        A-B-C
1         A     C     D      1        A-C-D
0         A     C     D      2      A-B-C-D
person DTT    schedule 07.06.2018