#python #graph #networkx
#python #График #networkx
Вопрос:
Я хотел бы найти соединение узла между узлом 1 и остальными узлами в графе. Формат входного текстового файла выглядит следующим образом:
1 2 1
1 35 1
8 37 1
и так далее для 167 строк. Первый столбец представляет исходный узел, второй столбец представляет узел назначения, а последний столбец представляет вес ребра.
Я пытаюсь прочитать исходные, целевые узлы из входного файла и сформировать границу между ними. Затем мне нужно выяснить, является ли это подключенной сетью (только один компонент graph и никаких подкомпонентов). Вот код
from numpy import*
import networkx as nx
G=nx.empty_graph()
for row in file('out40.txt'):
row = row.split()
src = row[0]
dest = row[1]
#print src
G.add_edge(src, dest)
print src, dest
for i in range(2, 41):
if nx.bidirectional_dijkstra(G, 1, i): print "path exists from 1 to ", i
добавление ребер вручную с помощью
G.add_edge(1, 2)
работает, но утомительно и не подходит для больших входных файлов, таких как мой. Условие цикла if работает, когда я добавляю ребра вручную, но выдает следующую ошибку для приведенного выше кода:
in neighbors_iter
raise NetworkXError("The node %s is not in the graph."%(n,))
networkx.exception.NetworkXError: The node 2 is not in the graph.
Любая помощь будет высоко оценена!
Ответ №1:
В вашем коде вы добавляете узлы "1"
и "2"
так далее (поскольку чтение из файла даст вам строки, если вы явно не преобразуете их).
Однако затем вы пытаетесь ссылаться на узлы 1
и 2
. Я предполагаю, что networkx
это так не думает 2 == "2"
.
Попробуйте изменить это…
G.add_edge(src, dest)
для этого:
G.add_edge(int(src), int(dest))
Комментарии:
1. @bhanu: если это правильное решение для вас, пожалуйста, отметьте его как таковое (и проголосуйте за полезные ответы)
2. @Rabarberski Я это сделал! Спасибо.
Ответ №2:
Не уверен, что это вариант для вас, но знаете ли вы о встроенной поддержке networkx для нескольких текстовых форматов graph?
Формат списка ребер, похоже, довольно хорошо подходит для вашего случая. В частности, следующий метод будет считывать ваши входные файлы без необходимости использования пользовательского кода:
G = nx.read_weighted_edgelist(filename)
Если вы хотите удалить веса (потому что они вам не нужны), вы можете впоследствии выполнить следующее:
for e in G.edges_iter(data=True):
e[2].clear() #[2] is the 3rd element of the tuple, which
#contains the dictionary with edge attributes
Комментарии:
1. Спасибо, я не заглядывал в нее. Я изучу это.
2. Я отредактировал свой ответ,
read_weighted_edgelist()
я думаю, что метод — это именно то, что вам нужно.3. Отлично! Я думаю, что буду использовать это в будущем, когда буду работать с взвешенными ребрами. В настоящее время работаю с невзвешенными ребрами. Спасибо!
Ответ №3:
Из Networkx
документации:
for row in file('out40.txt'):
row = row.split()
src = row[0]
dest = row[1]
G.add_nodes_from([src, dest])
#print src
G.add_edge(src, dest)
print src, dest
В сообщении об ошибке говорится, что в графике G
нет узлов, которые вы хотите создать между ними.
Комментарии:
1. Янтарь ответил на это! Я не преобразовал его в целое число. Спасибо!
Ответ №4:
Вы также можете использовать «is_connected()», чтобы сделать это немного проще. например
$ cat disconnected.edgelist
1 2 1
2 3 1
4 5 1
$ cat connected.edgelist
1 2 1
2 3 1
3 4 1
$ ipython
In [1]: import networkx as nx
In [2]: print(nx.is_connected(nx.read_weighted_edgelist('disconnected.edgelist')))
False
In [3]: print(nx.is_connected(nx.read_weighted_edgelist('connected.edgelist')))
True
Комментарии:
1. Спасибо @aric, я использую ‘nx.number_connected_components (G)’, чтобы определить, подключен ли граф или нет. Однако я хотел бы знать, есть ли способ объединить два несвязанных компонента графика. Знаете ли вы о каком-либо подходе? Спасибо.
Ответ №5:
Другой вариант — загрузить файл в виде фрейма данных pandas, а затем использовать iterrows
для итерации:
import pandas as pd
import networkx as nx
cols = ["src", "des", "wei"]
df = pd.read_csv('out40.txt', sep=" ", header=None, names=cols)
G = nx.empty_graph()
for index, row in df.iterrows():
G.add_edge(row["src"], row["des"])