Visualizing in Python for less-than-conventional datasets

Domain
Technology

The idea that the easiest way to learn something new is to enjoy doing it and I suppose… this new endeavour bolstered by love, faith and humility(?) would be the easiest way to learn something new too. Let’s go, insyaAllah.

# Required libraries
import matplotlib.pyplot as plt
import networkx as nx
from matplotlib.patches import Patch

# Node definitions
nodes = [
    "Rub their shoulders",
    "Kiss her cheek",
    "Hold her hand",
    "Kiss her forehead",
    "Give her a foot rub",
    "Tickle her knees",
    "Pat her back",
    "Stare into her eyes",
    "Play footsie",
    "Give her a long hug",
    "Cuddle on the couch",
    "Touch shoulders in passing",
    "Hug for no reason",
    "Hold hands when on a walk",
    "Have a secret handshake",
    "Snuggle",
    "Rest her head on your shoulder",
    "Sit close as we watch something together",
    "Tickle her",
    "Give her a high five",
]

# Create a graph and add the nodes
G = nx.Graph()
G.add_nodes_from(nodes)

# Define the clusters
clusters = {
    "Upper body": ["Rub their shoulders", "Pat her back", "Touch shoulders in passing", "Rest her head on your shoulder", "Kiss her cheek", "Kiss her forehead"],
    "Hands": ["Hold her hand", "Hold hands when on a walk", "Have a secret handshake", "Give her a high five"],
    "Lower body": ["Give her a foot rub", "Play footsie", "Tickle her knees"],
    "Full body": ["Give her a long hug", "Cuddle on the couch", "Hug for no reason", "Snuggle", "Sit close as we watch something together", "Tickle her"],
    "Undefined": [node for node in G.nodes() if node not in sum(clusters.values(), [])],
}

# Define the colors
colors = {
    "Upper body": "#a8dadc88",
    "Hands": "#f1faee88",
    "Lower body": "#e6394688",
    "Full body": "#a8d8ea88",
    "Undefined": "#457b9d88",
}

# Define a central node
central_node = "Physical Touch as a Love Language"

# Add the central node to the graph
G.add_node(central_node)

# Connect all other nodes to the central node
for node in nodes:
    G.add_edge(node, central_node)

# Assign a color to each node based on its cluster or if it's the central node
node_colors = []
for node in G.nodes():
    if node == central_node:
        node_colors.append("#b39ddb88")  # central node color with alpha
    else:
        for cluster, nodes in clusters.items():
            if node in nodes:
                node_colors.append(colors[cluster])  # cluster color with alpha
                break

# Compute positions for all nodes, including the new central node
pos = nx.spring_layout(G, seed=42)

# Create the legend
legend_elements = [Patch(facecolor=color[:-2], edgecolor='k', label=cluster) for cluster, color in colors.items()]

# Adjust the color and width of the edges
edge_colors = ["#333333" for edge in G.edges()]  # dark gray
edge_widths = [0.5 for edge in G.edges()]  # thinner lines

# Create the figure
fig = plt.figure(figsize=(19.20, 11.80))  # increased height to accommodate larger bottom padding

# Create an Axes object with specified margins
ax = plt.axes([0.05, 0.1, 0.9, 0.8])  # left, bottom, width, height

# Draw the graph without labels on the Axes object
nx.draw(G, pos, node_color=node_colors, node_size=2000, edge_color=edge_colors, width=edge_widths, linewidths=1, with_labels=False, ax=ax)

# Draw the labels separately with custom font sizes on the Axes object
for node, (x, y) in pos.items():
    if node == central_node:
        ax.text(x, y, node, fontsize=15, color='black', ha='center', va='center')
    else:
        ax.text(x, y, node, fontsize=8, color='black', ha='center', va='center')

# Add the custom legend at the bottom on the Axes object
ax.legend(handles=legend_elements, loc="lower center", bbox_to_anchor=(0.5, -0.05), ncol=len(legend_elements))

# Save the figure
plt.savefig('network_graph.png', format='PNG')