Physik der sozio-ökonomischen Systeme mit dem Computer

(Physics of Socio-Economic Systems with the Computer)

Vorlesung gehalten an der J.W.Goethe-Universität in Frankfurt am Main

(Wintersemester 2020/21)

von Dr.phil.nat. Dr.rer.pol. Matthias Hanauske

Frankfurt am Main 02.11.2020

Zweiter Vorlesungsteil:

Zitations- und Autorennetzwerke

Einführung

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:

In [15]:
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):

In [2]:
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
Anzahl der veröffentlichten Artikel
63
Anzahl der Koautoren die einen Google Scholar Account haben
20

Wir erstellen den bipartiten Graphen in NetworkX

In [3]:
import networkx as nx
from networkx.algorithms import bipartite

und kennzeichnen die Autorenknoten durch ihren Namen

In [4]:
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.

In [5]:
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

In [6]:
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.

In [7]:
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.

In [8]:
print("Anzahl der Koautoren (unter Umständen Mehrfachnennungen)")
print(len(AutorList))
Anzahl der Koautoren (unter Umständen Mehrfachnennungen)
90

Wir separieren die bipartiten Knoten in zwei separate Listen

In [9]:
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

In [10]:
pos=nx.fruchterman_reingold_layout(B)
In [11]:
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]       
In [12]:
import plotly.graph_objects as go
In [13]:
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'
               )
In [14]:
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()