как сохранить определенный узел в networkx

В настоящее время я изучаю специальную тему в колледже. Моя проблема в том, что я могу удалить весь узел, который мне не нужен, но я хочу сохранить какой-то конкретный узел. Вот как я это делаю.

1.читать gml в networkx

2. используя этот код, чтобы удалить веб-сайт, который мне не нужен, а затем записать его в новый файл gml

import networkx as nx
G = nx.read_gml('test.gml')
for i in range(2000):
    for node in G.nodes:
        if "pu.edu.tw" not in node:
            G.remove_node(node)
            break
nx.write_gml(G,"finaltest.gml")

3. Как вы можете видеть часть этого gml-файла, я успешно сохраняю весь веб-сайт pu.edu.tw.

graph [
directed 1
multigraph 1
node [
  id 0
  label "https://www.pu.edu.tw/"
]
node [
  id 1
  label "https://alumni.pu.edu.tw/"
]
node [
  id 2
  label "https://freshman.pu.edu.tw/"
]
node [
  id 3
  label "https://tdc.pu.edu.tw/"
]
node [
  id 4
  label "https://alcat.pu.edu.tw/"
]
node [
  id 5
  label "https://www.secretary.pu.edu.tw/"
]
node [
  id 6
  label "https://pugive.pu.edu.tw/"
]

4. Проблема в том, что когда я пытаюсь нарисовать этот файл gml с помощью networkx, я получаю некоторые узлы без egdes введите здесь описание изображения

5. И я узнал, что причина в том, что я удалил ссылку, связанную с «pu.edu.tw», поэтому некоторые элементы отсутствуют.

Я хочу знать, как не только удалить веб-сайт, который мне не нужен, но и сохранить конкретный узел, связанный с «pu.edu.tw», чтобы края не пропадали. или какой-то способ переподключить node. Спасибо.

---------------------------------------------------------------------------------

обновить новый вопрос .... Что, если я хочу добавить несколько условий, например

def cleanup(g):
    g_aux = g.to_undirected()
        for node in g_aux.nodes:
            if ("tku.edu.tw"or"scu.edu.tw"or"cycu.edu.tw"or"fcu.edu.tw") not in node:
            for neighbor in g_aux.neighbors(node):
                if "tku.edu.tw"or"scu.edu.tw"or"cycu.edu.tw"or"fcu.edu.tw" in neighbor:
                    break
            else:
                g.remove_node(node)

это правильный способ сделать?


person KaiHung    schedule 01.12.2020    source источник
comment
Итак, эти сироты принадлежат 'pu.edu.tw', но были подключены только к узлам, которые не принадлежат этому веб-сайту, и вы хотите создать ребра, которые заменят такие непрямые соединения? Скажем, были узлы «A.pu.edu.tw» — B.oth — C.oth — D.pu.edu.tw, значит, вы хотите добавить ребро A — C?   -  person tyrrr    schedule 01.12.2020
comment
Да! это то, что я пытаюсь сделать прямо сейчас.   -  person KaiHung    schedule 02.12.2020
comment
Да, это способ сделать это, если вы хотите, чтобы узлы имели любой из этих идентификаторов.   -  person willcrack    schedule 22.12.2020


Ответы (3)


Одна вещь, которую вы можете сделать, это сохранить каждый узел, у соседа которого есть "pu.edu.tw" в его имени.

Вот полный код:

import networkx as nx

def cleanup(g):
    g_aux = g.to_undirected()
    for node in g_aux.nodes:
        if "pu.edu.tw" not in node:
            for neighbor in g_aux.neighbors(node):
                if "pu.edu.tw" in neighbor:
                    # Found
                    break
            else:
                # Didn't find pu.edu.tw in any neighbors
                g.remove_node(node)

G = nx.read_gml('test.gml')
cleanup(G)
nx.write_gml(G,"finaltest.gml")

Полученный результат — это каждый узел с "pu.edu.tw" и его соседи.
Обратите внимание, что я использовал неориентированную версию графа g_aux = g.to_undirected(), сохраняя каждого соседа "pu.edu.tw" независимо от направления соединяющего ребра.

Вот некоторый код, чтобы проверить, нет ли у какого-либо pu.edu.tw соседей:

def check_isolated(g):
    for node in g.nodes:
        if "pu.edu.tw" in node:
            if g.degree[node] == 0:
                print(node)

Если это выводит что-либо до запуска cleanup, то эти узлы всегда будут изолированы.

print(“before”)
check_isolated(g)
print(“cleaning...”)
cleanup(g)
print(“after”)
check_isolated(g)
person willcrack    schedule 02.12.2020
comment
Не будут ли пропускаться случаи, когда узлы с 'pw.edu.tw' соединены более чем через 2 узла без этой метки? - person tyrrr; 02.12.2020
comment
Да, это было бы. Он просто сохраняет в графе каждый узел, у соседа которого есть pu.edu.tw в его имени. - person willcrack; 02.12.2020
comment
@KaiHung, почему ты снял пометку с моего ответа? - person willcrack; 09.12.2020
comment
@willcrack извините, но есть еще несколько узлов, которые изолированы от других. - person KaiHung; 10.12.2020
comment
Удалось ли вам определить, почему? - person willcrack; 10.12.2020
comment
Вы проверили, не были ли эти изолированные узлы изолированы в исходном графе? - person willcrack; 10.12.2020
comment
Я добавил код для проверки этих узлов. - person willcrack; 10.12.2020
comment
Спасибо за ваш ответ. Код, который вы мне дали, не печатает ни одного узла. Или вы можете сказать мне, где я должен ввести код точно? - person KaiHung; 11.12.2020
comment
Я добавил код, объясняющий, что я имею в виду - person willcrack; 11.12.2020
comment
После переработки моего файла GML изолированного узла нет вообще. - person KaiHung; 13.12.2020
comment
1.что означает g_aux? 2. Значит, мне нужно изменить undirected на directed, если мой график Multigrpah? - person KaiHung; 15.12.2020
comment
1. Предполагается, что это вспомогательный граф. \\ 2. Я не думаю, что вам нужно что-то менять, если вы используете мультиграф - person willcrack; 15.12.2020
comment
Извините, но не могли бы вы прокомментировать, что означает каждый код? Спасибо :) - person KaiHung; 20.12.2020
comment
И когда я меняю ненаправленное на направленное, результат меняется. - person KaiHung; 20.12.2020
comment
Не могли бы вы опубликовать новый вопрос с подробностями? - person willcrack; 20.12.2020
comment
я добавил новый вопрос ниже - person KaiHung; 21.12.2020

Если вы хотите поддерживать только одно соединение от каждого узла-сироты, с ближайшим узлом из вашего подграфа, вы можете сделать следующее: после создания подграфа выполнить итерацию по узлам-сиротам и для каждого из них выполнить BFS алгоритм на исходном графике, останавливаясь, когда вы найти узел с меткой 'pw.edu.tw' и добавить новое ребро из этого узла в узел-сироту в подграфе. С BFS вы гарантированно найдете ближайший узел с нужным свойством.

Следующий код должен помочь:

import networkx as nx
from networkx.algorithms.traversal.breadth_first_search import bfs_edges

G = nx.read_gml('test.gml')

desired_nodes = [node for node in G.nodes if 'pu.edu.tw' in node]
subgraph = nx.Graph(G.subgraph(desired_nodes))

orphan_nodes = [node for node in subgraph.nodes if 
subgraph.degree[node] == 0]

for orphan in orphan_nodes:
    for _, neigh in bfs_edges(G, orphan):
        if 'pu.edu.tw' in neigh:
            subgraph.add_edge(neigh, orphan)
            break
            
nx.write_gml(subgraph,"finaltest.gml")

Я также изменил метод удаления узлов из графа — вместо двойного цикла, который вы реализовали, я сначала нахожу узлы с желаемым свойством со списком, а затем использую метод subgraph из networkx.Graph — он чище и будет работать для произвольных количество удаленных узлов (в отличие от циклов, о которых вы, вероятно, знаете). Таким образом, создается новый объект графа, а не удаляются ребра из старого, что необходимо для алгоритма, представленного выше.

person tyrrr    schedule 02.12.2020
comment
имя 'neigh' не определено - person willcrack; 02.12.2020
comment
@willcrack конечно, спасибо за редактирование! - person tyrrr; 02.12.2020
comment
Также G.subgraph(desired_nodes) вернет сообщение о том, что вы не можете изменить замороженный график, вероятно, потому, что они не хотят, чтобы вы рисковали испортить часть исходного графика. Вместо этого должно быть nx.Graph(G.subgraph(desired_nodes)). Нп ;) - person willcrack; 02.12.2020

Вот вопрос хочу задать....

g_aux = g.to_undirected() 

почему я должен использовать g_aux для запуска этой программы? я не понимаю, что на самом деле делает вспомогательный граф в NetworkX.

person KaiHung    schedule 20.12.2020
comment
g_aux это просто переменная, это неориентированная версия графа g - person willcrack; 21.12.2020
comment
Кроме того, для вас было бы предпочтительнее добавить редактирование к своему вопросу, чем задавать вопрос в сообщении с ответом. - person willcrack; 21.12.2020
comment
хорошо, я обновил новый вопрос в своем исходном сообщении, пожалуйста, проверьте это .... - person KaiHung; 22.12.2020
comment
Извините, не могу найти, можно ссылку сюда? - person willcrack; 22.12.2020
comment
просто проверьте мой исходный вопрос, я добавил обновление ниже - person KaiHung; 22.12.2020