<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Parsing Los Angeles County's precinct-level results from the 2014 general election.
Step1:  Load the PDF in PDFPlumber
Step2:  Let's look at the first 15 characters on the first page of the PDF
Step3:  Extract the precint ID
The corresponding characters are about 37–44 pixels from the top, and on the left half of the page.
Step4:  We can do the same for the number of ballots cast
Step5:  ... and for the number of registered voters in each precinct
Step6:  Getting the results for each race is a bit trickier
The data representation isn't truly tabular, but it's structured enough to allow us to create tabular data from it. This function divides the first column of the result-listings into columns (explicitly defined, in pixels) and rows (separated by gutters of whitespace).
Step7:  Let's restructure that slightly, so that each row contains information about the relevant race
Step8:  From there, we can start to do some calculations
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
import pdfplumber
import re
Explanation: Parsing Los Angeles County's precinct-level results from the 2014 general election.
End of explanation
pdf = pdfplumber.open("2014-bulletin-first-10-pages.pdf")
print(len(pdf.pages))
Explanation: Load the PDF in PDFPlumber:
End of explanation
first_page = pdf.pages[0]
chars = pd.DataFrame(first_page.chars)
chars.head(15)
Explanation: Let's look at the first 15 characters on the first page of the PDF:
End of explanation
pd.DataFrame(first_page.crop((0, 37, first_page.width / 2, 44 )).chars)
def get_precinct_id(page):
    cropped = page.crop((0, 37, page.width / 2, 44 ))
    text = "".join((c["text"] for c in cropped.chars))
    trimmed = re.sub(r" +", "|", text)
    return trimmed
for page in pdf.pages:
    print(get_precinct_id(page))
Explanation: Extract the precint ID
The corresponding characters are about 37–44 pixels from the top, and on the left half of the page.
End of explanation
def get_ballots_cast(page):
    cropped = page.crop((0, 48, page.width / 3, 60))
    text = "".join((c["text"] for c in cropped.chars))
    count = int(text.split(" ")[0])
    return count
for page in pdf.pages:
    print(get_ballots_cast(page))
Explanation: We can do the same for the number of ballots cast
End of explanation
def get_registered_voters(page):
    cropped = page.crop((0, 62, page.width / 3, 74))
    text = "".join((c["text"] for c in cropped.chars))
    count = int(text.split(" ")[0])
    return count
for page in pdf.pages:
    print(get_registered_voters(page))
Explanation: ... and for the number of registered voters in each precinct
End of explanation
def get_results_rows(page):
    first_col = page.crop((0, 77, 212, page.height))
    table = first_col.extract_table(
        v=(0, 158, 180, 212),
        h="gutters",
        x_tolerance=1)
    return table
get_results_rows(first_page)
Explanation: Getting the results for each race is a bit trickier
The data representation isn't truly tabular, but it's structured enough to allow us to create tabular data from it. This function divides the first column of the result-listings into columns (explicitly defined, in pixels) and rows (separated by gutters of whitespace).
End of explanation
def get_results_table(page):
    rows = get_results_rows(page)
    results = []
    race = None
    for row in rows:
        name, affil, votes = row
        if name == "VOTER NOMINATED": continue
        if votes == None:
            race = name
        else:
            results.append((race, name, affil, int(votes)))
    results_df = pd.DataFrame(results, columns=[ "race", "name", "party", "votes" ])
    return results_df
get_results_table(first_page)
Explanation: Let's restructure that slightly, so that each row contains information about the relevant race:
End of explanation
def get_jerry_brown_pct(page):
    table = get_results_table(page)
    brown_votes = table[table["name"] == "EDMUND G BROWN"]["votes"].iloc[0]
    kashkari_votes = table[table["name"] == "NEEL KASHKARI"]["votes"].iloc[0]
    brown_prop = float(brown_votes) / (kashkari_votes + brown_votes)
    return (100 * brown_prop).round(1)
for page in pdf.pages:
    precinct_id = get_precinct_id(page)
    brown = get_jerry_brown_pct(page)
    print("{0}: {1}%".format(precinct_id, brown))
Explanation: From there, we can start to do some calculations:
End of explanation
<END_TASK>