尝试将 networkx 实现到图形场景中

Trying to implement networkx into graphicsscene

-------- companytrades.csv --------

date,Company1,Company2
1/2/2017,1001,1111
1/3/2017,1001,1100
1/4/2017,1111,1001
1/5/2017,1100,1001
1/6/2017,1011,1001
1/7/2017,1001,1111
1/8/2017,1111,1100
1/9/2017,1100,1011

我发现了一组 类 将 networkx 实现到图形场景中的很好的例子 GraphNetworkX.py

Node.py

Edge.py

我正在使用下面的代码来实现这三个模块

--------- netxgui.py --------

import pandas as pd
from numpy import *
import sys
from math import *
from PyQt4 import QtCore,QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import networkx as nx
import GraphNetworkX
from x import *

pf = pd.read_csv('/desktop/companytrades.csv',header=0,index_col=['date'])

#setup the needed variables
if __names__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    app.setStyle("Plastique")

class netx(QtGui.QDialog):
    def __init__(self):
        super(netx,self).__init__()
        self.uiNX = Ui_Form() 
        self.uiNX.setupUi(self)
        G = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
Pos = nx.spring_layout(g,scale=300)
scene = GraphNetworkx.GraphGraphicsScene(G=g,pos=Pos)
self.uiNX.neworkx_graphicsView.setScene(scene)

NX = netx()
NX.show()
sys.exit(exit(app.exec_())
app.deleteLater()

-------- x.py ------

from PyQt4 import QtCore,QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.unicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(1492,1029)
        self.networkx_graphicsView = QtGui.QGraphicsView(Form)
        self.networkx_graphicsView.setGeometry(QtCore.QRect(240,70,971,911))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(5)
        sizePolicy.setHeightForWidth(self.networkx_graphicsView.sizePolicy().hasHeightForWidth())
        self.networkx_graphicsView.setSizePolicy(sizePolicy)
        self.networkx_graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.networkx_graphicsView.setObjectName(_fromUtf8("networkx_graphicsView"))
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
    def retranslateUi(self,Form):
        Form.setWindowTitle(_translate("Form","Form",None))

我在实施时遇到问题。我遇到的问题是在 drawGraph 函数下的 GraphNetworkX 中。打印功能似乎与 n 一起正常工作,但我真的不明白用 i 替换它的原因。

    i = 0
    for n in G.nodes():
        #print str(pos[n][0]) + " " + str(pos[n][1])+ " "+str(n)
        self.addNode(pos[i][0], pos[i][1], n)
        i += 1

我做了一个实验,用 n 替换 i 并添加节点似乎有效,但后来我在添加边时遇到了问题。

    for e in G.edges():
        node1 = self.nodes[e[0]]
        node2 = self.nodes[e[1]]
        self.addEdge(node1, node2)

它一直说 e[0] 超出范围..考虑到 Nodes.py 函数是将 self.nodes 变成 Nodes.nodes 对象的列表,我想也许是每个对象内的占位符,但我不太确定。然后我尝试进行此更改:

node1 = e[0]
node2 = e[1] 

但后来我在 Edge.py 中收到错误,指出

 x1 = node1.centerX() 

一个整数没有函数 centerX()

我有点不知所措。有人可以帮助我理解这一点并帮助我让它发挥作用吗?

一个更简单的问题可能有助于获得答案。 (例如,您的 x.py 中没有任何内容与最后的问题相关)

首先,您可能遇到了一些命名空间重载(重命名相同的对象)。在 netxgui.py 中你有 import networkx as nx 但几行之后你声明了 class nx(QtGui.QDialog)。在此之后,您尝试调用 nx.spring_layout(),您可能希望它来自 networkx 而不是您的自定义 nx class。您尝试访问的结构可能存在于 networkx Graph 实例中,但不存在于 QDialog 实例中?

一般来说,避免使用 from examplemodule import * 将使您在尝试跟踪错误或仅在开发代码时更轻松。

--- 编辑 ---

我仔细看了看,问题是因为 networkx.Graph / .DiGraph 等和 GraphGraphicsScene 中使用的表示不同。 Networkx 在下面使用 字典 来存储节点(以及边)。 GraphGraphicsScene 使用 list 节点。

快速而肮脏的解决方案:如果您的节点被标记为从 0 开始并且具有连续序列,这些 恰好 兼容。

稍微更稳健的方法是像这样生成您自己的图表,可以通过以下方式实现:

def re_index_digraph(G_orig):
    remap = {i: n for (i,n) in enumerate(G_orig.nodes())}
    inv_remap = {v:k for k,v in remap.items()}
    G = nx.DiGraph()
    G.add_nodes_from(remap)
    remap_edges = [(inv_remap[src], inv_remap[sink]) for (src, sink) in G_orig.edges()]
    G.add_edges_from(remap_edges)
    return G

G_orig = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
G = re_index_digraph(G_orig)

然后像以前一样继续G。 (如果除了简单的节点名称和边之外还有其他属性,则需要相应地扩展重映射函数)。

除此之外,您可能需要投入大量精力来开发 GraphGraphicsScene 实施。