ajout activité sur X-Files & contamination
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user