In [2]:
import pandas as pd

We imported the General Election results from the DC Board of Elections for the years 2012-2018, inclusive. Earlier historic election results are available, but would require dealing with ANC boundary changes.


In [3]:
dc_2012 = pd.read_csv('Data/November_6_2012_General_and_Special_Election_Certified_Results.csv')
dc_2014 = pd.read_csv('Data/November_4_2014_General_Election_Certified_Results.csv')
dc_2016 = pd.read_csv('Data/November_4_2014_General_Election_Certified_Results.csv')
dc_2018 = pd.read_csv('Data/November_6_2018_General_Election_Certified_Results.csv')

2012-2016 had consistent headers. 2018 was renamed to be consistent.


In [4]:
# rename the 2018 dataframe headers
dc_2018 = dc_2018.rename(columns = {'ElectionDate':'ELECTION_DATE',  'ElectionName': 'ELECTION_NAME', 'ContestNumber': 'CONTEST_ID',
                'ContestName': 'CONTEST_NAME', 'PrecinctNumber': 'PRECINCT_NUMBER', 'WardNumber': 'WARD',
                'Candidate': 'CANDIDATE', 'Party': 'PARTY', 'Votes': 'VOTES'}, index=str)

In [5]:
dc_2012.dtypes


Out[5]:
ELECTION_DATE      object
ELECTION_NAME      object
CONTEST_ID          int64
CONTEST_NAME       object
PRECINCT_NUMBER     int64
WARD                int64
CANDIDATE          object
PARTY              object
VOTES               int64
dtype: object

In [6]:
# initial merge
dc_2012_2016 = pd.concat([dc_2012, dc_2014, dc_2016], sort=False, axis = 0)

2012-2016 and 2018 had slightly different formats for expressing CONTEST_NAME. We extracted the name of each ANC Single Member District from the CONTEST_NAME column and created a new column for the SMD.


In [7]:
# add the appropriate SMD column for the various years
dc_2012_2016['SMD'] = dc_2012_2016.CONTEST_NAME.str[-4:]
dc_2018['SMD'] = dc_2018.CONTEST_NAME.str[6:10]

In [8]:
dc_2012_2018 = pd.concat([dc_2012_2016, dc_2018], sort=False, axis = 0)

In [9]:
# filter for just the results that include the name "ANC" or "ADVISORY NEIGHBORHOOD COMMISSIONER"
anc_only =  dc_2012_2018[(dc_2012_2018['CONTEST_NAME'].str.contains("ANC")) | (dc_2012_2018['CONTEST_NAME'].str.contains("ADVISORY NEIGHBORHOOD COMMISSIONER")) ]

In [11]:
anc_only.ELECTION_DATE = anc_only.ELECTION_DATE.apply(pd.to_datetime)

In [12]:
anc_only.shape


Out[12]:
(8498, 10)

In [13]:
anc_only.dtypes


Out[13]:
ELECTION_DATE      datetime64[ns]
ELECTION_NAME              object
CONTEST_ID                  int64
CONTEST_NAME               object
PRECINCT_NUMBER             int64
WARD                        int64
CANDIDATE                  object
PARTY                      object
VOTES                       int64
SMD                        object
dtype: object

In [14]:
anc_only.groupby(['ELECTION_DATE', 'SMD', 'CANDIDATE']).VOTES.sum()


Out[14]:
ELECTION_DATE  SMD   CANDIDATE               
2012-11-06     1A01  LISA KRALOVIC               374
                     WRITE-IN                     24
               1A02  ALEXANDER GALLO             295
                     VICKEY A. WRIGHT-SMITH      432
                     WRITE-IN                     11
               1A03  STEVE SWANK                 406
                     WRITE-IN                     36
               1A04  LAINA AQUILINE              430
                     SENTAMU KIREMERWA           120
                     WRITE-IN                     18
               1A05  KEVIN HOLMES                440
                     WRITE-IN                     16
               1A06  KEVIN E. CLINESMITH          87
                     PATRICK W. FLYNN            411
                     WILLIAM "BILL" BROWN JR.    218
                     WRITE-IN                      9
               1A07  THOMAS BOISVERT             633
                     WRITE-IN                     44
               1A08  KENT C. BOESE               852
                     WRITE-IN                     14
               1A09  BOBBY HOLMES                495
                     WRITE-IN                     37
               1A10  ANTHONY CIMINO              554
                     LENWOOD "LENNY" JOHNSON     250
                     WRITE-IN                      6
               1A11  DOTTI LOVE WADE             429
                     MIRIAM Z. SAVAD             205
                     WRITE-IN                     16
               1A12  ROSALIND M. GILLIAM         322
                     WRITE-IN                     10
                                                ... 
2018-11-06     8E01  Rufaro Jenkins               89
                     UNDER VOTES                  29
                     WRITE-IN                     34
               8E02  Amanda Beale                128
                     Anthony Muhammad            155
                     Cheryl Moore                229
                     OVER VOTES                    1
                     UNDER VOTES                  31
                     WRITE-IN                     11
               8E03  Monica Watts                281
                     OVER VOTES                    0
                     UNDER VOTES                  57
                     WRITE-IN                     26
               8E04  Andre Towner                283
                     Kendall Simmons             326
                     OVER VOTES                    0
                     UNDER VOTES                  44
                     WRITE-IN                     26
               8E05  Christopher L. Hawthorne    525
                     OVER VOTES                    0
                     UNDER VOTES                 126
                     WRITE-IN                     41
               8E06  Karlene (K.) Armstead       378
                     OVER VOTES                    0
                     UNDER VOTES                  99
                     WRITE-IN                     17
               8E07  OVER VOTES                    0
                     Stephen A Slaughter         455
                     UNDER VOTES                 102
                     WRITE-IN                     40
Name: VOTES, Length: 3268, dtype: int64

In [15]:
# verify ward 8 against current officeholders
anc_only[anc_only.WARD==8].groupby(['ELECTION_DATE', 'SMD', 'CANDIDATE']).VOTES.sum()


Out[15]:
ELECTION_DATE  SMD   CANDIDATE               
2012-11-06     8A01  HOLLY MUHAMMAD              935
                     WRITE-IN                     36
               8A02  BARBARA J. CLARK            799
                     RANDI K. POWELL             200
                     WRITE-IN                     47
               8A03  L. YVONNE (L.Y.) MOORE      834
                     WRITE-IN                     52
               8A04  MOSES SMITH                 479
                     WRITE-IN                     39
               8A05  CHARLES E. WILSON           539
                     JEREMY J. PHILLIPS          297
                     WRITE-IN                     11
               8A06  GRETA J. FULLER             352
                     KENDALL J. GRAHAM           441
                     STEPHEN COOKE               201
                     WRITE-IN                     19
               8A07  NATALIE WILLIAMS            806
                     WRITE-IN                     28
               8B01  KHADIJAH WATSON             741
                     WRITE-IN                      8
               8B02  WRITE-IN                     71
               8B03  CHARLES H. WILSON           783
                     WRITE-IN                     36
               8B04  ANTHONY LORENZO             492
                     JB SHOATZ                   209
                     WRITE-IN                     12
               8B05  BETTY SCIPPIO               465
                     WRITE-IN                     15
               8B06  MITCHELL G. HAWKINS III     490
                     WRITE-IN                     15
                                                ... 
2018-11-06     8E01  Rufaro Jenkins               89
                     UNDER VOTES                  29
                     WRITE-IN                     34
               8E02  Amanda Beale                128
                     Anthony Muhammad            155
                     Cheryl Moore                229
                     OVER VOTES                    1
                     UNDER VOTES                  31
                     WRITE-IN                     11
               8E03  Monica Watts                281
                     OVER VOTES                    0
                     UNDER VOTES                  57
                     WRITE-IN                     26
               8E04  Andre Towner                283
                     Kendall Simmons             326
                     OVER VOTES                    0
                     UNDER VOTES                  44
                     WRITE-IN                     26
               8E05  Christopher L. Hawthorne    525
                     OVER VOTES                    0
                     UNDER VOTES                 126
                     WRITE-IN                     41
               8E06  Karlene (K.) Armstead       378
                     OVER VOTES                    0
                     UNDER VOTES                  99
                     WRITE-IN                     17
               8E07  OVER VOTES                    0
                     Stephen A Slaughter         455
                     UNDER VOTES                 102
                     WRITE-IN                     40
Name: VOTES, Length: 373, dtype: int64

In [16]:
#with pd.option_context("max.rows", 300):
    #print(dc_2012_2018.CONTEST_NAME.value_counts())

In [17]:
df = anc_only.groupby(['ELECTION_DATE', 'SMD', 'CANDIDATE']).VOTES.sum()

In [18]:
df = df.reset_index()

In [ ]:


In [19]:
grouper = df.groupby(['ELECTION_DATE', 'SMD'])
# Number of candidates in each SMD ANC race. Usually if there are 2 "candidates" in the race, the winner was unopposed as the other "candidate"
# were the pile of write-ins.
grouper.CANDIDATE.count()


Out[19]:
ELECTION_DATE  SMD 
2012-11-06     1A01    2
               1A02    3
               1A03    2
               1A04    3
               1A05    2
               1A06    4
               1A07    2
               1A08    2
               1A09    2
               1A10    3
               1A11    3
               1A12    3
               1B01    2
               1B02    2
               1B03    2
               1B04    2
               1B05    2
               1B06    2
               1B07    2
               1B08    2
               1B09    2
               1B10    2
               1B11    2
               1B12    5
               1C01    4
               1C02    2
               1C03    3
               1C04    2
               1C05    2
               1C06    3
                      ..
2018-11-06     8A06    5
               8A07    4
               8B01    5
               8B02    4
               8B03    5
               8B04    4
               8B05    4
               8B06    4
               8B07    4
               8C01    4
               8C02    5
               8C03    4
               8C04    5
               8C05    4
               8C06    4
               8C07    5
               8D01    4
               8D02    4
               8D03    4
               8D04    4
               8D05    4
               8D06    4
               8D07    5
               8E01    6
               8E02    6
               8E03    4
               8E04    5
               8E05    4
               8E06    4
               8E07    4
Name: CANDIDATE, Length: 888, dtype: int64

In [20]:
# there are 296 SMDs as per https://thedcline.org/2018/08/14/districts-296-anc-races-draw-as-many-as-five-candidates-but-two-thirds-are-uncontested/
df.SMD.value_counts()


Out[20]:
5E09    16
6E02    16
5E04    15
7C07    15
6D07    14
3D05    14
5C06    14
6B05    14
5C01    14
5E05    14
5D05    14
1B12    14
8A06    14
5B01    14
8E02    13
5B04    13
5C07    13
1D05    13
6E01    13
5E07    13
7D03    13
4B01    13
7E04    13
6A06    13
8C02    13
4C09    13
6B03    13
6B06    13
2B04    13
7D01    13
        ..
6C02    10
4A06    10
4D05    10
3C09    10
2F05    10
5E08    10
8C06    10
2D01    10
1B09    10
8B06    10
4C02    10
3B03    10
6B09    10
7B01    10
3B04    10
8D01    10
3E03    10
2E04     9
5A04     9
7F07     9
8E05     9
3D07     9
7F06     9
8D05     9
2A08     9
7B03     9
7D02     9
3D06     9
8C01     9
4A05     9
Name: SMD, Length: 296, dtype: int64

In [21]:
df


Out[21]:
ELECTION_DATE SMD CANDIDATE VOTES
0 2012-11-06 1A01 LISA KRALOVIC 374
1 2012-11-06 1A01 WRITE-IN 24
2 2012-11-06 1A02 ALEXANDER GALLO 295
3 2012-11-06 1A02 VICKEY A. WRIGHT-SMITH 432
4 2012-11-06 1A02 WRITE-IN 11
5 2012-11-06 1A03 STEVE SWANK 406
6 2012-11-06 1A03 WRITE-IN 36
7 2012-11-06 1A04 LAINA AQUILINE 430
8 2012-11-06 1A04 SENTAMU KIREMERWA 120
9 2012-11-06 1A04 WRITE-IN 18
10 2012-11-06 1A05 KEVIN HOLMES 440
11 2012-11-06 1A05 WRITE-IN 16
12 2012-11-06 1A06 KEVIN E. CLINESMITH 87
13 2012-11-06 1A06 PATRICK W. FLYNN 411
14 2012-11-06 1A06 WILLIAM "BILL" BROWN JR. 218
15 2012-11-06 1A06 WRITE-IN 9
16 2012-11-06 1A07 THOMAS BOISVERT 633
17 2012-11-06 1A07 WRITE-IN 44
18 2012-11-06 1A08 KENT C. BOESE 852
19 2012-11-06 1A08 WRITE-IN 14
20 2012-11-06 1A09 BOBBY HOLMES 495
21 2012-11-06 1A09 WRITE-IN 37
22 2012-11-06 1A10 ANTHONY CIMINO 554
23 2012-11-06 1A10 LENWOOD "LENNY" JOHNSON 250
24 2012-11-06 1A10 WRITE-IN 6
25 2012-11-06 1A11 DOTTI LOVE WADE 429
26 2012-11-06 1A11 MIRIAM Z. SAVAD 205
27 2012-11-06 1A11 WRITE-IN 16
28 2012-11-06 1A12 ROSALIND M. GILLIAM 322
29 2012-11-06 1A12 WRITE-IN 10
... ... ... ... ...
3238 2018-11-06 8E01 Rufaro Jenkins 89
3239 2018-11-06 8E01 UNDER VOTES 29
3240 2018-11-06 8E01 WRITE-IN 34
3241 2018-11-06 8E02 Amanda Beale 128
3242 2018-11-06 8E02 Anthony Muhammad 155
3243 2018-11-06 8E02 Cheryl Moore 229
3244 2018-11-06 8E02 OVER VOTES 1
3245 2018-11-06 8E02 UNDER VOTES 31
3246 2018-11-06 8E02 WRITE-IN 11
3247 2018-11-06 8E03 Monica Watts 281
3248 2018-11-06 8E03 OVER VOTES 0
3249 2018-11-06 8E03 UNDER VOTES 57
3250 2018-11-06 8E03 WRITE-IN 26
3251 2018-11-06 8E04 Andre Towner 283
3252 2018-11-06 8E04 Kendall Simmons 326
3253 2018-11-06 8E04 OVER VOTES 0
3254 2018-11-06 8E04 UNDER VOTES 44
3255 2018-11-06 8E04 WRITE-IN 26
3256 2018-11-06 8E05 Christopher L. Hawthorne 525
3257 2018-11-06 8E05 OVER VOTES 0
3258 2018-11-06 8E05 UNDER VOTES 126
3259 2018-11-06 8E05 WRITE-IN 41
3260 2018-11-06 8E06 Karlene (K.) Armstead 378
3261 2018-11-06 8E06 OVER VOTES 0
3262 2018-11-06 8E06 UNDER VOTES 99
3263 2018-11-06 8E06 WRITE-IN 17
3264 2018-11-06 8E07 OVER VOTES 0
3265 2018-11-06 8E07 Stephen A Slaughter 455
3266 2018-11-06 8E07 UNDER VOTES 102
3267 2018-11-06 8E07 WRITE-IN 40

3268 rows × 4 columns


In [22]:
df['WARD'] = df.SMD.str[:1]

In [24]:
df.tail()


Out[24]:
ELECTION_DATE SMD CANDIDATE VOTES WARD
3263 2018-11-06 8E06 WRITE-IN 17 8
3264 2018-11-06 8E07 OVER VOTES 0 8
3265 2018-11-06 8E07 Stephen A Slaughter 455 8
3266 2018-11-06 8E07 UNDER VOTES 102 8
3267 2018-11-06 8E07 WRITE-IN 40 8

In [25]:
# save progress
df.to_csv('anc_electoral_history_2012_2018.csv')

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: