- PVSM.RU - https://www.pvsm.ru -

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1

Общероссийское голосование по вопросу одобрения изменений, вносимых в Конституцию Российской Федерации, проводилось с 25 июня по 1 июля 2020 года (wikipedia) [1].

Основная цель данной заметки — это продемонстрировать как можно быстро начать работать с данными голосования и показать наличие определенного вида аномалий в них.

Все вычисления, визуализации и парсинг данных приведены в Google Colab, который доступен по этой ссылке google colab [2]

Мы сконцентрируемся на выявлении случаев голосования с нулевой дисперсией, то есть результатов, когда все УИКи внутри одного ТИКа голосуют одинаково или с минимальным разбросом. Данные случаи не имеют естественного объяснения кроме того, что подсчет голосов не осуществлялся.

Примерно это выглядит так:

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 1

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 2

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 3

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 4

Источники данных

Сведения о результатах голосования предоставляет ЦИК РФ. Разнообразные цифры с разбивкой по округам доступны на странице ( ЦИК [3]). К сожалению, эти данные сильно фрагментированы и мало приспособлены для машинного анализа.

Сергей Шпилькин одним из первых в нашей стране стал предоставлять данные голосования в режиме реального времени в формате JSON и CSV файлов. За что ему отдельное спасибо (no data, no job!). Соответственно, я использую данные результатов и явки, которые взяты из его телеграм-канала RUElectionData [4].

Основной результат

  1. Найдены ТИКи имеющие близкий к нулю разброс явки и результата голосования.
  2. Найдены ТИКи, где волатильность приращения внутридневной явки между контрольными точками 10.00 12.00 15.00 и 18.00 крайне мала.
  3. Данные случаи не имеют естественного объяснения кроме того, что подсчет голосов не осуществлялся.

Можно сказать, что общее количество аномальных ТИКов исчисляется сотнями.

Избранные результаты сохранены в архиве [5].

Самый математически красивый результат показал ТИК 18 «Клинцовская городская» из Брянской области. Для всех участков (кроме одного) приращение явки между 12.00 и 10.00 часами составило 3%, а приращение явки между 15.00 и 12.00 часами составило 5% (ссылка на страницу ЦИК [6]).

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 5

Но самое интересное, что на УИКах с четными номерами явка составила 91%, а на участках с нечетными номерами — 90%.

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 6

Описание кода

Весь код можно прогнать через меню Runtime->Run All. Это займет около 15 минут.

Для загрузки данных с Google Drive необходимо иметь Google account. GoogleCredentials выведет ссылку с кодом доступа. Скопировав код доступа в колаб, вы сможете загрузить необходимые данные. Это стандартная процедура для колаба.

В самом конце будет предложена возможность сохранить результаты вычисления на локальном компьютере.

Ниже идет детальное описание основных частей программы.

Начнём с загрузки данных явки и результатов голосования (раздел «Загрузка данных явки и результатов голосования»). Данные соответствуют файлам turnouts_05_Jul_2020_14_56.zip и results_06_Jul_2020_19_05.zip из телеграм канала RUElectionData [4].

Далее данные по явке df2 и результатам голосования df1 совмещаются в один дата фрейм df:

df= pd.merge(df1, df2.drop(columns=['reg']), how='inner',on=['tik', 'uik'])

Для транслитерации названий регионов и ТИКов я использую пакет transliterate:

!pip install transliterate
from transliterate import translit

После этого сосчитаем значения явки и результата референдума в процентах:

df['turnout_pct']=df['n_ballots_all']/df['n_registered_voters']*100.
df['yes_pct']=df['yes']/df['n_ballots_polling_station']*100.
df['no_pct']=df['no']/df['n_ballots_polling_station']*100.  
df['non_valid_pct']=df['n_ballots_invalid']/df['n_ballots_all']*100.

И сделаем резервную копию получившегося дата фрейма:

df_original=df.copy(deep=True)

Теперь можно приступать к анализу. В разделе «Визуализация явки и результатов голосования» приводится визуализация процентов голосов «За» и «Против». Предварительно отфильтруем участки с явкой ровно 100%.

df=df[df['turnout_pct']<100.]
ax = df.plot.scatter(x='turnout_pct',y='yes_pct',label='За (Синий)', c='DarkBlue',s=0.001)
ax = df.plot.scatter(x='turnout_pct',y='no_pct', label='Против (Красный)',c='DarkRed',s=0.001,ax=ax)

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 7

Далее, в качестве разогрева, приведем ставшие уже классическими оценки аномальных голосов на графиках голоса «За» против явки:

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 8

И гистограммы голосов «За» и явки:

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 9

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 10

Обратите внимание на пики в районе круглых чисел 80%, 85%, 90% и 95%.

На главное блюдо у нас обнаружение аномалий с низкой дисперсией. В отличие от многих других методов, данный метод прост (результат и его интерпретация понятна и человеку без специального образования) и свободен от модельных предположений (Помни: A Model Is Only as Good as Its Assumptions).

В разделе «Расчет дисперсии процентов явки и голосов За» сосчитаны основные статистики и записаны в Excel файл. Для оценки разброса (дисперсии) наиболее подходит робастная версия стандартного отклонения wiki:Median absolute deviation [7].

Аномальные результаты можно обнаружить изучая дисперсию голосов «За» и явки. Дополнительно я изучил суммы дисперсий голосов «За» и явки и дисперсии внутридневной явки. Четыре последующих раздела посвящены детальному исследованию каждого случая.

Графики ТИКов с низкой дисперсией голосов и явки выглядят как прямые линии. Графики ТИКов с низкой дисперсией суммы дисперсий голосов и явки выглядят жирное пятно (окружность).

Поскольку все 4 раздела имеют одну и ту же структуру, я подробно разберу лишь один из них: «Результаты с низкой дисперсией процента голосов 'За'».

В подразделе «Таблица результатов» приведены топ 50 ТИКов с малой дисперсией по проценту голосов 'За'.

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 11

В подразделе «Детальная визуализация отдельных ТИКов», я привожу пример как можно визуализировать отдельные ТИКи. Для этого надо выбрать соответствующий индекс (цифра в первой колонке) и присвоить переменной id_num её значение. Для примера можно посмотреть id_num 1616, 1995 или 2165.

Значение id_num=1616 соответствует ТИКу 33 Пермь, Орджоникидзевская в Пермском крае. В табличной форме он выглядит так:

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 12

При том что каждый УИК имеет под тысячу избирателей, голоса «За» (колонка yes_pct) распределились невероятно близко к 71.9%. На графиках это выглядит так:

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 13

Аномалии общероссийского голосования по поправкам к Конституции России. Часть 1 - 14

Наконец, в подразделе «Визуализация всех аномальных результатов» отсортируем ТИКи по величине разброса голосов «За». Затем визуализируем и сохраним plot_top_n_results лучших результатов. Я рекомендую глазами посмотреть от plot_top_n_results=50 до plot_top_n_results=300 результатов.

После проведения всех вычислений, есть возможность сжать полученные данные с результатами и сохранить их на локальный компьютер.

import shutil
from google.colab import files
directory='/content/drive/anomaly/dispersion'
shutil.make_archive(directory, 'zip', directory)
files.download('/content/drive/anomaly/dispersion.zip')

Дополнительные ссылки

Много интересных результатов приведено в Facebook'е Сергея Шпилькина [8] и Азат Габдульвалеева [9].

В журнале Александра Киреева [10]

и https://vybory-91.livejournal.com/ [11].

По возможности, поддержите борьбу за честные выборы и общероссийское общественное движение в защиту прав избирателей «Голос» (https://www.golosinfo.org/ [12])

Визуализация результатов референдума:

https://elections.dekoder.org/de/russia/constitution/2020/ [13]

https://constitution.observer/ [14]

https://www.electoral.graphics/ru-ru/ [15]

Хабр о федеральных выборах в РФ:

https://habr.com/ru/post/313270/ [16]

https://habr.com/ru/post/352424/ [17]

Автор: Vladimir M

Источник [18]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/data-mining/355281

Ссылки в тексте:

[1] (wikipedia): https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%89%D0%B5%D1%80%D0%BE%D1%81%D1%81%D0%B8%D0%B9%D1%81%D0%BA%D0%BE%D0%B5_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%BF%D0%BE%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0%D0%BC_%D0%BA_%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B8%D1%82%D1%83%D1%86%D0%B8%D0%B8_%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D0%B8

[2] google colab: https://colab.research.google.com/drive/1I1PilGank96f_ZfKPbkGz_m3bMRF3Mnl

[3] ЦИК: http://www.vybory.izbirkom.ru/region/izbirkom?action=show&root_a=12000007&vrn=100100163596966&region=0&global=true&type=0&prver=0&pronetvd=null

[4] RUElectionData : https://t.me/RUElectionData

[5] архиве: https://drive.google.com/file/d/1divZjkTM1szwj8V0STtf61IMKou3_kfN/view?usp=sharing

[6] ссылка на страницу ЦИК : http://www.vybory.izbirkom.ru/region/izbirkom?action=show&global=true&root=322000006&tvd=23220001314888&vrn=100100163596966&prver=0&pronetvd=null&region=32&sub_region=32&type=450&vibid=23220001314888

[7] wiki:Median absolute deviation: https://en.wikipedia.org/wiki/Median_absolute_deviation

[8] Сергея Шпилькина: https://www.facebook.com/sergey.shpilkin

[9] Азат Габдульвалеева: https://www.facebook.com/profile.php?id=100005978881555

[10] Александра Киреева: https://kireev.livejournal.com/

[11] https://vybory-91.livejournal.com/: https://vybory-91.livejournal.com/

[12] https://www.golosinfo.org/: https://www.golosinfo.org/

[13] https://elections.dekoder.org/de/russia/constitution/2020/: https://elections.dekoder.org/de/russia/constitution/2020/

[14] https://constitution.observer/: https://constitution.observer/

[15] https://www.electoral.graphics/ru-ru/: https://www.electoral.graphics/ru-ru/

[16] https://habr.com/ru/post/313270/: https://habr.com/ru/post/313270/

[17] https://habr.com/ru/post/352424/: https://habr.com/ru/post/352424/

[18] Источник: https://habr.com/ru/post/512166/?utm_source=habrahabr&utm_medium=rss&utm_campaign=512166