I'm working on a code snippet that generates a network graph.
def create_network(df, node, column_edge, column_edge1=None, column_edge2=None):
# select columns, remove NaN
df_edge1 = df[[node, column_edge]].dropna(subset=[column_edge]).drop_duplicates()
# To create connections between "node" who have the same "edge",
# join data with itself on the "node" column.
df_edge1 = df_edge1.merge(
df_edge1[[node, column_edge]].rename(columns={node:node+"_2"}),
on=column_edge
)
# By joining the data with itself, node will have a connection with themselves.
# Remove self connections, to keep only connected nodes which are different.
edge1 = df_edge1[~(df_edge1[node]==df_edge1[node+"_2"])].dropna()[[node, node +"_2", column_edge]]
# To avoid counting twice the connections (person 1 connected to person 2 and person 2 connected to person 1)
# we force the first ID to be "lower" then ID_2
edge1.drop(edge1.loc[edge1[node+"_2"]<edge1[node]].index.tolist(), inplace=True)
G = nx.from_pandas_edgelist(df=edge1, source=node, target=node + '_2', edge_attr=column_edge)
G.add_nodes_from(nodes_for_adding=df[node].tolist())
if column_edge1:
df_edge2 = df[[node, column_edge1]].dropna(subset=[column_edge1]).drop_duplicates()
df_edge2 = df_edge2.merge(
df_edge2[[node, column_edge1]].rename(columns={node:node+"_2"}),
on=column_edge1
)
edge2 = df_edge2[~(df_edge2[node]==df_edge2[node+"_2"])].dropna()[[node, node+"_2", column_edge1]]
edge2.drop(edge2.loc[edge2[node+"_2"]<edge2[node]].index.tolist(), inplace=True)
# Create the connections in the graph
links_attributes = {tuple(row[[node, node+"_2"]]): {column_edge1: row[column_edge1]} for i,row in edge2.iterrows()}
# create the connection, without attribute.
G.add_edges_from(links_attributes)
# adds the attribute.
nx.set_edge_attributes(G=G, values=links_attributes)
if column_edge2:
df_edge3 = df[[node, column_edge2]].dropna(subset=[column_edge2]).drop_duplicates()
df_edge3 = df_edge3.merge(
df_edge3[[node, column_edge2]].rename(columns={node:node+"_2"}),
on=column_edge2
)
edge3 = df_edge3[~(df_edge3[node]==df_edge3[node+"_2"])].dropna()[[node, node+"_2", column_edge2]]
edge3.drop(edge3.loc[edge3[node+"_2"]<edge3[node]].index.tolist(), inplace=True)
# Create the connections in the graph
links_attributes2 = {tuple(row[[node, node+"_2"]]): {column_edge2: row[column_edge2]} for i,row in edge3.iterrows()}
# create the connection, without attribute.
G.add_edges_from(links_attributes2)
# adds the attribute.
nx.set_edge_attributes(G=G, values=links_attributes2)
return G
The above function takes dataframe, node, and one or more column edges and generates the graph using Networkx
python package.
Is there a better / more elegant / more accurate way to do this?