In diesem Jupyter Notebook wird ein Beispiel eines multipartiten Netzwerks betrachtet, das sogenannte Zitations-Autorennetzwerk. In multipartiten Netzwerken kann man die Menge der Netzwerkknoten ${\bf \cal I}$ in disjunkte Teilmengen gliedern. Wir betrachten im folgenden den wissenschaftlichen Informationsmarkt, indem Autoren (Teilmenge ${\bf \cal A}= \left\{ A, B, ...\right\}$ der Netzwerkknoten) wissenschaftliche Artikel/Papers (Teilmenge ${\bf \cal P}= \left\{ p_1, p_2, ...\right\}$ der Netzwerkknoten) schreiben und in wissenschaftlichen Journalen (Teilmenge ${\bf \cal J}$ der Netzwerkknoten) veröffentlichen. Wir beschränken uns jedoch hierbei auf ein bipartites Netzwerk und betrachten lediglich das Autoren-Zitationsnetzwerk ((${\bf \cal I} = {\bf \cal A} \cup {\bf \cal P}$)).
Neben diesen unterschiedlichen Knotenarten existieren auch unterschiedliche Kanten in diesem bipartitem Netzwerk. Die Kanten welche die Autoren miteinander verbinden kennzeichnen Koautorenschaften die entstehen können, wenn man einen gemeinsamen Artikel schreibt; diese Kanten haben zahlenmäßige Gewichtung (wieviele Artikel man zusammen geschrieben hat) und sind ungerichtet. Kanten, die Autorenknoten mit Artikelknoten miteinander verknüpfen sind ungerichtet und ungewichtet und kennzeichnen einfach das dieser Autor diesen Artikel geschrieben hat. Diejenige Kanten, die Artikel miteinander verbinden sind dagegen gerichtet und ungewichtet und kennzeichnen das ein Artikel einen anderen zitiert.
Heutzutage können Autoren-Zitationsnetzwerke relativ einfach dargestellt werden da es öffentlich zugängliche, digitale Autoren-Zitationsdatebanken gibt (z.B. Google Scholar). Unser erstes Beispiel betrachtet mein eigenes Autoren-Zitationsnetzwerk:
from scholarly import scholarly
search_query = scholarly.search_author('Matthias Hanauske')
author = next(search_query).fill()
#print(author)
Die von Google Scholar bereitgestellten Daten beinhalten unter anderem die wesentlichen Eigenschaften der veröffentlichten Artikel, als auch eine Liste der Koautoren (hier jedoch nur diejenigen Koautoren, die ebenfalls einen Google Scholar Account haben):
print("Anzahl der veröffentlichten Artikel")
NP=len(author.publications)
print(NP)
print("Anzahl der Koautoren die einen Google Scholar Account haben")
NCoA=len(author.coauthors)
print(NCoA)
#aa=author.publications[1]
#aa.bib['title']
#aa
Wir erstellen den bipartiten Graphen in NetworkX
import networkx as nx
from networkx.algorithms import bipartite
und kennzeichnen die Autorenknoten durch ihren Namen
B = nx.Graph()
citedby=author.citedby
B.add_node(author.name, bipartite=0, cites=citedby)
for koaut in author.coauthors:
B.add_node(koaut.name, bipartite=0)
und die Papers durch ihren Titel.
for papers in author.publications:
# print(papers.bib['title'])
B.add_node(papers.bib['title'], bipartite=1, cites=int(papers.bib['cites']))
Wir kennzeichnen die Koautorenverbindungen durch ungerichtete Kanten
AutorList=[]
for koaut in author.coauthors:
B.add_edge(author.name,koaut.name)
AutorList.append(koaut.name)
Zusätzlich fügen wir diejenigen Autoren welche keinen Scholar Account haben ebenfalls zum Netzwerk und kennzeichnen die Zugehörigkeit der Artikel zu den Autoren ebenfalls als ungerichtete Kanten. Autorennamen können manchmal unterschiedlich geschrieben werden; hierzu kann man per Hand Änderungen einfügen (siehe z.B. Matthias Hanauske, M Hanauske, Matthias HANAUSKE) - diese Ausnahmen sind bei einigen Autoren per Hand korrigiert.
import itertools
for papers in author.publications:
B.add_edge(author.name,papers.bib['title'])
paperAuth=papers.fill().bib['author']
paperAuthList=paperAuth.split(" and ")
if 'Matthias HANAUSKE' in paperAuthList:
ind=paperAuthList.index('Matthias HANAUSKE')
paperAuthList[ind]='Matthias Hanauske'
if 'M Hanauske' in paperAuthList:
ind=paperAuthList.index('M Hanauske')
paperAuthList[ind]='Matthias Hanauske'
if 'W Greiner' in paperAuthList:
ind=paperAuthList.index('W Greiner')
paperAuthList[ind]='Walter Greiner'
if 'Horst Stöcker' in paperAuthList:
ind=paperAuthList.index('Horst Stöcker')
paperAuthList[ind]='Horst Stoecker'
if 'H Stoecker' in paperAuthList:
ind=paperAuthList.index('H Stoecker')
paperAuthList[ind]='Horst Stoecker'
if 'H Stöcker' in paperAuthList:
ind=paperAuthList.index('H Stöcker')
paperAuthList[ind]='Horst Stoecker'
if 'Wolfgang Koenig' in paperAuthList:
ind=paperAuthList.index('Wolfgang Koenig')
paperAuthList[ind]='Wolfgang König'
if 'Wolfgang Köenig' in paperAuthList:
ind=paperAuthList.index('Wolfgang Köenig')
paperAuthList[ind]='Wolfgang König'
for koaut in paperAuthList:
if koaut not in AutorList:
AutorList.append(koaut)
B.add_node(koaut, bipartite=0)
B.add_edge(koaut,papers.bib['title'])
combin=list(itertools.combinations(paperAuthList, 2))
for i in range(0, len(combin)):
ed0=list(itertools.combinations(paperAuthList, 2))[i][0]
ed1=list(itertools.combinations(paperAuthList, 2))[i][1]
B.add_edge(ed0,ed1)
Die Gesamtzahl der nun existierenden Koautoren beinhaltet nun auch Doppelnennungen, da manchmal der Name der Koautoren in den Artikeln unterschiedlich geschrieben ist.
print("Anzahl der Koautoren (unter Umständen Mehrfachnennungen)")
print(len(AutorList))
Wir separieren die bipartiten Knoten in zwei separate Listen
Author_nodes = {n for n, d in B.nodes(data=True) if d["bipartite"] == 0}
Paper_nodes = set(B) - Author_nodes
Layout Spezifikation der Positionen der Knoten
pos=nx.fruchterman_reingold_layout(B)
nodeA_x=[]
nodeA_y=[]
nodeA_z=[]
for koaut in Author_nodes:
nodeA_x.append(pos[koaut][0])
nodeA_y.append(pos[koaut][1])
nodeA_z.append(0)
nodeP_x=[]
nodeP_y=[]
nodeP_z=[]
cites0=[]
for paper in Paper_nodes:
nodeP_x.append(pos[paper][0])
nodeP_y.append(pos[paper][1])
nodeP_z.append(1)
cites0.append(B.nodes[paper]["cites"])
edge_x = []
edge_y = []
edge_z = []
for edge in B.edges():
edge_x+=[pos[edge[0]][0],pos[edge[1]][0], None]
edge_y+=[pos[edge[0]][1],pos[edge[1]][1], None]
if edge[0] in Author_nodes and edge[1] in Author_nodes:
edge_z+=[0,0, None]
if edge[0] in Author_nodes and edge[1] in Paper_nodes:
edge_z+=[0,1, None]
if edge[0] in Paper_nodes and edge[1] in Author_nodes:
edge_z+=[1,0, None]
if edge[0] in Paper_nodes and edge[1] in Paper_nodes:
edge_z+=[1,1, None]
import plotly.graph_objects as go
edge_trace=go.Scatter3d(x=edge_x,
y=edge_y,
z=edge_z,
mode='lines',
line=dict(color='black', width=0.3),
hoverinfo='none'
)
nodeA_trace=go.Scatter3d(x=nodeA_x,
y=nodeA_y,
z=nodeA_z,
mode='markers',
name='Authors',
marker=dict(symbol='square',
size=5,
line=dict(color='black', width=0.1)
),
text=list(Author_nodes),
opacity=0.9,
hoverinfo='text'
)
nodeP_trace=go.Scatter3d(x=nodeP_x,
y=nodeP_y,
z=nodeP_z,
mode='markers',
name='Papers',
marker=dict(symbol='circle',
size=2,
color=cites0,
colorscale='Jet',
line=dict(color='black', width=0.1)
),
text=list(Paper_nodes),
opacity=0.9,
hoverinfo='text'
)
axis=dict(showbackground=False,
backgroundcolor="white",
showline=False,
zeroline=False,
showgrid=True,
gridcolor="rgb(244, 233, 245)",
showticklabels=False,
showaxeslabels=False,
)
layout = go.Layout(
width=700,
height=700,
showlegend=False,
scene=dict(
xaxis=dict(axis),
yaxis=dict(axis),
zaxis=dict(axis),
),
margin=dict(b=20,l=10,r=10,t=10),
hovermode='closest',
)
data=[nodeA_trace,nodeP_trace,edge_trace]
fig=go.Figure(data=data, layout=layout)
fig.show()