零基礎學習數據可視化pyecharts人物關係圖開發



Pyecharts人物關係圖開發

1. Pyecharts版本說明

Pyecharts的版本最新版本為1.7.0版本,此版本跟0.5版本的使用方法不一樣了。很多參數方法配置不一樣了。Import的內容也不一樣了。官方的例子主要是採用函數定義,方法採用鏈式傳導操作方法,參數配置項也有變化。建議使用json或字典模式,時候前後臺系統,更符合echart的開發思路,方便擴展。

2. 基礎人物關係圖開發說明

關係圖參數設置有兩種方法可以採用(函數參數和字典數據)。第一種方法利用python程序直接在代碼中設置各種參數,如下例所示:


零基礎學習數據可視化pyecharts人物關係圖開發

<code>import jsonimport osfrom pyecharts import options as optsfrom pyecharts.charts import Graph, Pageimport webbrowsernodes = [        opts.GraphNode(name="結點1", symbol_size=10),        opts.GraphNode(name="結點2", symbol_size=20),        opts.GraphNode(name="結點3", symbol_size=30),        opts.GraphNode(name="結點4", symbol_size=40),        opts.GraphNode(name="結點5", symbol_size=50),    ]links = [    opts.GraphLink(source="結點1", target="結點2",value=1,linestyle_opts=opts.LineStyleOpts(width=20)),    opts.GraphLink(source="結點2", target="結點3",value=2),    opts.GraphLink(source="結點3", target="結點4",value=3),    opts.GraphLink(source="結點4", target="結點5",value=4),    opts.GraphLink(source="結點5", target="結點1",value=5),]mygraph=Graph()mygraph.add("系列名稱",nodes,links,repulsion=8000,edge_label=opts.LabelOpts(                is_show=True,                position="middle",                formatter="{b} {c}"))mygraph.set_global_opts(title_opts=opts.TitleOpts(title="Graph-基本示例"))mygraph.render()webbrowser.open("render.html")/<code>
零基礎學習數據可視化pyecharts人物關係圖開發

圖 1 函數參數配置人物關係圖

(1) 節點和鏈路

利用庫options函數的方法定義節點和鏈路,裡面有各種參數。這裡重點說明

linestyle_opts=opts.LineStyleOpts(width=20))

在線段的參數設置中,利用options的子方法進行二級屬性的設置。

(2) 圖形添加屬性

在利用graph()生成圖形後,給圖形添加節點、鏈路和圖形的各種屬性。

(3) 具體函數參數設置

函數的參數非常多,需要參考官方的函數說明

https://pyecharts.org/#/

3. 高級人物關係圖開發說明

(1) 數據及參數來源

在官方的例子中,複雜數據後大量數據展示,採用的是讀取json數據格式。在json數據中利用字典形式定義了各種屬性和對應的值。這裡需要注意的就是,參數如果有二級的子參數設置,在json中,也需要在字典的形式。坑是,在json中這種字典的一級key不是參數配置方法的名字,而是一個函數定義的縮寫,大小寫跟參數配置的還有區別,如下所示。在鏈路設置中,線型的屬性設置用的是"lineStyle": {"width": 10} 這裡的lineStyle是函數名字的縮寫,函數名字是lineStyleopt,也沒看到說明。只能自己分析了。推薦採用這種字典方式設置參數,這個方法類似於echart,方便後臺數據與前臺UI交換數據,方便後期擴展

(2) json數據


<code>{    "categories": [        {            "name": "類目0"        },        {            "name": "類目1"        },        {            "name": "類目2"        },        {            "name": "類目3"        },        {            "name": "類目4"        },        {            "name": "類目5"        },        {            "name": "類目6"        },        {            "name": "類目7"        },        {            "name": "類目8"        }    ],    "nodes": [        {            "id": "0",            "name": "張零",            "symbolSize": 10,            "value": 28.685715,            "label": {                "normal": {                    "show": true                }            },            "category": 0        },        {            "id": "1",            "name": "張一",            "symbolSize": 15,            "value": 4,            "label": {                "normal": {                    "show": true                }            },            "category": 0        },        {            "id": "2",            "name": "張二二",            "symbolSize": 20,            "value": 9.485714,            "label": {                "normal": {                    "show": true                }            },            "category": 1        },        {            "id": "3",            "name": "張三三",            "symbolSize": 25,            "value": 9.485714,            "label": {                "normal": {                    "show": true                }            },            "category": 1        },        {            "id": "4",            "name": "CountessDeLo",            "symbolSize": 30,            "value": 4,            "label": {                "normal": {                    "show": true                }            },            "category": 0        },        {            "id": "5",            "name": "Geborand",            "symbolSize": 35,            "value": 4,            "label": {                "normal": {                    "show": true                }            },            "category": 0        },        {            "id": "6",            "name": "Champtercier",            "symbolSize": 40,            "value": 4,            "label": {                "normal": {                    "show": true                }            },            "category": 0        }    ],    "links": [        {            "id": "0",            "source": "1",            "target": "0",            "lineStyle":{"width": 20}        },        {            "id": "1",            "source": "2",            "target": "0",            "lineStyle": {"width": 10}        },        {            "id": "2",            "source": "3",            "target": "0"        },        {            "id": "3",            "source": "3",            "target": "2"        },        {            "id": "4",            "source": "4",            "target": "0"        },        {            "id": "5",            "source": "5",            "target": "0"        },        {            "id": "6",            "source": "6",            "target": "0"        }    ]}/<code>

(3) 調用json代碼

調用json方法,利用字典傳遞參數

<code>import jsonimport osfrom pyecharts import options as optsfrom pyecharts.charts import Graph, Pageimport webbrowserdef graph_les_miserables():    with open("les-miserables.json", "r", encoding="utf-8") as f:        j = json.load(f)        nodes = j["nodes"]        links = j["links"]        categories = j["categories"]    print(nodes)    print(links)    c = (        Graph(init_opts=opts.InitOpts(width="1000px", height="600px"))        .add(            "",            nodes=nodes,            links=links,            categories=categories,            layout="circular", #圓形            is_rotate_label=True,            linestyle_opts=opts.LineStyleOpts(color="source", curve=0.3),            label_opts=opts.LabelOpts(position="right"),        )        .set_global_opts(            title_opts=opts.TitleOpts(title="Graph-Les Miserables"),            legend_opts=opts.LegendOpts(                orient="vertical", pos_left="2%", pos_top="20%"            ),        )    )    return cmygraph=graph_les_miserables()mygraph.render()webbrowser.open("render.html")/<code>
零基礎學習數據可視化pyecharts人物關係圖開發

圖 2 json參數配置人物關係圖

4. 紅樓夢人物關係圖

(1) 思路

數據源:

1  第一種方法,讀取文本,截詞分析,利用csv建立人物關係的矩陣圖。

2  第二種方法,模擬矩陣人物關係矩陣。

數據讀取

3  利用pandas讀取矩陣數據

4  類似於json,利用pandas,把第一類轉換為node,把行轉換為link。

數據填充

5  利用字典形式填充人物關係圖,利用字典數據配置各種參數。

6  生成人物關係圖。

零基礎學習數據可視化pyecharts人物關係圖開發

圖 3 人物關係矩陣

(2) 代碼

<code>from pyecharts import options as optsfrom pyecharts.charts import Graph, Pageimport webbrowserimport randomimport pandas as pdimport jiebaimport jieba.posseg as pseg# 構建一個模擬數據集,矩陣形式#停用詞stopwords = [line.strip() for line in open('baidu_stopwords.txt',encoding='UTF-8').readlines()]#數據來源一:讀取小說f=open("紅樓夢.txt","r",encoding="utf-8")jieba.load_userdict("紅樓夢人名錶.txt")#加載人物表names = {}#  保存人物,鍵為人物名稱,值為該人物在全文中出現的次數relationships = {}#保存人物關係的有向邊,鍵為有向邊的起點,值為一個字典 edge ,edge 的鍵為有向邊的終點,值是有向邊的權值lineNames = []# 緩存變量,保存對每一段分詞得到當前段中出現的人物名稱for line in f.readlines():        poss = pseg.cut(line)  # 分詞,返回詞性        lineNames.append([])  # 為本段增加一個人物列表        for w in poss:            if w.flag != 'nr' or len(w.word) < 2 or w.word in stopwords:                continue  # 當分詞長度小於2或該詞詞性不為nr(人名)時認為該詞不為人名            lineNames[-1].append(w.word)  # 為當前段的環境增加一個人物            if names.get(w.word) is None:  # 如果某人物(w.word)不在人物字典中                names[w.word] = 0                relationships[w.word] = {}            names[w.word] += 1f.close()# 對於 lineNames 中每一行,我們為該行中出現的所有人物兩兩相連。如果兩個人物之間尚未有邊建立,則將新建的邊權值設為 1,# 否則將已存在的邊的權值加 1。這種方法將產生很多的冗餘邊,這些冗餘邊將在最後處理。for line in lineNames:    for name1 in line:        for name2 in line:            if name1 == name2:                continue            if relationships[name1].get(name2) is None:                relationships[name1][name2] = 1            else:                relationships[name1][name2] = relationships[name1][name2] + 1#構建人物關係矩陣#行row_name={}for key0,value0 in relationships.items():    for key1,value1 in value0.items():        if value1>100: #設置門限,關係10次以上的提取            #print(key0,key1,value1)            row_name[key0]=row_name.get(key0,0)+1            row_name[key1]=row_name.get(key1,0)+1#row_nameprint(len(row_name))namepd0=pd.DataFrame()namepd0['name']=list(row_name.keys())print(namepd0.tail(10))#%%#列for i in row_name.keys():    col_name=i    col_data=[ ]    for j in row_name.keys():        if relationships[i].get(j)!=None and relationships[i].get(j)>100:           col_data.append(relationships[i][j])        else:            col_data.append(0)    namepd0[col_name]=col_datanamepd0.to_csv("data.csv",index=False)namepd0##%%#第二種方案,模擬隨機產生矩陣數據N=6x1=[]mypd0=pd.DataFrame()for i in range(0,N):    x1.append("張三"+str(i))mypd0["name"]=x1for i in range(0,N):    x2=[]    for j in range(0,N):        if i==j:            x2.append(0)        else:            x2.append(random.randint(0,6))    mypd0[x1[i]]=x2mypd0.to_csv("data.csv",index=False)mypd0/<code>
<code>#====================# 讀取數據集mypd2 = pd.read_csv("data.csv")print(mypd2)print("**" * 10)# 構建關係圖節點# 分類my_categories = [{"name": "類目0"},    { "name": "類目1"    },    {  "name": "類目2"    },    { "name": "類目3"    },    {"name": "類目4"    },    {"name": "類目5"    },    {"name": "類目6"    }]# node數據name = list(mypd2['name'])  # 節點名稱mynode1 = []for i in range(0, mypd2.shape[0]):  # 節點    mynode0 = {        "id": str(i),        "name": name[i],        "symbolSize": 10,        "value": 28.685715,        "label": {            "normal": { "show": "true"}        },        "category": random.randint(0,7) #分類    }    mynode1.append(mynode0)print(mynode1)# link數據mylink1 = []for i in range(0, mypd2.shape[0]):  # 行    source_node = mypd2.iloc[i, 0]  # 第一個數據為 人物姓名,做源節點    for j in range(1, mypd2.shape[1]):  # 列        des_node = name[j - 1]  # 目標人物姓名        w = mypd2.iloc[i, j]  # 線的權重        # print(i,jsource_node,des_node,w)        if w==0:            continue        mylink0 = {                    "id":str(i*(mypd2.shape[1]-1)+(j-1)),                    "source": str(i),                     "target": str(j-1),                     "lineStyle": {"width":1} # str(w/10*4)                   }        mylink1.append(mylink0)print(mylink1)#構建圖形函數def graph_les_miserables(nodes,links,categories):    print("**"*20)    print(nodes)    print(links)    c = (        Graph(init_opts=opts.InitOpts(width="1000px", height="600px"))        .add(            "",            nodes=nodes,            links=links,            categories=categories,            layout="circular", #圓形            is_rotate_label=True,            linestyle_opts=opts.LineStyleOpts(color="source", curve=0.2), #公共線條屬性            label_opts=opts.LabelOpts(position="right"),        )        .set_global_opts(            title_opts=opts.TitleOpts(title="人物關係圖"),            legend_opts=opts.LegendOpts(                orient="vertical", pos_left="2%", pos_top="20%"            ),        )    )    return c#生成圖形mygraph=graph_les_miserables(mynode1,mylink1,my_categories)mygraph.render()webbrowser.open("render.html")/<code> 


零基礎學習數據可視化pyecharts人物關係圖開發

圖 4 紅樓夢人物關係圖

零基礎學習數據可視化pyecharts人物關係圖開發

圖 5 隨機數人物關係圖



分享到:


相關文章: