liveBook · Manning

Graph density

As explained in Financial AI in Practice

Graph density is the proportion of possible edges that are present among a graph's nodes.

Graph density is the proportion of possible edges present among a graph’s nodes. A density of 1 means every node in the analyzed community is connected to every other node. section 9.3.3

In fraud analysis, density helps characterize communities detected with Louvain. Compare it with community size and counts of entity types—such as users, IPs, devices, phones, and cards—to investigate potentially suspicious groups. section 9.3.3

Listing 9.4 Preparing for detailed community analysis
if G is not None and partition is not None:
    # Group nodes by their community ID
    communities_dict_nodes = defaultdict(list)
    for node, comm_id in partition.items():
        communities_dict_nodes[comm_id].append(node)

    all_community_node_lists_sorted = [
        nodes for comm_id, nodes in sorted(communities_dict_nodes.items())
    ]

    print(f"Prepared {len(all_community_node_lists_sorted)} communities for detailed analysis.")

    # Define a function to analyze the characteristics of a single community
    def analyze_community_details_func(nodes_in_comm):
        """
        Calculates density, size, and node type counts for a given list of nodes
        representing a community within the graph G.
        """
        if not nodes_in_comm: 
            # Return default values for an empty community node list
            return [0.0, 0, {}] 

        # Create a subgraph containing only the nodes of the current community
        subgraph_comm = G.subgraph(nodes_in_comm)

        # Calculate the density of the subgraph
        # Density is the ratio of actual edges to all possible edges in the subgraph.
        density_comm = nx.density(subgraph_comm)

        # Get the size of the community (number of nodes)
        size_comm = len(nodes_in_comm)

        # Count the occurrences of each node type within this community
        type_counts_comm = defaultdict(int)
        for node_item in nodes_in_comm:
            # G.nodes[node_item] gives attributes of the node, including 'type'
            type_counts_comm[G.nodes[node_item].get('type', 'Unknown')] += 1

        return [density_comm, size_comm, dict(type_counts_comm)] # Return calculated metrics

    print("Function 'analyze_community_details_func' defined for community analysis.")
else:
    print("Graph G or partition not available. Skipping community analysis preparation.")
    all_community_node_lists_sorted = [] # Define for subsequent cells not to fail

Inspect the community-analysis function that calculates density alongside community size and node-type counts. section 9.3.3

How Financial AI in Practice covers it

How deep it goes
Defines density through community connectivity and identifies a value of one with a fully connected clique.
Examples
Calculates density for detected communities and compares it with their size and counts of users, IPs, devices, phones, and cards.
What it assumes
Assumes a constructed graph and Louvain-assigned community IDs; does not establish graph construction here.
What you can do after
Evaluate communities by considering density alongside size and node-type counts when investigating potentially suspicious groups.
How it connects
Connects graph density with graph subgraphs, Louvain community detection, and fraud detection.

Also explained in

Compare how 3 books explain graph density →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Financial AI in Practice. The section links point to the parts of the book it draws on.