Русский
Русский
English
Статистика
Реклама

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

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


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


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


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


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


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






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


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


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


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


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

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


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


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



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



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


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


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


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


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


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


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


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

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


!pip install transliteratefrom 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)


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



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




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


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


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


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


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


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


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



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


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



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




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


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


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

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


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


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


и https://vybory-91.livejournal.com/.


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


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


https://elections.dekoder.org/de/russia/constitution/2020/


https://constitution.observer/


https://www.electoral.graphics/ru-ru/


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


http://personeltest.ru/aways/habr.com/ru/post/313270/


http://personeltest.ru/aways/habr.com/ru/post/352424/

Источник: habr.com
К списку статей
Опубликовано: 23.07.2020 12:09:17
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Big data

Data mining

Визуализация данных

Открытые данные

Цик рф

Выборы

Анализ данных

Категории

Последние комментарии

© 2006-2020, personeltest.ru