From e8af38623349a7af3002a2f26c569854ef40bae0 Mon Sep 17 00:00:00 2001 From: Florian Mathieu Date: Tue, 11 Aug 2026 22:33:11 +0200 Subject: [PATCH] =?UTF-8?q?ajout=20activit=C3=A9=20sur=20X-Files=20&=20con?= =?UTF-8?q?tamination?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Seance_5_TP_Contamination.ipynb | 546 ++++++++++++++++++++++++++++++++ 1 file changed, 546 insertions(+) create mode 100644 Seance_5_TP_Contamination.ipynb diff --git a/Seance_5_TP_Contamination.ipynb b/Seance_5_TP_Contamination.ipynb new file mode 100644 index 0000000..dfce82e --- /dev/null +++ b/Seance_5_TP_Contamination.ipynb @@ -0,0 +1,546 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Séance 5 — TP : réseau d'affiliation et chaîne de contamination\n", + "\n", + "## Contexte\n", + "\n", + "Dans la première partie de la séance, vous avez travaillé sur le réseau d'ami·es\n", + "d'Alice et Bob : un réseau où **les liens sont directement observés** (« Alice connaît Bob »).\n", + "\n", + "Mais en sociologie, on dispose très rarement d'un tel réseau. Ce qu'on observe\n", + "concrètement, ce sont des **participations à des événements** : qui était à quelle\n", + "réunion, qui siège dans quel conseil d'administration, qui a signé quelle pétition,\n", + "qui était à quel dîner.\n", + "\n", + "Ce type de données forme un **réseau d'affiliation** (ou réseau *biparti*) : deux\n", + "types de nœuds — des **personnes** et des **événements** — et des liens qui vont\n", + "toujours d'une personne vers un événement, jamais de personne à personne.\n", + "\n", + "C'est une structure fondatrice de l'analyse de réseaux. L'étude qui l'a rendue\n", + "célèbre est celle de Davis, Gardner et Gardner (*Deep South*, 1941), qui reconstituait\n", + "la structure sociale d'une petite ville du sud des États-Unis à partir de la seule\n", + "présence de 18 femmes à 14 événements mondains, relevée dans la presse locale.\n", + "\n", + "## Le cas d'étude\n", + "\n", + "Nous reprenons ce principe sur un cas fictif : la commune de **Dudley**, organisée\n", + "autour d'une usine agroalimentaire. Plusieurs habitants sont tombés malades d'une\n", + "maladie transmise par l'alimentation. On ne sait pas qui a contaminé qui — mais on\n", + "dispose du registre des **repas communautaires** et de la liste de leurs participants.\n", + "\n", + "**Objectif : reconstituer la structure sociale à partir des seules participations,\n", + "puis identifier le groupe exposé.**\n", + "\n", + "## Objectifs pédagogiques\n", + "\n", + "- Construire et lire un **réseau d'affiliation** (graphe biparti)\n", + "- Comprendre ce qu'est la **projection** d'un réseau biparti en réseau unimode,\n", + " et ce qu'elle fait gagner et perdre\n", + "- Réinvestir les **composantes connexes** et le **parcours en largeur** vus en cours\n", + "- Interpréter sociologiquement une distance dans un réseau\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Les données\n", + "\n", + "Nous disposons de deux listes et d'un registre.\n", + "\n", + "**Les personnes** (habitants de Dudley et de la commune voisine de Millhaven) :\n", + "\n", + "| Personne | Commune | État de santé |\n", + "|---|---|---|\n", + "| Paula, Ray, Bonnie, Jess, Sam, Nancy | Dudley | **malades** |\n", + "| Walter, Curtis, Béatrice, Wendell | Dudley | en bonne santé |\n", + "| Doris, Martha, George | Dudley | en bonne santé |\n", + "| Marjorie, Harold, Irene | Millhaven | en bonne santé |\n", + "| Agnès | Millhaven | en bonne santé |\n", + "\n", + "**Les repas** enregistrés :\n", + "\n", + "| Repas | Date | Lieu |\n", + "|---|---|---|\n", + "| `R1988` | 17 septembre 1988 | Ferme Chaco (Dudley) |\n", + "| `R1989` | 24 juin 1989 | Salle des fêtes (Dudley) |\n", + "| `R1990` | 15 septembre 1990 | Ferme Chaco (Dudley) |\n", + "| `R1992` | 24 décembre 1992 | Église (Dudley) |\n", + "| `R1995` | 11 mars 1995 | Ferme Chaco (Dudley) |\n", + "| `M1991` | 8 mai 1991 | Foyer rural (Millhaven) |\n", + "\n", + "Le registre des participations est donné dans la cellule suivante.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# --- Les personnes -----------------------------------------------------\n", + "personnes = [\n", + " \"Paula\", \"Ray\", \"Bonnie\", \"Jess\", \"Sam\", \"Nancy\", # malades\n", + " \"Walter\", \"Curtis\", \"Beatrice\", \"Wendell\",\n", + " \"Doris\", \"Martha\", \"George\",\n", + " \"Marjorie\", \"Harold\", \"Irene\", \"Agnes\",\n", + "]\n", + "\n", + "malades = [\"Paula\", \"Ray\", \"Bonnie\", \"Jess\", \"Sam\", \"Nancy\"]\n", + "\n", + "# --- Les repas ---------------------------------------------------------\n", + "repas = [\"R1988\", \"R1989\", \"R1990\", \"R1992\", \"R1995\", \"M1991\"]\n", + "\n", + "# --- Le registre des participations ------------------------------------\n", + "# Chaque couple (personne, repas) signifie : cette personne etait a ce repas.\n", + "participations = [\n", + " (\"Paula\", \"R1988\"), (\"Ray\", \"R1988\"), (\"Bonnie\", \"R1988\"),\n", + " (\"Jess\", \"R1988\"), (\"Sam\", \"R1988\"), (\"Nancy\", \"R1988\"),\n", + " (\"Walter\", \"R1988\"), (\"Doris\", \"R1988\"), (\"Martha\", \"R1988\"),\n", + " (\"Curtis\", \"R1988\"), (\"Wendell\", \"R1988\"),\n", + "\n", + " (\"Paula\", \"R1989\"), (\"Ray\", \"R1989\"), (\"Bonnie\", \"R1989\"),\n", + " (\"Jess\", \"R1989\"), (\"Walter\", \"R1989\"), (\"Curtis\", \"R1989\"),\n", + " (\"Beatrice\", \"R1989\"), (\"Wendell\", \"R1989\"),\n", + "\n", + " (\"Paula\", \"R1990\"), (\"Ray\", \"R1990\"), (\"Sam\", \"R1990\"),\n", + " (\"Nancy\", \"R1990\"), (\"Walter\", \"R1990\"), (\"Curtis\", \"R1990\"),\n", + " (\"Wendell\", \"R1990\"), (\"George\", \"R1990\"),\n", + "\n", + " (\"Ray\", \"R1992\"), (\"Bonnie\", \"R1992\"), (\"Jess\", \"R1992\"),\n", + " (\"Sam\", \"R1992\"), (\"Nancy\", \"R1992\"), (\"Beatrice\", \"R1992\"),\n", + " (\"Wendell\", \"R1992\"),\n", + "\n", + " (\"Walter\", \"R1995\"), (\"Curtis\", \"R1995\"),\n", + " (\"Beatrice\", \"R1995\"), (\"Wendell\", \"R1995\"),\n", + "\n", + " (\"Marjorie\", \"M1991\"), (\"Harold\", \"M1991\"), (\"Irene\", \"M1991\"),\n", + "]\n", + "\n", + "print(\"Nombre de personnes :\", len(personnes))\n", + "print(\"Nombre de repas :\", len(repas))\n", + "print(\"Nombre de participations :\", len(participations))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Construire le réseau d'affiliation\n", + "\n", + "On construit un graphe qui contient **les deux types de nœuds à la fois** : les\n", + "personnes et les repas. On marque chaque nœud avec un attribut `bipartite`\n", + "(`0` pour les personnes, `1` pour les repas) afin de pouvoir les distinguer ensuite.\n", + "\n", + "Attention à Agnès : elle n'apparaît dans aucune participation. Il faut donc l'ajouter\n", + "explicitement au graphe, sinon elle n'existerait tout simplement pas.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "B = nx.Graph()\n", + "\n", + "# On declare les deux \"cotes\" du reseau\n", + "B.add_nodes_from(personnes, bipartite=0) # cote personnes\n", + "B.add_nodes_from(repas, bipartite=1) # cote repas\n", + "\n", + "# Puis les liens de participation\n", + "B.add_edges_from(participations)\n", + "\n", + "print(\"Le graphe est-il biparti ?\", nx.is_bipartite(B))\n", + "print(\"Nombre total de noeuds :\", B.number_of_nodes())\n", + "print(\"Nombre de liens :\", B.number_of_edges())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualisation\n", + "\n", + "On place les personnes sur une colonne et les repas sur l'autre. Ce type de\n", + "représentation s'appelle un **diagramme en deux modes**.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Positions : personnes a gauche, repas a droite\n", + "pos = {}\n", + "for i, p in enumerate(personnes):\n", + " pos[p] = (0, -i)\n", + "for j, r in enumerate(repas):\n", + " pos[r] = (2, -j * (len(personnes) - 1) / (len(repas) - 1))\n", + "\n", + "plt.figure(figsize=(9, 8))\n", + "nx.draw_networkx_edges(B, pos, alpha=0.35)\n", + "nx.draw_networkx_nodes(B, pos, nodelist=personnes,\n", + " node_color=\"lightblue\", node_size=900)\n", + "nx.draw_networkx_nodes(B, pos, nodelist=repas,\n", + " node_color=\"lightsalmon\", node_shape=\"s\", node_size=1200)\n", + "nx.draw_networkx_labels(B, pos, font_size=9)\n", + "plt.title(\"Reseau d'affiliation : personnes (bleu) x repas (orange)\")\n", + "plt.axis(\"off\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Questions**\n", + "\n", + "1. Agnès apparaît-elle sur le graphique ? À quoi la reconnaît-on ?\n", + "2. Quel repas rassemble le plus de monde ? Lisez-le directement sur la figure.\n", + "3. Dans ce graphe, deux personnes peuvent-elles être reliées **directement** par un\n", + " lien ? Pourquoi ?\n", + "4. Que représenterait, sociologiquement, une personne reliée à un seul repas ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Passer en réseau unimode : la projection\n", + "\n", + "Le réseau d'affiliation n'est pas directement exploitable avec les outils vus en cours\n", + "(composantes connexes, BFS, centralité), parce qu'il mélange deux types de nœuds.\n", + "\n", + "On le transforme donc en un réseau qui ne contient plus que des personnes, selon une\n", + "règle simple :\n", + "\n", + "> **Deux personnes sont reliées si elles ont participé à au moins un repas commun.**\n", + "\n", + "C'est ce qu'on appelle la **projection** du réseau biparti sur le mode « personnes ».\n", + "NetworkX la calcule pour nous — la cellule suivante est fournie, vous n'avez pas à\n", + "l'écrire.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from networkx.algorithms import bipartite\n", + "\n", + "# --- CELLULE FOURNIE ---------------------------------------------------\n", + "# projected_graph(B, noeuds) construit un nouveau graphe dont les noeuds sont\n", + "# ceux passes en second argument, et ou deux noeuds sont relies s'ils avaient\n", + "# au moins un voisin commun dans le graphe biparti B.\n", + "# Ici : deux personnes sont reliees si elles ont partage au moins un repas.\n", + "G = bipartite.projected_graph(B, personnes)\n", + "# -----------------------------------------------------------------------\n", + "\n", + "print(\"Reseau des personnes\")\n", + "print(\" noeuds :\", G.number_of_nodes())\n", + "print(\" liens :\", G.number_of_edges())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "couleurs = [\"lightcoral\" if p in malades else \"lightblue\" for p in G.nodes()]\n", + "\n", + "plt.figure(figsize=(9, 7))\n", + "pos_g = nx.spring_layout(G, seed=4)\n", + "nx.draw(G, pos_g, with_labels=True, node_color=couleurs,\n", + " node_size=1100, font_size=9, edge_color=\"gray\")\n", + "plt.title(\"Reseau unimode : 'a partage au moins un repas avec'\\n(rouge = malade)\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Questions**\n", + "\n", + "5. Le réseau biparti comptait 41 liens. Combien le réseau projeté en compte-t-il ?\n", + " Le nombre a-t-il augmenté ou diminué ? Proposez une explication.\n", + "6. Repérez sur la figure un groupe de personnes toutes reliées entre elles.\n", + " À quoi correspond ce groupe dans les données de départ ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ce que la projection fait perdre\n", + "\n", + "La projection est commode, mais elle n'est pas neutre. Deux remarques importantes :\n", + "\n", + "- **Chaque repas devient une clique.** Si dix personnes assistent au même repas,\n", + " la projection crée un lien entre *chacune* des paires possibles, soit 45 liens.\n", + " Le réseau projeté paraît donc beaucoup plus dense que la réalité sociale : il\n", + " affirme que dix personnes présentes dans la même salle se « connaissent » toutes.\n", + "- **On ne sait plus *pourquoi* deux personnes sont reliées.** Le lien Paula–Ray ne\n", + " dit pas s'il vient d'un seul repas ou de quatre.\n", + "\n", + "C'est un compromis classique en analyse de réseaux : on simplifie pour pouvoir\n", + "appliquer les outils, en acceptant de déformer un peu l'objet. L'important est de\n", + "**savoir dans quel sens il est déformé**.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Composantes connexes : qui pouvait être exposé ?\n", + "\n", + "Une **composante connexe** est un sous-ensemble du réseau où chacun peut atteindre\n", + "chacun par une suite de liens, sans aucun lien vers le reste du réseau.\n", + "\n", + "Ici, l'interprétation est directe : une contamination transmise lors des repas ne peut\n", + "**pas** franchir la frontière entre deux composantes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "composantes = list(nx.connected_components(G))\n", + "\n", + "print(\"Nombre de composantes connexes :\", len(composantes))\n", + "print()\n", + "for i, comp in enumerate(sorted(composantes, key=len, reverse=True), start=1):\n", + " nb_malades = len(set(comp) & set(malades))\n", + " print(f\"Composante {i} ({len(comp)} personnes, {nb_malades} malade(s)) :\")\n", + " print(\" \", sorted(comp))\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Questions**\n", + "\n", + "7. Combien de composantes obtient-on ? Décrivez-les en une phrase chacune.\n", + "8. Les malades sont-ils tous dans la même composante ? Était-ce prévisible ?\n", + "9. Agnès peut-elle avoir été contaminée lors d'un repas ? Justifiez à partir de la\n", + " structure du réseau, sans invoquer d'autre information.\n", + "10. Une personne appartient à la même composante que les malades, mais n'est pas\n", + " malade. Que peut-on en conclure — et surtout, que ne peut-on **pas** en conclure ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Parcours en largeur : à quelle distance sociale du cas index ?\n", + "\n", + "Le premier cas identifié — le **cas index** — est Paula.\n", + "\n", + "On reprend le parcours en largeur (BFS) de la première partie de la séance, mais\n", + "appliqué au **réseau biparti** cette fois. L'intérêt : les distances y sont\n", + "interprétables très directement.\n", + "\n", + "- distance **1** depuis Paula → un **repas** auquel Paula a participé\n", + "- distance **2** → une **personne** ayant partagé un repas avec Paula\n", + "- distance **3** → un **repas** fréquenté par ces personnes, mais pas par Paula\n", + "- distance **4** → des personnes atteignables en deux « sauts » de repas, et ainsi de suite\n", + "\n", + "Les distances paires désignent donc toujours des personnes, les distances impaires\n", + "toujours des repas. C'est une propriété générale des graphes bipartis — et une bonne\n", + "façon de vérifier qu'on a bien construit son réseau.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cas_index = \"Paula\"\n", + "distances = nx.single_source_shortest_path_length(B, cas_index)\n", + "\n", + "print(f\"Distances depuis le cas index ({cas_index}) dans le reseau d'affiliation\")\n", + "print()\n", + "for d in sorted(set(distances.values())):\n", + " noms = sorted(n for n, dist in distances.items() if dist == d)\n", + " print(f\" distance {d} : {noms}\")\n", + "\n", + "print()\n", + "non_atteints = sorted(set(B.nodes()) - set(distances))\n", + "print(\"Noeuds non atteints :\", non_atteints if non_atteints else \"aucun\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Meme chose sur le reseau unimode, pour comparaison\n", + "dist_uni = nx.single_source_shortest_path_length(G, cas_index)\n", + "\n", + "print(f\"Distances depuis {cas_index} dans le reseau unimode\")\n", + "print()\n", + "for personne in sorted(dist_uni, key=lambda p: (dist_uni[p], p)):\n", + " marque = \" (malade)\" if personne in malades else \"\"\n", + " print(f\" {personne:<10} : {dist_uni[personne]}{marque}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Questions**\n", + "\n", + "11. Dans le réseau biparti, quelles personnes sont à distance 2 de Paula ?\n", + " Que représente concrètement cet ensemble ?\n", + "12. Quels nœuds ne sont pas atteints du tout ? Reliez cette observation à la\n", + " question 9.\n", + "13. La distance maximale s'arrête ici à 3, alors que le principe énoncé plus haut\n", + " autoriserait 4, 5, etc. Qu'est-ce que cela dit de la taille du réseau ?\n", + "\n", + "**Le résultat le plus intéressant est celui de la seconde cellule. Prenez le temps\n", + "de le regarder avant de répondre.**\n", + "\n", + "14. Dans le réseau unimode, à quelle distance de Paula se trouve chaque personne\n", + " de sa composante ? Le résultat est-il celui que vous attendiez ?\n", + "\n", + "15. Ce résultat n'est pas une erreur : c'est la conséquence directe de ce qui a été\n", + " dit au point 3.\n", + "\n", + " - La composante de Paula compte 13 personnes, soit\n", + " 13 × 12 / 2 = **78 paires possibles**. Le réseau projeté compte 74 liens au\n", + " total, dont **71 à l'intérieur de cette composante** (les 3 autres forment le\n", + " triangle de Millhaven). Quelle proportion des paires possibles est donc\n", + " effectivement reliée ?\n", + " - Paula a participé à 3 des 5 repas de Dudley. En quoi cela explique-t-il\n", + " qu'elle soit à distance 1 de presque tout le monde ?\n", + " - **Un réseau où tout le monde est à distance 1 de tout le monde ne permet de\n", + " distinguer personne.** Quelles mesures vues en cours (centralité, distance\n", + " moyenne, coefficient de clustering) deviennent inutilisables sur un tel\n", + " réseau ?\n", + " - Le réseau biparti, lui, distinguait encore des niveaux. Que faut-il en\n", + " conclure sur l'ordre dans lequel mener une analyse : projeter d'abord,\n", + " ou explorer le biparti d'abord ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Le même outil, deux objets sociologiques\n", + "\n", + "Vous venez de faire de l'épidémiologie. Mais l'algorithme utilisé — le parcours en\n", + "largeur sur un réseau d'affiliation — est exactement celui qu'on emploie pour étudier\n", + "la **diffusion d'une information, d'une pratique ou d'une innovation**.\n", + "\n", + "L'étude fondatrice est celle de Coleman, Katz et Menzel (1957) sur l'adoption d'un\n", + "nouvel antibiotique par des médecins de l'Illinois. Leur résultat : la date à laquelle\n", + "un médecin se met à prescrire le médicament s'explique bien mieux par sa **position\n", + "dans le réseau professionnel** que par son âge, sa formation ou le volume de sa\n", + "patientèle.\n", + "\n", + "Autrement dit : ce qui circule dans un réseau — un virus, une rumeur, une pratique\n", + "professionnelle, une candidature — suit les mêmes chemins et obéit aux mêmes\n", + "contraintes structurelles. C'est ce qui fait la portée générale de ces outils, et\n", + "c'est aussi ce qui invite à la prudence : le même modèle décrit des phénomènes dont\n", + "les mécanismes réels n'ont rien à voir entre eux.\n", + "\n", + "**Question de synthèse (à rédiger, 10 à 15 lignes)**\n", + "\n", + "16. On vous confie un fichier recensant les participations de 400 salarié·es aux\n", + " réunions internes d'une entreprise sur deux ans. On vous demande d'identifier\n", + " « les personnes influentes ».\n", + "\n", + " - Quelles étapes de ce TP reprendriez-vous, et dans quel ordre ?\n", + " - Quelles limites signaleriez-vous dans votre rapport ?\n", + " - En quoi le fait que la projection transforme chaque réunion en clique\n", + " peut-il fausser une mesure d'influence ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Pour aller plus loin (facultatif)\n", + "\n", + "1. La fonction `bipartite.weighted_projected_graph(B, personnes)` construit la même\n", + " projection, mais en pondérant chaque lien par le **nombre de repas partagés**.\n", + " Construisez-la et affichez les cinq liens les plus lourds. En quoi cette version\n", + " corrige-t-elle en partie le défaut signalé au point 3 ?\n", + "2. Un **point d'articulation** est un nœud dont le retrait fragmente le réseau en\n", + " plusieurs composantes. NetworkX les liste avec `list(nx.articulation_points(...))`.\n", + "\n", + " - Appliquez la fonction au réseau projeté `G`. La liste est **vide**. Au vu de ce\n", + " que vous avez découvert à la question 15, pouviez-vous le prévoir ?\n", + " - Appliquez-la maintenant au réseau biparti `B`. On en trouve **trois**.\n", + " Lesquels ? De quel type sont ces nœuds ?\n", + " - Retirez `R1990` de `B` (`B.copy()` d'abord, pour ne pas abîmer le réseau) et\n", + " regardez qui se retrouve isolé. Même chose avec `R1988`.\n", + " - Concluez : en projetant, qu'est-ce qu'on a rendu invisible ?\n", + "3. Reprenez la projection sur l'autre mode : `bipartite.projected_graph(B, repas)`.\n", + " Deux repas y sont reliés s'ils ont au moins un participant commun. Qu'est-ce que\n", + " ce réseau donne à voir que le précédent ne montrait pas ?\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. Synthèse\n", + "\n", + "- Un **réseau d'affiliation** relie des personnes à des événements. C'est la forme\n", + " sous laquelle les données de réseau se présentent le plus souvent en sociologie,\n", + " parce que les participations sont observables alors que les relations ne le sont pas.\n", + "- La **projection** transforme ce réseau à deux modes en un réseau de personnes,\n", + " exploitable avec les outils habituels. Elle a un coût : chaque événement devient\n", + " une clique, et le réseau paraît plus dense qu'il ne l'est.\n", + "- Les **composantes connexes** délimitent ce qui peut circuler et jusqu'où. Rien ne\n", + " franchit la frontière entre deux composantes.\n", + "- Le **parcours en largeur** mesure une distance ; dans un réseau biparti, les\n", + " distances paires désignent des personnes et les impaires des événements.\n", + "- Un même outil formel sert à décrire une contagion, une rumeur ou l'adoption d'une\n", + " pratique professionnelle. La structure est commune ; les mécanismes ne le sont pas.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "Auteur : Florian Mathieu — L3 Sociologie quantitative, *Algorithmes des graphes*\n", + "\n", + "Licence CC BY-NC-SA 4.0\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file