Сформируйте все возможные пути (список / dict) из фрейма данных в python - PullRequest
2 голосов
/ 11 июля 2020

Я пытаюсь сформировать все возможные пути, используя фреймворк. У меня есть следующий фрейм данных:

import pandas as pd 
data = {'from': ['b','c','d','e','f','g'], 'to': ['a', 'a', 'a', 'b','c','e']}
df = pd.DataFrame.from_dict(data)
print(df)

образец фрейма данных

Теперь я хочу создать все возможные пути / цепочки, используя эти 2 столбца. Вывод должен выглядеть примерно так:

  1. e -> b -> a
  2. f -> c -> a
  3. g -> e -> b -> a

Если возможно, представьте их числами, например:

  1. e -> b -> a = 5,2,1
  2. f -> c -> a = 6,3,1
  3. g -> e -> b -> a = 7,5,2,1

Обновление: поле «От» может содержать повторяющиеся записи.

Ответы [ 4 ]

1 голос
/ 11 июля 2020
# first of all let's make 'from' as index of df
df.set_index('from', inplace = True)

pth = []
def path(df, ch, res = []):
    if ch in df.index:
        path(df, df.loc[ch]['to'], res + [df.loc[ch]['to']])
    else:
        global pth
        pth = res
        return

import string    # we will use it below for get character  position in alphabet

for el in df.index:
    path(df,el,[el])
    print('->'.join(pth))

    # when you speak about indexes, looks you want to get the character index in alphabet
    # so here is my code
    print([string.ascii_lowercase.index(i)+1 for i in pth])
    print('') 

Out[1]:
b->a
[2, 1]

c->a
[3, 1]

d->a
[4, 1]

e->b->a
[5, 2, 1]

f->c->a
[6, 3, 1]

g->e->b->a
[7, 5, 2, 1]
1 голос
/ 11 июля 2020

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

data = {'from': ['b','c','d','e','f','g'], 'to': ['a', 'a', 'a', 'b','c','e']}
d = list(zip(data['from'], data['to']))
def get_paths(n, c = []):
   if n is None:
      yield from [i for k, _ in d for i in get_paths(k)]
   elif (r:=[b for a, b in d if a == n]):
      yield from [i for k in r for i in get_paths(k, c+[n])]
   else:
      yield c+[n]

result = list(get_paths(None))
#[['b', 'a'], ['c', 'a'], ['d', 'a'], ['e', 'b', 'a'], ['f', 'c', 'a'], ['g', 'e', 'b', 'a']]

Затем, чтобы преобразовать в целые числа:

from string import ascii_lowercase as al
new_results = [[al.index(b)+1 for b in i] for i in result]

Вывод:

[[2, 1], [3, 1], [4, 1], [5, 2, 1], [6, 3, 1], [7, 5, 2, 1]]
1 голос
/ 11 июля 2020

В одну сторону от networkx

import networkx as nx
 
G = nx.from_pandas_edgelist(df, 'from', 'to')
[[*nx.all_simple_paths(G, source=x, target='a')][0] for x in list('efg')]
[['e', 'b', 'a'], ['f', 'c', 'a'], ['g', 'e', 'b', 'a']]
0 голосов
/ 15 июля 2020

спасибо за ваши предложения. Ниже код работал у меня:

import networkx as nx
G = nx.from_pandas_edgelist(test,'From','To',create_using=nx.DiGraph())
all_paths = []
y = test['From'].unique()
for var in y:
 paths = nx.all_simple_paths(G,source = var ,target = 'XYZ')
 all_paths.extend(paths)
all_paths
...