code: def build_cooccurrence_network(
      data: Sequence[str] | Sequence[Sequence[str]],
      *,
      window_size: int = 2,
      edge_weighting: Literal["count", "binary"] = "count",
  ) -> nx.Graph:
      """
      Transform an ordered sequence of strings (or a sequence of such sequences)
      into a graph, where each string is represented by a node with weighted edges
      linking it to other strings that co-occur within ``window_size`` elements of itself.
  
      Input ``data`` can take a variety of forms. For example, as a ``Sequence[str]``
      where elements are token or term strings from a single document:
  
      .. code-block:: pycon
  
          >>> texts = [
          ...     "Mary had a little lamb. Its fleece was white as snow.",
          ...     "Everywhere that Mary went the lamb was sure to go.",
          ... ]
          >>> docs = [make_spacy_doc(text, lang="en_core_web_sm") for text in texts]
          >>> data = [tok.text for tok in docs[0]]
          >>> graph = build_cooccurrence_network(data, window_size=2)
          >>> sorted(graph.adjacency())[0]
          ('.', {'lamb': {'weight': 1}, 'Its': {'weight': 1}, 'snow': {'weight': 1}})
  
      Or as a ``Sequence[Sequence[str]]``, where elements are token or term strings
      per sentence from a single document:
  
      .. code-block:: pycon
  
          >>> data = [[tok.text for tok in sent] for sent in docs[0].sents]
          >>> graph = build_cooccurrence_network(data, window_size=2)
          >>> sorted(graph.adjacency())[0]
          ('.', {'lamb': {'weight': 1}, 'snow': {'weight': 1}})
  
      Or as a ``Sequence[Sequence[str]]``, where elements are token or term strings
      per document from multiple documents:
  
      .. code-block:: pycon
  
          >>> data = [[tok.text for tok in doc] for doc in docs]
          >>> graph = build_cooccurrence_network(data, window_size=2)
          >>> sorted(graph.adjacency())[0]
          ('.',
           {'lamb': {'weight': 1},
            'Its': {'weight': 1},
            'snow': {'weight': 1},
            'go': {'weight': 1}})
  
      Note how the "." token's connections to other nodes change for each case. (Note
      that in real usage, you'll probably want to remove stopwords, punctuation, etc.
      so that nodes in the graph represent meaningful concepts.)
  
      Args:
          data
          window_size: Size of sliding window over ``data`` that determines
              which strings are said to co-occur. For example, a value of 2 means that
              only immediately adjacent strings will have edges in the network;
              larger values loosen the definition of co-occurrence and typically
              lead to a more densely-connected network.
  
              .. note:: Co-occurrence windows are not permitted to cross sequences.
                 So, if ``data`` is a ``Sequence[Sequence[str]]``, then co-occ counts
                 are computed separately for each sub-sequence, then summed together.
  
          edge_weighting: Method by which edges between nodes are weighted.
              If "count", nodes are connected by edges with weights equal to
              the number of times they co-occurred within a sliding window;
              if "binary", all such edges have weight set equal to 1.
  
      Returns:
          Graph whose nodes correspond to individual strings from ``data``;
          those that co-occur are connected by edges with weights determined
          by ``edge_weighting``.
  
      Reference:
          https://en.wikipedia.org/wiki/Co-occurrence_network
      """
      if not data:
          LOGGER.warning(
              "input `data` is empty, so output graph is also empty"
          )
          return nx.Graph()
  
      if window_size < 2:
          raise ValueError(
              f"window_size = {window_size} is invalid; value must be >= 2"
          )
  
      # input data is Sequence[str]
      if isinstance(data[0], str):
          windows = itertoolz.sliding_window(
              min(window_size, len(data)), data
          )
      # input data is Sequence[Sequence[str]]
      elif isinstance(data[0], Sequence) and isinstance(
          data[0][0], str
      ):
          windows = itertoolz.concat(
              itertoolz.sliding_window(
                  min(window_size, len(subseq)), subseq
              )
              for subseq in data
          )
      else:
          raise TypeError(
              errors.type_invalid_msg(
                  "data",
                  data,
                  Union[Sequence[str], Sequence[Sequence[str]]],
              )
          )
  
      graph = nx.Graph()
      if edge_weighting == "count":
          cooc_counts = collections.Counter(
              w1_w2
              for window in windows
              for w1_w2 in itertools.combinations(sorted(window), 2)
          )
          graph.add_edges_from(
              (w1, w2, {"weight": weight})
              for (w1, w2), weight in cooc_counts.items()
          )
      elif edge_weighting == "binary":
          edge_data = {"weight": 1}
          graph.add_edges_from(
              (w1, w2, edge_data)
              for window in windows
              for (w1, w2) in itertools.combinations(window, 2)
          )
      else:
          raise ValueError(
              errors.value_invalid_msg(
                  "edge_weighting", edge_weighting, {"count", "binary"}
              )
          )
  
      return graph
  
file_path: textacy/src/textacy/representations/network.py
imports: from __future__ import annotations
  import collections
  import itertools
  import logging
  from operator import itemgetter
  from typing import Any, Collection, Literal, Optional, Sequence, Union
  import networkx
  import numpy
  from cytoolz import itertoolz
  from ..None import errors, similarity
label_desc: Use image node_id 1 for calling a global function with example usage: build_cooccurrence_network(data) and returns: graph, nx