Une représentation visuelle des élections à Saint-Pétersbourg - la magie de l'habillage vocal

Salut

En septembre de cette année (2019), l'élection du gouverneur de Saint-Pétersbourg a eu lieu. Toutes les données de vote sont accessibles au public sur le site Web de la commission électorale, nous ne casserons rien, mais visualisons simplement les informations de ce site Web www.st-petersburg.vybory.izbirkom.ru sous la forme dont nous avons besoin, nous effectuerons une analyse très simple et en identifierons Motifs "magiques".

Habituellement, pour ces tâches, j'utilise Google Colab. Il s'agit d'un service qui vous permet d'exécuter Jupyter Notebooks, et d'avoir accès au GPU (NVidia Tesla K80) gratuitement, il accélérera considérablement l'analyse des données et le traitement ultérieur. J'avais besoin d'un travail préparatoire avant d'importer.

%%time !apt update !apt upgrade !apt install gdal-bin python-gdal python3-gdal # Install rtree - Geopandas requirment !apt install python3-rtree # Install Geopandas !pip install git+git://github.com/geopandas/geopandas.git # Install descartes - Geopandas requirment !pip install descartes 

Importations supplémentaires.

 import requests from bs4 import BeautifulSoup import numpy as np import pandas as pd import matplotlib.pyplot as plt import geopandas as gpd import xlrd 

Description des bibliothèques utilisées


  • demandes - module pour une demande de connexion à un site

  • BeautifulSoup - module pour analyser les documents html et xml; vous permet d'accéder directement au contenu de toutes les balises en html

  • numpy - un module mathématique avec un ensemble de base et nécessaire de fonctions mathématiques

  • pandas - bibliothèque d'analyse de données

  • matplotlib.pyplot - ensemble de modules de méthodes de construction

  • géopandas - module pour construire une carte électorale

  • xlrd - module de lecture des fichiers de table

Le moment est venu de collecter les données elles-mêmes, parsim. Le comité électoral s'est occupé de notre temps et a fourni des rapports dans les tableaux, c'est pratique.

 ### Parser list_of_TIKS = [] for i in range (1, 31): list_of_TIKS.append('   №' + str(i)) num_of_voters = [] num_of_voters_voted = [] appearence = [] votes_for_Amosov_percent = [] votes_for_Beglov_percent = [] votes_for_Tikhonova_percent = [] url = "http://www.st-petersburg.vybory.izbirkom.ru/region/region/st-petersburg?action=show&root=1&tvd=27820001217417&vrn=27820001217413&region=78&global=&sub_region=78&prver=0&pronetvd=null&vibid=27820001217417&type=222" response = requests.get(url) page = BeautifulSoup(response.content, "lxml") main_links = page.find_all('a') for TIK in list_of_TIKS: for main_tag in main_links: main_link = main_tag.get('href') if TIK in main_tag: current_TIK = pd.read_html(main_link, encoding='cp1251', header=0)[7] num_of_voters.extend(int(current_TIK.iloc[0,i]) for i in range (len(current_TIK.columns))) num_of_voters_voted.extend(int(current_TIK.iloc[2,i]) + int(current_TIK.iloc[3,i]) for i in range (len(current_TIK.columns))) appearence.extend(round((int(current_TIK.iloc[2,i]) + int(current_TIK.iloc[3,i]))/int(current_TIK.iloc[0,i])*100, 2) for i in range (len(current_TIK.columns))) votes_for_Amosov_percent.extend(round(float(current_TIK.iloc[12,i][-6]+current_TIK.iloc[12,i][-5]+current_TIK.iloc[12,i][-4]+current_TIK.iloc[12,i][-3]+current_TIK.iloc[12,i][-2]),2) for i in range (len(current_TIK.columns))) votes_for_Beglov_percent.extend(round(float(current_TIK.iloc[13,i][-6]+current_TIK.iloc[13,i][-5]+current_TIK.iloc[13,i][-4]+current_TIK.iloc[13,i][-3]+current_TIK.iloc[13,i][-2]),2) for i in range (len(current_TIK.columns))) votes_for_Tikhonova_percent.extend(round(float(current_TIK.iloc[14,i][-6]+current_TIK.iloc[14,i][-5]+current_TIK.iloc[14,i][-4]+current_TIK.iloc[14,i][-3]+current_TIK.iloc[14,i][-2]),2) for i in range (len(current_TIK.columns))) 

Voilà donc ce qui a été discuté. Les données de Google Colab sont collectées intelligemment, mais pas tellement.

Avant de construire différents graphiques et cartes, il est bon pour nous d'avoir une idée de ce que nous appelons un «ensemble de données».

Analyse des données de la commission électorale


Dans la ville de Saint-Pétersbourg, il y a 30 commissions territoriales; à elles, dans la 31e colonne, nous renvoyons aux bureaux de vote numériques.

image

Chaque commission territoriale compte plusieurs dizaines de PEC (commissions électorales de circonscription).

image

La principale chose qui nous intéresse est l'apparition dans chaque bureau de vote et le type de dépendances que nous pouvons observer. Je m'appuierai sur les éléments suivants:

  • dépendance du taux de participation et du nombre de bureaux de vote;

  • dépendance du pourcentage de voix des candidats sur la participation;

  • Dépendance de la participation au nombre d'électeurs dans l'enceinte.

À partir du tableau de données, il est assez difficile de retracer le déroulement des élections et de tirer des conclusions, les graphiques sont donc notre chemin.

Construisons ce que nous avons trouvé.

 ### Plots Data #Votes in percent (appearence) - no need in extra computations #Appearence (num of voters) - no need in extera computations #Number of UIKs (appearence) interval = 1 interval_num_of_UIKs = [] for i in range (int(100/interval+1/interval)): interval_num_of_UIKs.append(0) for i in range (0, int(100/interval+1/interval), interval): for j in range (len(appearence)): if appearence[j] < (i + interval/2) and appearence[j] >= (i - interval/2): interval_num_of_UIKs[i] = interval_num_of_UIKs[i] + 1 

 ### Plotting #Number of UIKs (appearence) plt.figure(figsize=(10, 6)) plt.plot(interval_num_of_UIKs) plt.axis([0, 100, 0, 200]) plt.ylabel('Number of UIKs in a 1% range') plt.xlabel('Appearence') plt.show() #Votes in percent (appearence) plt.figure(figsize=(10, 10)) plt.scatter(appearence, votes_for_Amosov_percent, c = 'g', s = 6) plt.scatter(appearence, votes_for_Beglov_percent, c = 'b', s = 6) plt.scatter(appearence, votes_for_Tikhonova_percent, c = 'r', s = 6) plt.ylabel('Votes in % for each candidate') plt.xlabel('Appearence') plt.show() #Appearence (num of voters) plt.figure(figsize=(10, 6)) plt.scatter(num_of_voters, appearence, c = 'y', s = 6) plt.ylabel('Appearence') plt.xlabel('Number of voters registereg in UIK') plt.show() 

Dépendance du taux de participation et du nombre de bureaux de vote

image

Dépendance du pourcentage de voix des candidats sur le taux de participation

  • «Vert» - vote pour Amosov

  • «Blue» - pour Beglov

  • «Rouge» - pour Tikhonov

image

Dépendance de la participation au nombre d'électeurs dans l'enceinte

image

Les constructions sont assez tolérables, mais au cours des travaux, il s'est avéré qu'en moyenne 400 personnes sur le site et le pourcentage pour Beglov est de 50 à 70, mais il y a deux sites avec une participation> 1200 personnes et un pourcentage de 90 + -0,2. Il est intéressant que cela se soit produit dans ces domaines. Des agitateurs fantastiques ont-ils fonctionné? Ou simplement conduit 10 bus et forcé de voter? D'une manière ou d'une autre, nous sommes ravis, une petite enquête de ce type est en cours. Mais nous devons encore tirer des cartes. Continuons.

Représentation visuelle et travail avec les géopandas


 ### Extra data for visualization: appearence and number of voters by municipal districts current_UIK = pd.read_html(url, encoding='cp1251', header=0)[7] num_of_voters_dist = [] num_of_voters_voted_dist = [] appearence_dist = [] for j in [num_of_voters_dist, num_of_voters_voted_dist, appearence_dist]: j.extend(0 for i in range (18)) districts = { '0' : [1], # '1' : [2], # '2' : [18], # '3' : [16, 30], # '4' : [10, 14, 22], # '5' : [11, 17], # '6' : [4, 25], # '7' : [5, 24], # '8' : [23, 29], # '9' : [9, 12, 28], # '10' : [13], # '11' : [15], # '12' : [21], # '13' : [20], # '14' : [19, 27], # '15' : [3, 7], # '16' : [6, 26], # '17' : [8] # } for i in districts.keys(): for k in range (1, 31): if k in districts[i]: num_of_voters_dist[int(i)]= num_of_voters_dist[int(i)] + int(current_UIK.iloc[0,k-1]) num_of_voters_voted_dist[int(i)] = num_of_voters_voted_dist[int(i)] + int(current_UIK.iloc[2,k-1]) + int(current_UIK.iloc[3,k-1]) for i in range (18): appearence_dist[i] = round(num_of_voters_voted_dist[i]/num_of_voters_dist[i]*100, 2) 

 ### GeoDataFrame SPb_shapes= gpd.read_file('./shapes/Administrative_Discrits.shp', encoding='cp1251') temp = pd.DataFrame({' ': num_of_voters_dist, '':appearence_dist }) temp[''] = SPb_shapes[['']] temp['geometry'] = SPb_shapes[['geometry']] SPB_elections_visualization = gpd.GeoDataFrame(temp) 

 ### Colored districts SPB_elections_visualization.plot(column = '', linewidth=0, cmap='plasma', legend=True, figsize=[15,15]) 



Ils ont peint les quartiers administratifs de la ville et les ont signés, ça a l'air familier, ça ressemble à Peter, mais la Neva ne suffit toujours pas.

Nombre d'électeurs

 ### Number of voters gradient SPB_elections_visualization.plot(column = ' ', linewidth=0, cmap='plasma', legend=True, figsize=[15,15]) 



Participation

 ### Appearence gradient SPB_elections_visualization.plot(column = '', linewidth=0, cmap='plasma', legend=True, figsize=[15,15]) 



Conclusion


Vous pouvez vous amuser avec les données pendant longtemps, les utiliser dans différents domaines et, bien sûr, en retirer des avantages, car elles existent. Des outils de visualisation de géolocalisation simples et sophistiqués peuvent faire de grandes choses. Écrivez sur votre succès dans les commentaires!

Source: https://habr.com/ru/post/fr475258/


All Articles