{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"id": "1ecdf2ae",
"metadata": {
"id": "1ecdf2ae"
},
"source": [
"### Web Scraping"
]
},
{
"cell_type": "markdown",
"id": "af20daad",
"metadata": {
"id": "af20daad"
},
"source": [
"The data was collected from IHP Sri Lanka(https://www.ihp.lk/taxonomy/term/135) and Numbers.lk(https://numbers.lk/analysis\n",
")."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d5e515be",
"metadata": {
"id": "d5e515be",
"outputId": "88580cac-44ce-413f-d500-63de8a3c0dc8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[\"Numbers.lk's first pre-election poll results point to Anura Kumara Dissanayake as the frontrunner in Sri Lanka's upcoming presidential election, though no candidate has secured a clear majority yet. The poll surveyed 2,048 adults across all 22 electoral districts online from April 4-18, and it has a margin of error of +/- 3.5%.\", 'According to the survey finding, Anura Kumara Dissanayaka leads the presidential race with 46% support among Sri Lankan adults. He holds a substantial lead over Sajith Premadasa, who has 22% support, and the incumbent President Ranil Wickremesinghe, who trails with 18%. However, with 10% of voters still undecided and another 4% backing other candidates, the race remains open for potential shifts before election day.', \"Anuna Kumara Dissanayake's core strengths lie with Sri Lanka's youngest voters, securing a staggering 67% support among first-time voters. He also leads comfortably among the under-40 crowd. Premadasa counters with a base among older generations whose highest educational attainment is below A/L levels.\\nHowever, Premadasa significantly lags with first-time voters compared to the other top candidates. Only 3% of these crucial first time voters say they plan to vote for the SJB's Sajith Premadasa. At the same time, incumbent President Ranil Wickremesinghe captures 10% approval in this group.\\nAnother 10% of first-time voters report intending to vote for other candidates outside the top three. And a further 10% remain undecided, leaving a substantial pool of young votes still up for grabs.\", \"When it comes to older voters, support for the traditional candidates rises along with age. Sajith Premadasa's strongest base comes from voters aged 41 and above whose highest educational attainment is below A/L levels. In this demographic, Sajith Premadasa leads with 38% support, while Anura Kumara Dissanayake could muster only 28% backing. Ranil Wickremesinghe captures 21% of these older, comparatively less educated demographic while 14% remain undecided.\", \"This cohort represents by far the largest voter block in the country, with over 40% of Sri Lanka's total electorate falling into the category of being 41 or older with education below A/L level. Their sheer numbers give outsized importance to whichever candidate can most effectively court these more traditionalist voters with modest educational credentials.\", 'The sampling procedure and stratification weighting yield an overall margin of sampling error of ±3.5 percentage points at the 95% confidence level for the full unweighted sample of 2,048 Sri Lankan adults. This margin of error accounts for design effects from the weighting process.']\n"
]
}
],
"source": [
"import requests\n",
"from bs4 import BeautifulSoup\n",
"import csv\n",
"\n",
"# URL of the page with the poll results\n",
"url = \"https://numbers.lk/analysis/numbers-lk-s-first-pre-election-poll-results-akd-emerges-as-frontrunner-but-falls-short-of-the-crucial-50\"\n",
"\n",
"# Fetch the content of the page\n",
"response = requests.get(url)\n",
"html_content = response.content\n",
"\n",
"# Parse the page using BeautifulSoup\n",
"soup = BeautifulSoup(html_content, 'html.parser')\n",
"\n",
"# Find all relevant text sections\n",
"poll_results = []\n",
"\n",
"for paragraph in soup.find_all('p'):\n",
" text = paragraph.get_text().strip()\n",
" if \"AKD\" in text or \"%\" in text: # Filter based on content to capture poll data\n",
" poll_results.append(text)\n",
"\n",
"print(poll_results)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50194477",
"metadata": {
"id": "50194477",
"outputId": "19149067-60a7-4bb5-be5a-ad666ee93034"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['In first half of 2024, the most notable changes in voting intent were the rise in support for President Ranil Wickremasinghe as a potential Presidential candidate at the apparent expense of support for likely candidates from the NPP, SJB and SLPP. In IHP’s MRP (Multilevel Regression and Post-Stratification) model projections, support for NPP leader Anura Dissanayake, SJB leader Sajith Premadasa, and a generic SLPP candidate declined by 7%, 1% and 5% respectively from the first two months of the year to June/July 2024. The main beneficiary was President Wickremesinghe, whose support more than doubled, increasing 13% to 22% during the same period, although this still left him trailing in third place.', 'NPP leader, Anura Dissanayake, registered losses in support across most demographics, but the biggest losses were in his core base of the better-off, Sinhala and youth (18–29 years) voters, where support fell 12, 9, and 17 points respectively. Support amongst voters with a favourable view of the Aragalaya fell 9%–a bigger fall than Sajith Premadasa experienced, although he retained a strong lead over his opponents in these voters. He also lost support amongst voters who voted for Gotabaya Rajapakse or Sajith Premadasa in 2019, although the MRP estimates suggest he managed to consolidate his 2019 Presidential Election voters.', 'The shifts away from both Anura Dissanayake and Sajith Premadasa seem to have been largely to the gain of President Ranil Wickremesinghe. His support rose across all demographics, except in Muslims. This included a larger gain in women (+17% vs. +8% in men), improving his better performance in women. Shifts in his favour were biggest in better-off (+17), Sinhala (+16), older (+24), and former Gotabaya Rajapakse (+20) voters. But notably the biggest shifts in his favour were in anti-Aragalaya voters, where he gained 26 points to build a lead over all other likely candidates. To a considerable extent, President Wickremesinghe has been a major beneficiary of the core pro-government/Rajapakse/SLPP vote, which in the first half of the year largely collapsed across all demographics.', 'Unlike in conventional opinion surveys, IHP’s SLOTS MRP voting intent estimates are not weighted tabulations of the raw survey responses. First, non-responses and refusals to the voting history and voting intent questions are handled by multiple imputation models that consider a wide range of respondent characteristics and impute the probability distribution of who the respondent might have voted for or would vote for. Second, voting intent is estimated using Multilevel Regression and Post-Stratification (MRP) modelling. MRP involves modelling the voting choices of respondents in relation to their characteristics, and then using the estimated model parameters to predict how the full adult population would vote. As MRP does not lend itself to standard computations of survey error, IHP uses a multiple imputation approach to estimate the uncertainty in its model predictions, and this is reported as the margin of error. Specifically, the margin of error represents IHP’s best estimates of the range in which the true levels of voting intent would lie 95% of the time. The MoE here represents uncertainty related to how well the MRP model fits the observed data, as well as traditional sampling noise. However, it does not capture any systematic errors that might arise due to non-sample bias, such as when supporters of one party are less likely to be reached by phone or agree to be interviewed.', 'The analysis reported here are based on modelling of responses from 18,206 interviews conducted from 1 December 2021 to 19 August 2024, including 1,077 interviews conducted in January/February 2024 and 1,146 interviews conducted in June/July 2024. The margins of error are assessed as 2–4% for Ranil Wickremesinghe, Sajith Premadasa, and AK Dissanayake.']\n"
]
}
],
"source": [
"import requests\n",
"from bs4 import BeautifulSoup\n",
"import csv\n",
"\n",
"# URL of the page with the poll results\n",
"url = \"https://www.ihp.lk/research-updates/changes-support-leading-presidential-candidates-during-2024-lead-campaign-period\"\n",
"\n",
"# Fetch the content of the page\n",
"response = requests.get(url)\n",
"html_content = response.content\n",
"\n",
"# Parse the page using BeautifulSoup\n",
"soup = BeautifulSoup(html_content, 'html.parser')\n",
"\n",
"# Find all relevant text sections\n",
"poll_results = []\n",
"\n",
"for paragraph in soup.find_all('p'):\n",
" text = paragraph.get_text().strip()\n",
" if \"AKD\" in text or \"%\" in text: # Filter based on content to capture poll data\n",
" poll_results.append(text)\n",
"\n",
"print(poll_results)\n"
]
},
{
"cell_type": "markdown",
"id": "b32deb3d",
"metadata": {
"id": "b32deb3d"
},
"source": [
"### Data Collection and Pre Processing"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f753cdb3",
"metadata": {
"id": "f753cdb3",
"outputId": "2b4b3232-aa2d-4fe7-8c1b-48d0c8fe945e"
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" date | \n",
" age_group | \n",
" education | \n",
" AKD_support | \n",
" Premadasa_support | \n",
" Ranil_support | \n",
" undecided | \n",
" other_support | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 04.05.2024 | \n",
" adults | \n",
" common | \n",
" 67 | \n",
" 3 | \n",
" 10 | \n",
" 10 | \n",
" 10 | \n",
"
\n",
" \n",
" 1 | \n",
" 04.05.2024 | \n",
" over_40 | \n",
" below_AL | \n",
" 28 | \n",
" 38 | \n",
" 21 | \n",
" 14 | \n",
" 0 | \n",
"
\n",
" \n",
" 2 | \n",
" 04.05.2024 | \n",
" young | \n",
" common | \n",
" 46 | \n",
" 22 | \n",
" 18 | \n",
" 10 | \n",
" 4 | \n",
"
\n",
" \n",
" 3 | \n",
" 25.08.2024 | \n",
" adults | \n",
" common | \n",
" 43 | \n",
" 27 | \n",
" 22 | \n",
" 2 | \n",
" 2 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" date age_group education AKD_support Premadasa_support \\\n",
"0 04.05.2024 adults common 67 3 \n",
"1 04.05.2024 over_40 below_AL 28 38 \n",
"2 04.05.2024 young common 46 22 \n",
"3 25.08.2024 adults common 43 27 \n",
"\n",
" Ranil_support undecided other_support \n",
"0 10 10 10 \n",
"1 21 14 0 \n",
"2 18 10 4 \n",
"3 22 2 2 "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.metrics import accuracy_score\n",
"\n",
"# Sample data in dictionary format based on the information provided\n",
"data = {\n",
" 'date':['04.05.2024','04.05.2024','04.05.2024','25.08.2024'],\n",
" 'age_group': ['adults', 'over_40', 'young', 'adults'],\n",
" 'education': ['common', 'below_AL', 'common','common'],\n",
" 'AKD_support': [67, 28, 46, 43],\n",
" 'Premadasa_support': [3, 38, 22,27],\n",
" 'Ranil_support': [10, 21, 18, 22],\n",
" 'undecided': [10, 14, 10, 2],\n",
" 'other_support': [10, 0, 4, 2],\n",
"}\n",
"\n",
"# Convert the dictionary to a pandas DataFrame\n",
"df = pd.DataFrame(data)\n",
"\n",
"# Convert categorical data to numerical using one-hot encoding\n",
"df_encoded = pd.get_dummies(df, columns=['age_group', 'education'])\n",
"\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8fd57451",
"metadata": {
"id": "8fd57451",
"outputId": "414b57ed-704b-4d7c-e060-ae93aed00c25"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Updated DataFrame:\n",
" Candidate July_2024_Support August_2024_Support \\\n",
"0 AK Dissanayake 37 36 \n",
"1 Sajith Premadasa 36 32 \n",
"2 Ranil Wickremesinghe 23 33 \n",
"3 Namal Rajapaksa 4 3 \n",
"\n",
" July_2024_Favorability August_2024_Favorability \n",
"0 3 -21 \n",
"1 -44 -32 \n",
"2 -24 -33 \n",
"3 -89 -89 \n",
"\n",
"Average Support (July 2024): 25.0\n",
"Average Support (August 2024): 26.0\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Candidate | \n",
" July_2024_Support | \n",
" August_2024_Support | \n",
" July_2024_Favorability | \n",
" August_2024_Favorability | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" AK Dissanayake | \n",
" 37 | \n",
" 36 | \n",
" 3 | \n",
" -21 | \n",
"
\n",
" \n",
" 1 | \n",
" Sajith Premadasa | \n",
" 36 | \n",
" 32 | \n",
" -44 | \n",
" -32 | \n",
"
\n",
" \n",
" 2 | \n",
" Ranil Wickremesinghe | \n",
" 23 | \n",
" 33 | \n",
" -24 | \n",
" -33 | \n",
"
\n",
" \n",
" 3 | \n",
" Namal Rajapaksa | \n",
" 4 | \n",
" 3 | \n",
" -89 | \n",
" -89 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Candidate July_2024_Support August_2024_Support \\\n",
"0 AK Dissanayake 37 36 \n",
"1 Sajith Premadasa 36 32 \n",
"2 Ranil Wickremesinghe 23 33 \n",
"3 Namal Rajapaksa 4 3 \n",
"\n",
" July_2024_Favorability August_2024_Favorability \n",
"0 3 -21 \n",
"1 -44 -32 \n",
"2 -24 -33 \n",
"3 -89 -89 "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = {\n",
" 'Candidate': ['AK Dissanayake', 'Sajith Premadasa', 'Ranil Wickremesinghe', 'Namal Rajapaksa'],\n",
" 'July_2024_Support': [37, 36, 23, 4],\n",
" 'August_2024_Support': [36, 32, 28, 3],\n",
" 'July_2024_Favorability': [3, -44, -24, -89],\n",
" 'August_2024_Favorability': [-21, -32, -33, -89]\n",
"}\n",
"\n",
"df = pd.DataFrame(data)\n",
"\n",
"# Example update: Increase support for Ranil Wickremesinghe by 5% in August\n",
"df.loc[df['Candidate'] == 'Ranil Wickremesinghe', 'August_2024_Support'] += 5\n",
"\n",
"# Example analysis: Calculate average support\n",
"average_support_july = df['July_2024_Support'].mean()\n",
"average_support_august = df['August_2024_Support'].mean()\n",
"\n",
"# Example output\n",
"print(\"Updated DataFrame:\")\n",
"print(df)\n",
"print(\"\\nAverage Support (July 2024):\", average_support_july)\n",
"print(\"Average Support (August 2024):\", average_support_august)\n",
"\n",
"df"
]
},
{
"cell_type": "markdown",
"id": "7b3552e3",
"metadata": {
"id": "7b3552e3"
},
"source": [
"#### Comparison of past pre election polls and final results"
]
},
{
"cell_type": "markdown",
"id": "65dd44bf",
"metadata": {
"id": "65dd44bf"
},
"source": [
"https://numbers.lk/analysis/presidential-election-2024-voter-perception-analysis"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f36bf3db",
"metadata": {
"id": "f36bf3db",
"outputId": "9b3fc3a8-d169-41d1-e681-df225fd4c1f0"
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Candidate | \n",
" 2019_polls | \n",
" Final_result | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Candidate 1 | \n",
" 54 | \n",
" 52.25 | \n",
"
\n",
" \n",
" 1 | \n",
" Candidate 2 | \n",
" 39 | \n",
" 41.99 | \n",
"
\n",
" \n",
" 2 | \n",
" Candidate 3 | \n",
" 5 | \n",
" 3.16 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Candidate 2019_polls Final_result\n",
"0 Candidate 1 54 52.25\n",
"1 Candidate 2 39 41.99\n",
"2 Candidate 3 5 3.16"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 2019 pre-election polls and final election results\n",
"data_2019 = {\n",
" 'Candidate': ['Candidate 1', 'Candidate 2', 'Candidate 3'],\n",
" '2019_polls': [54, 39, 5],\n",
" 'Final_result': [52.25, 41.99, 3.16]\n",
"}\n",
"# Convert 2019 data to a DataFrame\n",
"df_2019 = pd.DataFrame(data_2019)\n",
"\n",
"df_2019"
]
},
{
"cell_type": "markdown",
"id": "2115aef9",
"metadata": {
"id": "2115aef9"
},
"source": [
"### Predictions using LSTM model"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8917f20c",
"metadata": {
"id": "8917f20c",
"outputId": "af433b32-89d3-4b3d-fea1-f4a62bdc8cc6"
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Candidate | \n",
" April_2024 | \n",
" May_2024 | \n",
" June_2024 | \n",
" July_2024 | \n",
" August_2024 | \n",
" September_2024 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" AK Dissanayake | \n",
" 46 | \n",
" 39 | \n",
" 38 | \n",
" 37 | \n",
" 36 | \n",
" 43 | \n",
"
\n",
" \n",
" 1 | \n",
" Sajith Premadasa | \n",
" 22 | \n",
" 39 | \n",
" 38 | \n",
" 36 | \n",
" 32 | \n",
" 27 | \n",
"
\n",
" \n",
" 2 | \n",
" Ranil Wickremesinghe | \n",
" 18 | \n",
" 15 | \n",
" 18 | \n",
" 23 | \n",
" 33 | \n",
" 22 | \n",
"
\n",
" \n",
" 3 | \n",
" other | \n",
" 14 | \n",
" 7 | \n",
" 6 | \n",
" 4 | \n",
" 3 | \n",
" 8 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Candidate April_2024 May_2024 June_2024 July_2024 \\\n",
"0 AK Dissanayake 46 39 38 37 \n",
"1 Sajith Premadasa 22 39 38 36 \n",
"2 Ranil Wickremesinghe 18 15 18 23 \n",
"3 other 14 7 6 4 \n",
"\n",
" August_2024 September_2024 \n",
"0 36 43 \n",
"1 32 27 \n",
"2 33 22 \n",
"3 3 8 "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 2024 poll data\n",
"data_2024 = {\n",
" 'Candidate': ['AK Dissanayake', 'Sajith Premadasa', 'Ranil Wickremesinghe', 'other'],\n",
" 'April_2024':[46,22,18,14],\n",
" 'May_2024': [39, 39, 15, 7],\n",
" 'June_2024': [38, 38, 18, 6],\n",
" 'July_2024': [37, 36, 23, 4],\n",
" 'August_2024': [36, 32, 33, 3],\n",
" 'September_2024': [43, 27, 22, 8]\n",
"}\n",
"\n",
"# Create DataFrame\n",
"df_2024 = pd.DataFrame(data_2024)\n",
"\n",
"df_2024"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "728f6ade",
"metadata": {
"id": "728f6ade",
"outputId": "7380ddd8-f221-4efd-cb9c-d09d8f8c50aa"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/100\n",
"1/1 [==============================] - 2s 2s/step - loss: 1.0014\n",
"Epoch 2/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0007\n",
"Epoch 3/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
"Epoch 4/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 5/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 6/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
"Epoch 7/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0002\n",
"Epoch 8/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
"Epoch 9/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
"Epoch 10/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0003\n",
"Epoch 11/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0002\n",
"Epoch 12/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
"Epoch 13/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 14/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 15/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 16/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 17/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 18/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
"Epoch 19/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
"Epoch 20/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0001\n",
"Epoch 21/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0001\n",
"Epoch 22/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
"Epoch 23/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 24/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 25/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 26/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 27/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 28/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 29/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 30/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 31/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 32/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 33/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 34/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 35/100\n",
"1/1 [==============================] - 0s 13ms/step - loss: 1.0000\n",
"Epoch 36/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 37/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 38/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 39/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 40/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 41/100\n",
"1/1 [==============================] - 0s 14ms/step - loss: 1.0000\n",
"Epoch 42/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 43/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 44/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 45/100\n",
"1/1 [==============================] - 0s 12ms/step - loss: 1.0000\n",
"Epoch 46/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 47/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 48/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 49/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 50/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 51/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 52/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 53/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 54/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 55/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 56/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 57/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 58/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 59/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 60/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 61/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 62/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 63/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 64/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 65/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 66/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 67/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 68/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 69/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 70/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 71/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 72/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 73/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 74/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 75/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 76/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 77/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 78/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 79/100\n",
"1/1 [==============================] - 0s 13ms/step - loss: 1.0000\n",
"Epoch 80/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 81/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 82/100\n",
"1/1 [==============================] - 0s 6ms/step - loss: 1.0000\n",
"Epoch 83/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 84/100\n",
"1/1 [==============================] - 0s 12ms/step - loss: 1.0000\n",
"Epoch 85/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 86/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 87/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 88/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 89/100\n",
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
"Epoch 90/100\n",
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
"Epoch 91/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 92/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 93/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 94/100\n",
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
"Epoch 95/100\n",
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
"Epoch 96/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 97/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 98/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 99/100\n",
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
"Epoch 100/100\n",
"1/1 [==============================] - 0s 6ms/step - loss: 1.0000\n",
"1/1 [==============================] - 1s 553ms/step\n",
"Predicted Final Results for 2024 (percentages):\n",
"AK Dissanayake: 39.57%\n",
"Sajith Premadasa: 32.12%\n",
"Ranil Wickremesinghe: 21.36%\n",
"other: 6.95%\n",
"\n",
"Second Preference Redistribution:\n",
"AKD Final (after redistribution): 44.27%\n",
"Sajith Final (after redistribution): 39.59%\n",
"AKD wins after second preference votes.\n",
"\n",
"Final Vote Counts for 17.1 Million People:\n",
"AKD Votes: 7569928\n",
"Sajith Votes: 6770571\n"
]
}
],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"from sklearn.preprocessing import StandardScaler\n",
"from tensorflow.keras.models import Sequential\n",
"from tensorflow.keras.layers import LSTM, Dense\n",
"\n",
"\n",
"# Prepare the 2024 poll data (transpose to match time steps)\n",
"polls_2024 = df_2024[['April_2024','May_2024', 'June_2024', 'July_2024', 'August_2024', 'September_2024']].values.T\n",
"\n",
"# Scaling the 2024 poll data\n",
"scaler = StandardScaler()\n",
"polls_2024_scaled = scaler.fit_transform(polls_2024)\n",
"\n",
"# Reshape the data to fit the LSTM model input format (samples, time steps, features)\n",
"polls_2024_scaled = np.reshape(polls_2024_scaled, (1, polls_2024_scaled.shape[0], polls_2024_scaled.shape[1]))\n",
"\n",
"# Define a simple LSTM model\n",
"model = Sequential()\n",
"model.add(LSTM(50, return_sequences=False, input_shape=(polls_2024_scaled.shape[1], polls_2024_scaled.shape[2])))\n",
"model.add(Dense(4)) # Output 4 values (one for each candidate)\n",
"\n",
"# Compile the model\n",
"model.compile(optimizer='adam', loss='mean_squared_error')\n",
"\n",
"# Since we don't have final results, we're using the same polls for training and prediction (this is just an example)\n",
"model.fit(polls_2024_scaled, polls_2024_scaled, epochs=100, batch_size=1, verbose=1)\n",
"\n",
"# Predict the final results for 2024 based on the polls\n",
"predicted_final_2024_scaled = model.predict(polls_2024_scaled)\n",
"\n",
"# Rescale the predictions back to the original scale\n",
"predicted_final_2024_rescaled = scaler.inverse_transform(predicted_final_2024_scaled)\n",
"\n",
"# Normalize the predictions so that they sum to 100%\n",
"predicted_final_2024_sum = np.sum(predicted_final_2024_rescaled, axis=1, keepdims=True)\n",
"predicted_final_2024_normalized = (predicted_final_2024_rescaled / predicted_final_2024_sum) * 100\n",
"\n",
"# Display the normalized final results for 2024\n",
"print(\"Predicted Final Results for 2024 (percentages):\")\n",
"for i, candidate in enumerate(df_2024['Candidate']):\n",
" print(f\"{candidate}: {predicted_final_2024_normalized[0][i]:.2f}%\")\n",
"\n",
"# ---- Second Preference Calculation ---- #\n",
"# Define second preference redistribution\n",
"second_preference = {\n",
" 'AKD_from_Ranil': 0.22,\n",
" 'Sajith_from_Ranil': 0.35,\n",
" 'AKD_from_Sajith': 0.29,\n",
" 'Ranil_from_Sajith': 0.32,\n",
" 'Sajith_from_AKD': 0.09,\n",
" 'Ranil_from_AKD': 0.11\n",
"}\n",
"\n",
"# First-round results\n",
"akd_first_round = predicted_final_2024_normalized[0][0]\n",
"sajith_first_round = predicted_final_2024_normalized[0][1]\n",
"ranil_first_round = predicted_final_2024_normalized[0][2]\n",
"other_first_round = predicted_final_2024_normalized[0][3]\n",
"\n",
"# Check if a candidate won outright in the first round (>50%)\n",
"if akd_first_round > 50 or sajith_first_round > 50:\n",
" print(\"First-round winner: No need for second preference votes.\")\n",
"else:\n",
" # Assume Ranil is eliminated and his votes are redistributed\n",
" akd_final = akd_first_round + second_preference['AKD_from_Ranil'] * ranil_first_round\n",
" sajith_final = sajith_first_round + second_preference['Sajith_from_Ranil'] * ranil_first_round\n",
"\n",
" print(\"\\nSecond Preference Redistribution:\")\n",
" print(f\"AKD Final (after redistribution): {akd_final:.2f}%\")\n",
" print(f\"Sajith Final (after redistribution): {sajith_final:.2f}%\")\n",
"\n",
" # Determine final winner\n",
" if akd_final > sajith_final:\n",
" print(\"AKD wins after second preference votes.\")\n",
" else:\n",
" print(\"Sajith wins after second preference votes.\")\n",
"\n",
"# ---- Adjust Final Results for Population ---- #\n",
"population_size = 17100000 # 17.1 million people\n",
"\n",
"# Convert percentages to absolute numbers based on the total population\n",
"akd_final_votes = (akd_final / 100) * population_size\n",
"sajith_final_votes = (sajith_final / 100) * population_size\n",
"\n",
"print(\"\\nFinal Vote Counts for 17.1 Million People:\")\n",
"print(f\"AKD Votes: {akd_final_votes:.0f}\")\n",
"print(f\"Sajith Votes: {sajith_final_votes:.0f}\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0b11609b",
"metadata": {
"id": "0b11609b"
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.3"
},
"colab": {
"provenance": [],
"include_colab_link": true
}
},
"nbformat": 4,
"nbformat_minor": 5
}