Spaces:
Build error
Build error
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +17 -0
- ChatBot.ipynb +0 -0
- README.md +103 -12
- Social_Media_Sentiment.ipynb +241 -0
- Win_Predictor.ipynb +998 -0
- webapp/.dart_tool/chrome-device/Default/Affiliation Database +0 -0
- webapp/.dart_tool/chrome-device/Default/Affiliation Database-journal +0 -0
- webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/BrowsingTopicsSiteData +0 -0
- webapp/.dart_tool/chrome-device/Default/BrowsingTopicsSiteData-journal +0 -0
- webapp/.dart_tool/chrome-device/Default/BrowsingTopicsState +12 -0
- webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/DIPS +0 -0
- webapp/.dart_tool/chrome-device/Default/DIPS-journal +0 -0
- webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Rules/000003.log +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Rules/CURRENT +1 -0
- webapp/.dart_tool/chrome-device/Default/Extension Rules/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Rules/LOG +2 -0
- webapp/.dart_tool/chrome-device/Default/Extension Rules/MANIFEST-000001 +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Scripts/000003.log +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Scripts/CURRENT +1 -0
- webapp/.dart_tool/chrome-device/Default/Extension Scripts/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension Scripts/LOG +2 -0
- webapp/.dart_tool/chrome-device/Default/Extension Scripts/MANIFEST-000001 +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/000003.log +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/CURRENT +1 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/LOG +3 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/LOG.old +3 -0
- webapp/.dart_tool/chrome-device/Default/Extension State/MANIFEST-000001 +0 -0
- webapp/.dart_tool/chrome-device/Default/Favicons +0 -0
- webapp/.dart_tool/chrome-device/Default/Favicons-journal +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOCK +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOG +0 -0
- webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOG.old +0 -0
- webapp/.dart_tool/chrome-device/Default/GCM Store/Encryption/000003.log +0 -0
- webapp/.dart_tool/chrome-device/Default/GCM Store/Encryption/CURRENT +1 -0
.gitattributes
CHANGED
@@ -33,3 +33,20 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
webapp/.dart_tool/chrome-device/Default/History filter=lfs diff=lfs merge=lfs -text
|
37 |
+
webapp/.dart_tool/chrome-device/Default/Visited[[:space:]]Links filter=lfs diff=lfs merge=lfs -text
|
38 |
+
webapp/.dart_tool/chrome-device/Default/Web[[:space:]]Data filter=lfs diff=lfs merge=lfs -text
|
39 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000003.log filter=lfs diff=lfs merge=lfs -text
|
40 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000004.log filter=lfs diff=lfs merge=lfs -text
|
41 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000005.ldb filter=lfs diff=lfs merge=lfs -text
|
42 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000007.log filter=lfs diff=lfs merge=lfs -text
|
43 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000008.ldb filter=lfs diff=lfs merge=lfs -text
|
44 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000010.log filter=lfs diff=lfs merge=lfs -text
|
45 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000011.ldb filter=lfs diff=lfs merge=lfs -text
|
46 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000013.log filter=lfs diff=lfs merge=lfs -text
|
47 |
+
webapp/.dart_tool/chrome-device/Default/shared_proto_db/000014.ldb filter=lfs diff=lfs merge=lfs -text
|
48 |
+
webapp/assets/bgimg.jpg filter=lfs diff=lfs merge=lfs -text
|
49 |
+
webapp/build/cache.dill.track.dill filter=lfs diff=lfs merge=lfs -text
|
50 |
+
webapp/build/flutter_assets/assets/bgimg.jpg filter=lfs diff=lfs merge=lfs -text
|
51 |
+
webapp/build/flutter_assets/fonts/MaterialIcons-Regular.otf filter=lfs diff=lfs merge=lfs -text
|
52 |
+
webapp/build/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf filter=lfs diff=lfs merge=lfs -text
|
ChatBot.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
README.md
CHANGED
@@ -1,12 +1,103 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Right Vote
|
2 |
+
|
3 |
+
# Manifesto Comparator with RAG Chatbot and Win Predictor for the 2024 Presidential Election in Sri Lanka
|
4 |
+
|
5 |
+
This project aims to create a manifesto comparator for each leading candidates in presidential election with a chatbot using a Retrieval-Augmented Generation (RAG) model and Win Predictor model using Official Poll data and social media sentiments. The system allows users to query political manifestos and retrieve relevant information of each candidate and ask the general information on the election as well. The backend is built using Flask, Firebase and the frontend is built using Flutter.
|
6 |
+
|
7 |
+
## Features
|
8 |
+
|
9 |
+
- **Chatbot using LangChain**: Provides fast and relevant document retrieval related to the Sri Lanka's President Election 2024 from vectorstores using Hugging Face embedding model and Gemini-1.5-flash LLM.
|
10 |
+
- **Flutter Web App**: Allows users to query manifestos and view retrieved information in an interactive UI.
|
11 |
+
- **Flask API**: Handles queries from the frontend, retrieves relevant documents from the FAISS vector store, and returns results.
|
12 |
+
|
13 |
+
## Tech Stack
|
14 |
+
- **ChatBot**: Python, LangChain, Chroma, Hugging Face, Gemini-1.5-flash
|
15 |
+
- **Backend**: Python, Flask, FireBase
|
16 |
+
- **Frontend**: Flutter
|
17 |
+
- **Hosting**: Google Colab (for testing) and cloud platforms (for deployment)
|
18 |
+
|
19 |
+
## Prerequisites
|
20 |
+
|
21 |
+
- Python 3.x
|
22 |
+
- Google Colab (for testing)
|
23 |
+
- Flutter installed on your machine
|
24 |
+
- `ngrok` for exposing the Flask API in Google Colab
|
25 |
+
|
26 |
+
|
27 |
+
## Win Predictor using LSTM
|
28 |
+
|
29 |
+
This project focuses on analyzing pre-election poll data and predicting final election results using an LSTM (Long Short-Term Memory) neural network model. The project also simulates the redistribution of second-preference votes based on pre-defined assumptions and calculates the final vote counts for the election.
|
30 |
+
|
31 |
+
### 1. Web Scraping Poll Results
|
32 |
+
We extracted the latest poll data from a specified URL using `BeautifulSoup` to scrape the necessary information, including support percentages for the candidates. This information is then used to train a model and make predictions.
|
33 |
+
|
34 |
+
### 2. Data Analysis and Preprocessing
|
35 |
+
A sample dataset of election polls from 2024 is created and preprocessed for analysis. The data is one-hot encoded, and relevant features like candidate support and demographics (age group, education level) are considered. The model also uses historical data from the 2019 election for comparison.
|
36 |
+
|
37 |
+
### 3. LSTM Model for Prediction
|
38 |
+
The model is trained using poll data across several months (April 2024 to September 2024). A scaled and reshaped dataset is fed into an LSTM model to predict the potential election outcome. The model outputs predicted percentages for each candidate.
|
39 |
+
|
40 |
+
### 4. Second Preference Redistribution
|
41 |
+
In cases where no candidate crosses the 50% mark, we simulate the redistribution of second-preference votes based on a predefined redistribution model. The final vote shares are recalculated to determine the election outcome.
|
42 |
+
|
43 |
+
### 5. Final Vote Calculation
|
44 |
+
After determining the final percentages, the total vote count is adjusted based on the estimated population size (17.1 million). This provides a clearer understanding of the number of votes each candidate is expected to receive.
|
45 |
+
|
46 |
+
## Sentiment Analysis
|
47 |
+
To assess public sentiment towards candidates by analyzing text data from social media and news sources. This helps to understand the emotional tone of public discourse, which can be crucial for interpreting polling data.
|
48 |
+
|
49 |
+
### Techniques Used
|
50 |
+
|
51 |
+
#### Data Collection & text preprocessing
|
52 |
+
|
53 |
+
- **Tool:** Twitter API
|
54 |
+
- **Process:**
|
55 |
+
- Collected recent tweets mentioning the candidates of interest.
|
56 |
+
- Used the `tweepy` library to fetch tweets based on specific search queries related to each candidate.
|
57 |
+
- Ensured that the sentiment analysis is not influenced by specific users or external links mentioned in the tweets.
|
58 |
+
|
59 |
+
#### Sentiment Analysis Model
|
60 |
+
|
61 |
+
- **Tool:** RoBERTa model
|
62 |
+
- **Process:**
|
63 |
+
- **Tokenization:** Converted text into a format suitable for model input using the RoBERTa tokenizer.
|
64 |
+
- **Model Inference:** Passed tokenized text through the RoBERTa model to obtain sentiment scores. The model was pre-trained on Twitter data to effectively classify sentiments in social media contexts.
|
65 |
+
- **Softmax Function:** Applied the softmax function to the model's output to convert raw scores into probabilities, representing the likelihood of each sentiment class (positive, neutral, negative).
|
66 |
+
|
67 |
+
#### Sentiment Classification
|
68 |
+
|
69 |
+
- **Objective:** To categorize each tweet into one of three sentiment classes: positive, neutral, or negative.
|
70 |
+
- **Process:**
|
71 |
+
- Assigned sentiment labels based on the highest probability from the model’s output.
|
72 |
+
|
73 |
+
|
74 |
+
## ChatBot
|
75 |
+
|
76 |
+
This feature is a chatbot that allows users to query the manifestos and policies of prominent Sri Lankan candidates, view pre-election poll results, and get general information on the election. Built with Langchain and RAG (Retrieval-Augmented Generation) architecture, the model uses PDF documents of candidates' manifestos, web search tools, and poll predictions to provide insightful answers.
|
77 |
+
|
78 |
+
### 1. Reading Multiple PDFs
|
79 |
+
We utilized the `pypdf` library in Python to extract text from PDF documents. The chatbot reads manifestos from multiple candidates including Ranil Wickremesinghe, Anura Kumara Dissanayake, and Sajith Premadasa, as well as pre-election poll data and general election questions.
|
80 |
+
|
81 |
+
### 2.Embedding the Text and Storing in a Vectorstore
|
82 |
+
The extracted text from each PDF is converted into embeddings using the HuggingFace `hkunlp/instructor-xl` model. These embeddings are then stored in a `Chroma` vectorstore. By persisting the vectorstore, we efficiently reuse the data for answering future queries.
|
83 |
+
|
84 |
+
### 3. Agent Architecture
|
85 |
+
We implemented tools for each candidate's manifesto using a RAG (Retrieval-Augmented Generation) setup. Each tool is responsible for retrieving and answering questions about a specific candidate’s manifesto. Additionally, a DuckDuckGo search tool is integrated to fetch real-time web data, and a poll prediction tool is included for querying pre-election polls and their forecasts.
|
86 |
+
|
87 |
+
### 4. LLM Integration
|
88 |
+
The chatbot uses the `gemini-1.5-flash` model from Google Generative AI for generating responses. This LLM is deployed within the RAG architecture to provide accurate and context-aware answers based on both document retrieval and external web search.
|
89 |
+
|
90 |
+
### 5. Interactive Querying
|
91 |
+
Users can ask the chatbot detailed questions about individual manifestos, compare policies between candidates, or inquire about pre-election predictions and general election information. The system uses a mix of retrieval from vectorstores and real-time web search to deliver comprehensive responses.
|
92 |
+
|
93 |
+
## Requirements
|
94 |
+
|
95 |
+
- Python 3.x
|
96 |
+
- `langchain` for building the RAG-based model and managing agent architectures
|
97 |
+
- `langchain-community` for using additional tools from the Langchain community
|
98 |
+
- `langchain-chroma` for managing and storing document embeddings in Chroma's vectorstore
|
99 |
+
- `pypdf` for reading and extracting text from PDFs
|
100 |
+
- `InstructorEmbedding` for generating text embeddings using HuggingFace models
|
101 |
+
- `sentence-transformers==2.2.2` for text preprocessing and vectorization
|
102 |
+
- `langchain_google_genai` for connecting to Google’s generative AI models like `gemini-1.5-flash`
|
103 |
+
|
Social_Media_Sentiment.ipynb
ADDED
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {
|
6 |
+
"id": "view-in-github",
|
7 |
+
"colab_type": "text"
|
8 |
+
},
|
9 |
+
"source": [
|
10 |
+
"<a href=\"https://colab.research.google.com/github/NaveenSanjaya/Right-Vote/blob/main/Social_Media_Sentiment.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
11 |
+
]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"cell_type": "markdown",
|
15 |
+
"id": "296aa3df",
|
16 |
+
"metadata": {
|
17 |
+
"id": "296aa3df"
|
18 |
+
},
|
19 |
+
"source": [
|
20 |
+
"### Twitter Sentiment Analysis"
|
21 |
+
]
|
22 |
+
},
|
23 |
+
{
|
24 |
+
"cell_type": "code",
|
25 |
+
"execution_count": null,
|
26 |
+
"id": "c9a7dc7a",
|
27 |
+
"metadata": {
|
28 |
+
"id": "c9a7dc7a"
|
29 |
+
},
|
30 |
+
"outputs": [],
|
31 |
+
"source": [
|
32 |
+
"import tweepy\n",
|
33 |
+
"import re\n",
|
34 |
+
"import pandas as pd\n",
|
35 |
+
"import matplotlib.pyplot as plt\n",
|
36 |
+
"from transformers import AutoTokenizer, TFAutoModelForSequenceClassification\n",
|
37 |
+
"from scipy.special import softmax\n",
|
38 |
+
"\n",
|
39 |
+
"# Twitter API credentials\n",
|
40 |
+
"API_KEY = 'MCu2BiFyXXXXXXX'\n",
|
41 |
+
"API_SECRET_KEY = 'Cl8FYiqoVl82KyXXXXXXXXXX'\n",
|
42 |
+
"BEARER_TOKEN = 'AAAAAAAAAAAAAAAAAAAAXXXXXXX'\n",
|
43 |
+
"ACCESS_TOKEN = '1709435XXXXXXXX'\n",
|
44 |
+
"ACCESS_TOKEN_SECRET = 'Lp50yuMNJjg5SDZXXXXXXXX'\n",
|
45 |
+
"\n",
|
46 |
+
"# Set up Twitter API client\n",
|
47 |
+
"client = tweepy.Client(bearer_token=BEARER_TOKEN)\n",
|
48 |
+
"\n",
|
49 |
+
"# Initialize sentiment analysis model and tokenizer\n",
|
50 |
+
"roberta = \"cardiffnlp/twitter-roberta-base-sentiment\"\n",
|
51 |
+
"model = TFAutoModelForSequenceClassification.from_pretrained(roberta)\n",
|
52 |
+
"tokenizer = AutoTokenizer.from_pretrained(roberta)\n",
|
53 |
+
"\n",
|
54 |
+
"# Labels for sentiment analysis\n",
|
55 |
+
"labels = ['Negative', 'Neutral', 'Positive']\n",
|
56 |
+
"\n",
|
57 |
+
"def preprocess_tweet(tweet):\n",
|
58 |
+
" \"\"\"\n",
|
59 |
+
" Preprocess the tweet by replacing mentions and URLs with placeholders.\n",
|
60 |
+
" \"\"\"\n",
|
61 |
+
" tweet_words = []\n",
|
62 |
+
" for word in tweet.split(' '):\n",
|
63 |
+
" if word.startswith('@') and len(word) > 1:\n",
|
64 |
+
" word = '@user'\n",
|
65 |
+
" elif word.startswith('http'):\n",
|
66 |
+
" word = \"http\"\n",
|
67 |
+
" tweet_words.append(word)\n",
|
68 |
+
" return \" \".join(tweet_words)\n",
|
69 |
+
"\n",
|
70 |
+
"def fetch_tweets(query, max_results=100):\n",
|
71 |
+
" \"\"\"\n",
|
72 |
+
" Fetch recent tweets containing the specified query.\n",
|
73 |
+
" \"\"\"\n",
|
74 |
+
" tweet_data = []\n",
|
75 |
+
" try:\n",
|
76 |
+
" tweets = client.search_recent_tweets(query=query, max_results=max_results, tweet_fields=['created_at', 'text'])\n",
|
77 |
+
" if tweets.data:\n",
|
78 |
+
" for tweet in tweets.data:\n",
|
79 |
+
" tweet_data.append({\n",
|
80 |
+
" 'created_at': tweet.created_at,\n",
|
81 |
+
" 'text': tweet.text\n",
|
82 |
+
" })\n",
|
83 |
+
" except Exception as e:\n",
|
84 |
+
" print(f\"Error fetching tweets: {e}\")\n",
|
85 |
+
" return tweet_data\n",
|
86 |
+
"\n",
|
87 |
+
"def analyze_sentiment(text):\n",
|
88 |
+
" \"\"\"\n",
|
89 |
+
" Analyze the sentiment of the given text using the pre-trained model.\n",
|
90 |
+
" \"\"\"\n",
|
91 |
+
" tweet_proc = preprocess_tweet(text)\n",
|
92 |
+
" encoded_tweet = tokenizer(tweet_proc, return_tensors='tf')\n",
|
93 |
+
" output = model(**encoded_tweet)\n",
|
94 |
+
" scores = output[0][0].numpy()\n",
|
95 |
+
" scores = softmax(scores)\n",
|
96 |
+
" return dict(zip(labels, scores))\n",
|
97 |
+
"\n",
|
98 |
+
"def plot_sentiment_distribution(sentiment_counts):\n",
|
99 |
+
" \"\"\"\n",
|
100 |
+
" Plot a bar chart of sentiment distribution.\n",
|
101 |
+
" \"\"\"\n",
|
102 |
+
" sentiments = list(sentiment_counts.keys())\n",
|
103 |
+
" counts = list(sentiment_counts.values())\n",
|
104 |
+
" plt.bar(sentiments, counts, color=['red', 'gray', 'green'])\n",
|
105 |
+
" plt.xlabel('Sentiment')\n",
|
106 |
+
" plt.ylabel('Count')\n",
|
107 |
+
" plt.title('Sentiment Distribution')\n",
|
108 |
+
" plt.show()\n",
|
109 |
+
"\n",
|
110 |
+
"def main():\n",
|
111 |
+
" # Example candidate names\n",
|
112 |
+
" candidates = [\"Sajith Premadasa\", \"Ranil Wickremesinghe\", \"Anura Kumara\"]\n",
|
113 |
+
"\n",
|
114 |
+
" all_tweet_data = []\n",
|
115 |
+
"\n",
|
116 |
+
" for candidate in candidates:\n",
|
117 |
+
" print(f\"Fetching tweets for {candidate}...\")\n",
|
118 |
+
" tweets = fetch_tweets(candidate, max_results=100)\n",
|
119 |
+
" for tweet in tweets:\n",
|
120 |
+
" tweet['candidate'] = candidate\n",
|
121 |
+
" all_tweet_data.append(tweet)\n",
|
122 |
+
"\n",
|
123 |
+
" # Convert tweet data to DataFrame\n",
|
124 |
+
" df = pd.DataFrame(all_tweet_data)\n",
|
125 |
+
"\n",
|
126 |
+
" # Analyze sentiment for each tweet\n",
|
127 |
+
" sentiment_counts = {label: 0 for label in labels}\n",
|
128 |
+
"\n",
|
129 |
+
" for text in df['text']:\n",
|
130 |
+
" sentiment = analyze_sentiment(text)\n",
|
131 |
+
" for label, score in sentiment.items():\n",
|
132 |
+
" sentiment_counts[label] += score\n",
|
133 |
+
"\n",
|
134 |
+
" # Print sentiment distribution\n",
|
135 |
+
" print(\"Sentiment Distribution:\")\n",
|
136 |
+
" for label, count in sentiment_counts.items():\n",
|
137 |
+
" print(f\"{label}: {count}\")\n",
|
138 |
+
"\n",
|
139 |
+
" # Plot sentiment distribution\n",
|
140 |
+
" plot_sentiment_distribution(sentiment_counts)\n",
|
141 |
+
"\n",
|
142 |
+
"if __name__ == \"__main__\":\n",
|
143 |
+
" main()\n"
|
144 |
+
]
|
145 |
+
},
|
146 |
+
{
|
147 |
+
"cell_type": "markdown",
|
148 |
+
"id": "815021d8",
|
149 |
+
"metadata": {
|
150 |
+
"id": "815021d8"
|
151 |
+
},
|
152 |
+
"source": [
|
153 |
+
"### Facebook Sentiment Analysis"
|
154 |
+
]
|
155 |
+
},
|
156 |
+
{
|
157 |
+
"cell_type": "code",
|
158 |
+
"execution_count": null,
|
159 |
+
"id": "cb529b29",
|
160 |
+
"metadata": {
|
161 |
+
"id": "cb529b29"
|
162 |
+
},
|
163 |
+
"outputs": [],
|
164 |
+
"source": [
|
165 |
+
"import requests\n",
|
166 |
+
"from transformers import pipeline\n",
|
167 |
+
"\n",
|
168 |
+
"# Facebook API credentials\n",
|
169 |
+
"ACCESS_TOKEN = 'EAAjjdeAxAF1eT5ZBbibXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n",
|
170 |
+
"PAGE_ID = 'XXXXXXXXXXXXX'\n",
|
171 |
+
"\n",
|
172 |
+
"# Initialize sentiment analysis pipeline\n",
|
173 |
+
"sentiment_pipeline = pipeline('sentiment-analysis')\n",
|
174 |
+
"\n",
|
175 |
+
"def fetch_facebook_posts(page_id, access_token, limit=10):\n",
|
176 |
+
" \"\"\"\n",
|
177 |
+
" Fetch recent posts from a Facebook page.\n",
|
178 |
+
" \"\"\"\n",
|
179 |
+
" url = f'https://graph.facebook.com/{page_id}/posts'\n",
|
180 |
+
" params = {\n",
|
181 |
+
" 'access_token': access_token,\n",
|
182 |
+
" 'limit': limit,\n",
|
183 |
+
" }\n",
|
184 |
+
" response = requests.get(url, params=params)\n",
|
185 |
+
" response.raise_for_status()\n",
|
186 |
+
" return response.json().get('data', [])\n",
|
187 |
+
"\n",
|
188 |
+
"def analyze_sentiment(text):\n",
|
189 |
+
" \"\"\"\n",
|
190 |
+
" Analyze the sentiment of the given text using Hugging Face's sentiment analysis model.\n",
|
191 |
+
" \"\"\"\n",
|
192 |
+
" return sentiment_pipeline(text)\n",
|
193 |
+
"\n",
|
194 |
+
"def main():\n",
|
195 |
+
" # Fetch recent posts\n",
|
196 |
+
" posts = fetch_facebook_posts(PAGE_ID, ACCESS_TOKEN, limit=5)\n",
|
197 |
+
"\n",
|
198 |
+
" if not posts:\n",
|
199 |
+
" print(\"No posts found.\")\n",
|
200 |
+
" return\n",
|
201 |
+
"\n",
|
202 |
+
" # Analyze sentiment for each post\n",
|
203 |
+
" for post in posts:\n",
|
204 |
+
" post_message = post.get('message', '')\n",
|
205 |
+
" if post_message:\n",
|
206 |
+
" sentiment = analyze_sentiment(post_message)\n",
|
207 |
+
" print(f\"Post: {post_message}\")\n",
|
208 |
+
" print(f\"Sentiment: {sentiment[0]['label']} (Confidence: {sentiment[0]['score']:.2f})\")\n",
|
209 |
+
" print()\n",
|
210 |
+
"\n",
|
211 |
+
"if __name__ == \"__main__\":\n",
|
212 |
+
" main()\n"
|
213 |
+
]
|
214 |
+
}
|
215 |
+
],
|
216 |
+
"metadata": {
|
217 |
+
"kernelspec": {
|
218 |
+
"display_name": "Python 3 (ipykernel)",
|
219 |
+
"language": "python",
|
220 |
+
"name": "python3"
|
221 |
+
},
|
222 |
+
"language_info": {
|
223 |
+
"codemirror_mode": {
|
224 |
+
"name": "ipython",
|
225 |
+
"version": 3
|
226 |
+
},
|
227 |
+
"file_extension": ".py",
|
228 |
+
"mimetype": "text/x-python",
|
229 |
+
"name": "python",
|
230 |
+
"nbconvert_exporter": "python",
|
231 |
+
"pygments_lexer": "ipython3",
|
232 |
+
"version": "3.11.3"
|
233 |
+
},
|
234 |
+
"colab": {
|
235 |
+
"provenance": [],
|
236 |
+
"include_colab_link": true
|
237 |
+
}
|
238 |
+
},
|
239 |
+
"nbformat": 4,
|
240 |
+
"nbformat_minor": 5
|
241 |
+
}
|
Win_Predictor.ipynb
ADDED
@@ -0,0 +1,998 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {
|
6 |
+
"id": "view-in-github",
|
7 |
+
"colab_type": "text"
|
8 |
+
},
|
9 |
+
"source": [
|
10 |
+
"<a href=\"https://colab.research.google.com/github/NaveenSanjaya/Right-Vote/blob/main/Win_Predictor.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
11 |
+
]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"cell_type": "markdown",
|
15 |
+
"id": "1ecdf2ae",
|
16 |
+
"metadata": {
|
17 |
+
"id": "1ecdf2ae"
|
18 |
+
},
|
19 |
+
"source": [
|
20 |
+
"### Web Scraping"
|
21 |
+
]
|
22 |
+
},
|
23 |
+
{
|
24 |
+
"cell_type": "markdown",
|
25 |
+
"id": "af20daad",
|
26 |
+
"metadata": {
|
27 |
+
"id": "af20daad"
|
28 |
+
},
|
29 |
+
"source": [
|
30 |
+
"The data was collected from IHP Sri Lanka(https://www.ihp.lk/taxonomy/term/135) and Numbers.lk(https://numbers.lk/analysis\n",
|
31 |
+
")."
|
32 |
+
]
|
33 |
+
},
|
34 |
+
{
|
35 |
+
"cell_type": "code",
|
36 |
+
"execution_count": null,
|
37 |
+
"id": "d5e515be",
|
38 |
+
"metadata": {
|
39 |
+
"id": "d5e515be",
|
40 |
+
"outputId": "88580cac-44ce-413f-d500-63de8a3c0dc8"
|
41 |
+
},
|
42 |
+
"outputs": [
|
43 |
+
{
|
44 |
+
"name": "stdout",
|
45 |
+
"output_type": "stream",
|
46 |
+
"text": [
|
47 |
+
"[\"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"
|
48 |
+
]
|
49 |
+
}
|
50 |
+
],
|
51 |
+
"source": [
|
52 |
+
"import requests\n",
|
53 |
+
"from bs4 import BeautifulSoup\n",
|
54 |
+
"import csv\n",
|
55 |
+
"\n",
|
56 |
+
"# URL of the page with the poll results\n",
|
57 |
+
"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",
|
58 |
+
"\n",
|
59 |
+
"# Fetch the content of the page\n",
|
60 |
+
"response = requests.get(url)\n",
|
61 |
+
"html_content = response.content\n",
|
62 |
+
"\n",
|
63 |
+
"# Parse the page using BeautifulSoup\n",
|
64 |
+
"soup = BeautifulSoup(html_content, 'html.parser')\n",
|
65 |
+
"\n",
|
66 |
+
"# Find all relevant text sections\n",
|
67 |
+
"poll_results = []\n",
|
68 |
+
"\n",
|
69 |
+
"for paragraph in soup.find_all('p'):\n",
|
70 |
+
" text = paragraph.get_text().strip()\n",
|
71 |
+
" if \"AKD\" in text or \"%\" in text: # Filter based on content to capture poll data\n",
|
72 |
+
" poll_results.append(text)\n",
|
73 |
+
"\n",
|
74 |
+
"print(poll_results)\n"
|
75 |
+
]
|
76 |
+
},
|
77 |
+
{
|
78 |
+
"cell_type": "code",
|
79 |
+
"execution_count": null,
|
80 |
+
"id": "50194477",
|
81 |
+
"metadata": {
|
82 |
+
"id": "50194477",
|
83 |
+
"outputId": "19149067-60a7-4bb5-be5a-ad666ee93034"
|
84 |
+
},
|
85 |
+
"outputs": [
|
86 |
+
{
|
87 |
+
"name": "stdout",
|
88 |
+
"output_type": "stream",
|
89 |
+
"text": [
|
90 |
+
"['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"
|
91 |
+
]
|
92 |
+
}
|
93 |
+
],
|
94 |
+
"source": [
|
95 |
+
"import requests\n",
|
96 |
+
"from bs4 import BeautifulSoup\n",
|
97 |
+
"import csv\n",
|
98 |
+
"\n",
|
99 |
+
"# URL of the page with the poll results\n",
|
100 |
+
"url = \"https://www.ihp.lk/research-updates/changes-support-leading-presidential-candidates-during-2024-lead-campaign-period\"\n",
|
101 |
+
"\n",
|
102 |
+
"# Fetch the content of the page\n",
|
103 |
+
"response = requests.get(url)\n",
|
104 |
+
"html_content = response.content\n",
|
105 |
+
"\n",
|
106 |
+
"# Parse the page using BeautifulSoup\n",
|
107 |
+
"soup = BeautifulSoup(html_content, 'html.parser')\n",
|
108 |
+
"\n",
|
109 |
+
"# Find all relevant text sections\n",
|
110 |
+
"poll_results = []\n",
|
111 |
+
"\n",
|
112 |
+
"for paragraph in soup.find_all('p'):\n",
|
113 |
+
" text = paragraph.get_text().strip()\n",
|
114 |
+
" if \"AKD\" in text or \"%\" in text: # Filter based on content to capture poll data\n",
|
115 |
+
" poll_results.append(text)\n",
|
116 |
+
"\n",
|
117 |
+
"print(poll_results)\n"
|
118 |
+
]
|
119 |
+
},
|
120 |
+
{
|
121 |
+
"cell_type": "markdown",
|
122 |
+
"id": "b32deb3d",
|
123 |
+
"metadata": {
|
124 |
+
"id": "b32deb3d"
|
125 |
+
},
|
126 |
+
"source": [
|
127 |
+
"### Data Collection and Pre Processing"
|
128 |
+
]
|
129 |
+
},
|
130 |
+
{
|
131 |
+
"cell_type": "code",
|
132 |
+
"execution_count": null,
|
133 |
+
"id": "f753cdb3",
|
134 |
+
"metadata": {
|
135 |
+
"id": "f753cdb3",
|
136 |
+
"outputId": "2b4b3232-aa2d-4fe7-8c1b-48d0c8fe945e"
|
137 |
+
},
|
138 |
+
"outputs": [
|
139 |
+
{
|
140 |
+
"data": {
|
141 |
+
"text/html": [
|
142 |
+
"<div>\n",
|
143 |
+
"<style scoped>\n",
|
144 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
145 |
+
" vertical-align: middle;\n",
|
146 |
+
" }\n",
|
147 |
+
"\n",
|
148 |
+
" .dataframe tbody tr th {\n",
|
149 |
+
" vertical-align: top;\n",
|
150 |
+
" }\n",
|
151 |
+
"\n",
|
152 |
+
" .dataframe thead th {\n",
|
153 |
+
" text-align: right;\n",
|
154 |
+
" }\n",
|
155 |
+
"</style>\n",
|
156 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
157 |
+
" <thead>\n",
|
158 |
+
" <tr style=\"text-align: right;\">\n",
|
159 |
+
" <th></th>\n",
|
160 |
+
" <th>date</th>\n",
|
161 |
+
" <th>age_group</th>\n",
|
162 |
+
" <th>education</th>\n",
|
163 |
+
" <th>AKD_support</th>\n",
|
164 |
+
" <th>Premadasa_support</th>\n",
|
165 |
+
" <th>Ranil_support</th>\n",
|
166 |
+
" <th>undecided</th>\n",
|
167 |
+
" <th>other_support</th>\n",
|
168 |
+
" </tr>\n",
|
169 |
+
" </thead>\n",
|
170 |
+
" <tbody>\n",
|
171 |
+
" <tr>\n",
|
172 |
+
" <th>0</th>\n",
|
173 |
+
" <td>04.05.2024</td>\n",
|
174 |
+
" <td>adults</td>\n",
|
175 |
+
" <td>common</td>\n",
|
176 |
+
" <td>67</td>\n",
|
177 |
+
" <td>3</td>\n",
|
178 |
+
" <td>10</td>\n",
|
179 |
+
" <td>10</td>\n",
|
180 |
+
" <td>10</td>\n",
|
181 |
+
" </tr>\n",
|
182 |
+
" <tr>\n",
|
183 |
+
" <th>1</th>\n",
|
184 |
+
" <td>04.05.2024</td>\n",
|
185 |
+
" <td>over_40</td>\n",
|
186 |
+
" <td>below_AL</td>\n",
|
187 |
+
" <td>28</td>\n",
|
188 |
+
" <td>38</td>\n",
|
189 |
+
" <td>21</td>\n",
|
190 |
+
" <td>14</td>\n",
|
191 |
+
" <td>0</td>\n",
|
192 |
+
" </tr>\n",
|
193 |
+
" <tr>\n",
|
194 |
+
" <th>2</th>\n",
|
195 |
+
" <td>04.05.2024</td>\n",
|
196 |
+
" <td>young</td>\n",
|
197 |
+
" <td>common</td>\n",
|
198 |
+
" <td>46</td>\n",
|
199 |
+
" <td>22</td>\n",
|
200 |
+
" <td>18</td>\n",
|
201 |
+
" <td>10</td>\n",
|
202 |
+
" <td>4</td>\n",
|
203 |
+
" </tr>\n",
|
204 |
+
" <tr>\n",
|
205 |
+
" <th>3</th>\n",
|
206 |
+
" <td>25.08.2024</td>\n",
|
207 |
+
" <td>adults</td>\n",
|
208 |
+
" <td>common</td>\n",
|
209 |
+
" <td>43</td>\n",
|
210 |
+
" <td>27</td>\n",
|
211 |
+
" <td>22</td>\n",
|
212 |
+
" <td>2</td>\n",
|
213 |
+
" <td>2</td>\n",
|
214 |
+
" </tr>\n",
|
215 |
+
" </tbody>\n",
|
216 |
+
"</table>\n",
|
217 |
+
"</div>"
|
218 |
+
],
|
219 |
+
"text/plain": [
|
220 |
+
" date age_group education AKD_support Premadasa_support \\\n",
|
221 |
+
"0 04.05.2024 adults common 67 3 \n",
|
222 |
+
"1 04.05.2024 over_40 below_AL 28 38 \n",
|
223 |
+
"2 04.05.2024 young common 46 22 \n",
|
224 |
+
"3 25.08.2024 adults common 43 27 \n",
|
225 |
+
"\n",
|
226 |
+
" Ranil_support undecided other_support \n",
|
227 |
+
"0 10 10 10 \n",
|
228 |
+
"1 21 14 0 \n",
|
229 |
+
"2 18 10 4 \n",
|
230 |
+
"3 22 2 2 "
|
231 |
+
]
|
232 |
+
},
|
233 |
+
"execution_count": 3,
|
234 |
+
"metadata": {},
|
235 |
+
"output_type": "execute_result"
|
236 |
+
}
|
237 |
+
],
|
238 |
+
"source": [
|
239 |
+
"import pandas as pd\n",
|
240 |
+
"from sklearn.model_selection import train_test_split\n",
|
241 |
+
"from sklearn.ensemble import RandomForestClassifier\n",
|
242 |
+
"from sklearn.metrics import accuracy_score\n",
|
243 |
+
"\n",
|
244 |
+
"# Sample data in dictionary format based on the information provided\n",
|
245 |
+
"data = {\n",
|
246 |
+
" 'date':['04.05.2024','04.05.2024','04.05.2024','25.08.2024'],\n",
|
247 |
+
" 'age_group': ['adults', 'over_40', 'young', 'adults'],\n",
|
248 |
+
" 'education': ['common', 'below_AL', 'common','common'],\n",
|
249 |
+
" 'AKD_support': [67, 28, 46, 43],\n",
|
250 |
+
" 'Premadasa_support': [3, 38, 22,27],\n",
|
251 |
+
" 'Ranil_support': [10, 21, 18, 22],\n",
|
252 |
+
" 'undecided': [10, 14, 10, 2],\n",
|
253 |
+
" 'other_support': [10, 0, 4, 2],\n",
|
254 |
+
"}\n",
|
255 |
+
"\n",
|
256 |
+
"# Convert the dictionary to a pandas DataFrame\n",
|
257 |
+
"df = pd.DataFrame(data)\n",
|
258 |
+
"\n",
|
259 |
+
"# Convert categorical data to numerical using one-hot encoding\n",
|
260 |
+
"df_encoded = pd.get_dummies(df, columns=['age_group', 'education'])\n",
|
261 |
+
"\n",
|
262 |
+
"df"
|
263 |
+
]
|
264 |
+
},
|
265 |
+
{
|
266 |
+
"cell_type": "code",
|
267 |
+
"execution_count": null,
|
268 |
+
"id": "8fd57451",
|
269 |
+
"metadata": {
|
270 |
+
"id": "8fd57451",
|
271 |
+
"outputId": "414b57ed-704b-4d7c-e060-ae93aed00c25"
|
272 |
+
},
|
273 |
+
"outputs": [
|
274 |
+
{
|
275 |
+
"name": "stdout",
|
276 |
+
"output_type": "stream",
|
277 |
+
"text": [
|
278 |
+
"Updated DataFrame:\n",
|
279 |
+
" Candidate July_2024_Support August_2024_Support \\\n",
|
280 |
+
"0 AK Dissanayake 37 36 \n",
|
281 |
+
"1 Sajith Premadasa 36 32 \n",
|
282 |
+
"2 Ranil Wickremesinghe 23 33 \n",
|
283 |
+
"3 Namal Rajapaksa 4 3 \n",
|
284 |
+
"\n",
|
285 |
+
" July_2024_Favorability August_2024_Favorability \n",
|
286 |
+
"0 3 -21 \n",
|
287 |
+
"1 -44 -32 \n",
|
288 |
+
"2 -24 -33 \n",
|
289 |
+
"3 -89 -89 \n",
|
290 |
+
"\n",
|
291 |
+
"Average Support (July 2024): 25.0\n",
|
292 |
+
"Average Support (August 2024): 26.0\n"
|
293 |
+
]
|
294 |
+
},
|
295 |
+
{
|
296 |
+
"data": {
|
297 |
+
"text/html": [
|
298 |
+
"<div>\n",
|
299 |
+
"<style scoped>\n",
|
300 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
301 |
+
" vertical-align: middle;\n",
|
302 |
+
" }\n",
|
303 |
+
"\n",
|
304 |
+
" .dataframe tbody tr th {\n",
|
305 |
+
" vertical-align: top;\n",
|
306 |
+
" }\n",
|
307 |
+
"\n",
|
308 |
+
" .dataframe thead th {\n",
|
309 |
+
" text-align: right;\n",
|
310 |
+
" }\n",
|
311 |
+
"</style>\n",
|
312 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
313 |
+
" <thead>\n",
|
314 |
+
" <tr style=\"text-align: right;\">\n",
|
315 |
+
" <th></th>\n",
|
316 |
+
" <th>Candidate</th>\n",
|
317 |
+
" <th>July_2024_Support</th>\n",
|
318 |
+
" <th>August_2024_Support</th>\n",
|
319 |
+
" <th>July_2024_Favorability</th>\n",
|
320 |
+
" <th>August_2024_Favorability</th>\n",
|
321 |
+
" </tr>\n",
|
322 |
+
" </thead>\n",
|
323 |
+
" <tbody>\n",
|
324 |
+
" <tr>\n",
|
325 |
+
" <th>0</th>\n",
|
326 |
+
" <td>AK Dissanayake</td>\n",
|
327 |
+
" <td>37</td>\n",
|
328 |
+
" <td>36</td>\n",
|
329 |
+
" <td>3</td>\n",
|
330 |
+
" <td>-21</td>\n",
|
331 |
+
" </tr>\n",
|
332 |
+
" <tr>\n",
|
333 |
+
" <th>1</th>\n",
|
334 |
+
" <td>Sajith Premadasa</td>\n",
|
335 |
+
" <td>36</td>\n",
|
336 |
+
" <td>32</td>\n",
|
337 |
+
" <td>-44</td>\n",
|
338 |
+
" <td>-32</td>\n",
|
339 |
+
" </tr>\n",
|
340 |
+
" <tr>\n",
|
341 |
+
" <th>2</th>\n",
|
342 |
+
" <td>Ranil Wickremesinghe</td>\n",
|
343 |
+
" <td>23</td>\n",
|
344 |
+
" <td>33</td>\n",
|
345 |
+
" <td>-24</td>\n",
|
346 |
+
" <td>-33</td>\n",
|
347 |
+
" </tr>\n",
|
348 |
+
" <tr>\n",
|
349 |
+
" <th>3</th>\n",
|
350 |
+
" <td>Namal Rajapaksa</td>\n",
|
351 |
+
" <td>4</td>\n",
|
352 |
+
" <td>3</td>\n",
|
353 |
+
" <td>-89</td>\n",
|
354 |
+
" <td>-89</td>\n",
|
355 |
+
" </tr>\n",
|
356 |
+
" </tbody>\n",
|
357 |
+
"</table>\n",
|
358 |
+
"</div>"
|
359 |
+
],
|
360 |
+
"text/plain": [
|
361 |
+
" Candidate July_2024_Support August_2024_Support \\\n",
|
362 |
+
"0 AK Dissanayake 37 36 \n",
|
363 |
+
"1 Sajith Premadasa 36 32 \n",
|
364 |
+
"2 Ranil Wickremesinghe 23 33 \n",
|
365 |
+
"3 Namal Rajapaksa 4 3 \n",
|
366 |
+
"\n",
|
367 |
+
" July_2024_Favorability August_2024_Favorability \n",
|
368 |
+
"0 3 -21 \n",
|
369 |
+
"1 -44 -32 \n",
|
370 |
+
"2 -24 -33 \n",
|
371 |
+
"3 -89 -89 "
|
372 |
+
]
|
373 |
+
},
|
374 |
+
"execution_count": 5,
|
375 |
+
"metadata": {},
|
376 |
+
"output_type": "execute_result"
|
377 |
+
}
|
378 |
+
],
|
379 |
+
"source": [
|
380 |
+
"data = {\n",
|
381 |
+
" 'Candidate': ['AK Dissanayake', 'Sajith Premadasa', 'Ranil Wickremesinghe', 'Namal Rajapaksa'],\n",
|
382 |
+
" 'July_2024_Support': [37, 36, 23, 4],\n",
|
383 |
+
" 'August_2024_Support': [36, 32, 28, 3],\n",
|
384 |
+
" 'July_2024_Favorability': [3, -44, -24, -89],\n",
|
385 |
+
" 'August_2024_Favorability': [-21, -32, -33, -89]\n",
|
386 |
+
"}\n",
|
387 |
+
"\n",
|
388 |
+
"df = pd.DataFrame(data)\n",
|
389 |
+
"\n",
|
390 |
+
"# Example update: Increase support for Ranil Wickremesinghe by 5% in August\n",
|
391 |
+
"df.loc[df['Candidate'] == 'Ranil Wickremesinghe', 'August_2024_Support'] += 5\n",
|
392 |
+
"\n",
|
393 |
+
"# Example analysis: Calculate average support\n",
|
394 |
+
"average_support_july = df['July_2024_Support'].mean()\n",
|
395 |
+
"average_support_august = df['August_2024_Support'].mean()\n",
|
396 |
+
"\n",
|
397 |
+
"# Example output\n",
|
398 |
+
"print(\"Updated DataFrame:\")\n",
|
399 |
+
"print(df)\n",
|
400 |
+
"print(\"\\nAverage Support (July 2024):\", average_support_july)\n",
|
401 |
+
"print(\"Average Support (August 2024):\", average_support_august)\n",
|
402 |
+
"\n",
|
403 |
+
"df"
|
404 |
+
]
|
405 |
+
},
|
406 |
+
{
|
407 |
+
"cell_type": "markdown",
|
408 |
+
"id": "7b3552e3",
|
409 |
+
"metadata": {
|
410 |
+
"id": "7b3552e3"
|
411 |
+
},
|
412 |
+
"source": [
|
413 |
+
"#### Comparison of past pre election polls and final results"
|
414 |
+
]
|
415 |
+
},
|
416 |
+
{
|
417 |
+
"cell_type": "markdown",
|
418 |
+
"id": "65dd44bf",
|
419 |
+
"metadata": {
|
420 |
+
"id": "65dd44bf"
|
421 |
+
},
|
422 |
+
"source": [
|
423 |
+
"https://numbers.lk/analysis/presidential-election-2024-voter-perception-analysis"
|
424 |
+
]
|
425 |
+
},
|
426 |
+
{
|
427 |
+
"cell_type": "code",
|
428 |
+
"execution_count": null,
|
429 |
+
"id": "f36bf3db",
|
430 |
+
"metadata": {
|
431 |
+
"id": "f36bf3db",
|
432 |
+
"outputId": "9b3fc3a8-d169-41d1-e681-df225fd4c1f0"
|
433 |
+
},
|
434 |
+
"outputs": [
|
435 |
+
{
|
436 |
+
"data": {
|
437 |
+
"text/html": [
|
438 |
+
"<div>\n",
|
439 |
+
"<style scoped>\n",
|
440 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
441 |
+
" vertical-align: middle;\n",
|
442 |
+
" }\n",
|
443 |
+
"\n",
|
444 |
+
" .dataframe tbody tr th {\n",
|
445 |
+
" vertical-align: top;\n",
|
446 |
+
" }\n",
|
447 |
+
"\n",
|
448 |
+
" .dataframe thead th {\n",
|
449 |
+
" text-align: right;\n",
|
450 |
+
" }\n",
|
451 |
+
"</style>\n",
|
452 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
453 |
+
" <thead>\n",
|
454 |
+
" <tr style=\"text-align: right;\">\n",
|
455 |
+
" <th></th>\n",
|
456 |
+
" <th>Candidate</th>\n",
|
457 |
+
" <th>2019_polls</th>\n",
|
458 |
+
" <th>Final_result</th>\n",
|
459 |
+
" </tr>\n",
|
460 |
+
" </thead>\n",
|
461 |
+
" <tbody>\n",
|
462 |
+
" <tr>\n",
|
463 |
+
" <th>0</th>\n",
|
464 |
+
" <td>Candidate 1</td>\n",
|
465 |
+
" <td>54</td>\n",
|
466 |
+
" <td>52.25</td>\n",
|
467 |
+
" </tr>\n",
|
468 |
+
" <tr>\n",
|
469 |
+
" <th>1</th>\n",
|
470 |
+
" <td>Candidate 2</td>\n",
|
471 |
+
" <td>39</td>\n",
|
472 |
+
" <td>41.99</td>\n",
|
473 |
+
" </tr>\n",
|
474 |
+
" <tr>\n",
|
475 |
+
" <th>2</th>\n",
|
476 |
+
" <td>Candidate 3</td>\n",
|
477 |
+
" <td>5</td>\n",
|
478 |
+
" <td>3.16</td>\n",
|
479 |
+
" </tr>\n",
|
480 |
+
" </tbody>\n",
|
481 |
+
"</table>\n",
|
482 |
+
"</div>"
|
483 |
+
],
|
484 |
+
"text/plain": [
|
485 |
+
" Candidate 2019_polls Final_result\n",
|
486 |
+
"0 Candidate 1 54 52.25\n",
|
487 |
+
"1 Candidate 2 39 41.99\n",
|
488 |
+
"2 Candidate 3 5 3.16"
|
489 |
+
]
|
490 |
+
},
|
491 |
+
"execution_count": 8,
|
492 |
+
"metadata": {},
|
493 |
+
"output_type": "execute_result"
|
494 |
+
}
|
495 |
+
],
|
496 |
+
"source": [
|
497 |
+
"# 2019 pre-election polls and final election results\n",
|
498 |
+
"data_2019 = {\n",
|
499 |
+
" 'Candidate': ['Candidate 1', 'Candidate 2', 'Candidate 3'],\n",
|
500 |
+
" '2019_polls': [54, 39, 5],\n",
|
501 |
+
" 'Final_result': [52.25, 41.99, 3.16]\n",
|
502 |
+
"}\n",
|
503 |
+
"# Convert 2019 data to a DataFrame\n",
|
504 |
+
"df_2019 = pd.DataFrame(data_2019)\n",
|
505 |
+
"\n",
|
506 |
+
"df_2019"
|
507 |
+
]
|
508 |
+
},
|
509 |
+
{
|
510 |
+
"cell_type": "markdown",
|
511 |
+
"id": "2115aef9",
|
512 |
+
"metadata": {
|
513 |
+
"id": "2115aef9"
|
514 |
+
},
|
515 |
+
"source": [
|
516 |
+
"### Predictions using LSTM model"
|
517 |
+
]
|
518 |
+
},
|
519 |
+
{
|
520 |
+
"cell_type": "code",
|
521 |
+
"execution_count": null,
|
522 |
+
"id": "8917f20c",
|
523 |
+
"metadata": {
|
524 |
+
"id": "8917f20c",
|
525 |
+
"outputId": "af433b32-89d3-4b3d-fea1-f4a62bdc8cc6"
|
526 |
+
},
|
527 |
+
"outputs": [
|
528 |
+
{
|
529 |
+
"data": {
|
530 |
+
"text/html": [
|
531 |
+
"<div>\n",
|
532 |
+
"<style scoped>\n",
|
533 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
534 |
+
" vertical-align: middle;\n",
|
535 |
+
" }\n",
|
536 |
+
"\n",
|
537 |
+
" .dataframe tbody tr th {\n",
|
538 |
+
" vertical-align: top;\n",
|
539 |
+
" }\n",
|
540 |
+
"\n",
|
541 |
+
" .dataframe thead th {\n",
|
542 |
+
" text-align: right;\n",
|
543 |
+
" }\n",
|
544 |
+
"</style>\n",
|
545 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
546 |
+
" <thead>\n",
|
547 |
+
" <tr style=\"text-align: right;\">\n",
|
548 |
+
" <th></th>\n",
|
549 |
+
" <th>Candidate</th>\n",
|
550 |
+
" <th>April_2024</th>\n",
|
551 |
+
" <th>May_2024</th>\n",
|
552 |
+
" <th>June_2024</th>\n",
|
553 |
+
" <th>July_2024</th>\n",
|
554 |
+
" <th>August_2024</th>\n",
|
555 |
+
" <th>September_2024</th>\n",
|
556 |
+
" </tr>\n",
|
557 |
+
" </thead>\n",
|
558 |
+
" <tbody>\n",
|
559 |
+
" <tr>\n",
|
560 |
+
" <th>0</th>\n",
|
561 |
+
" <td>AK Dissanayake</td>\n",
|
562 |
+
" <td>46</td>\n",
|
563 |
+
" <td>39</td>\n",
|
564 |
+
" <td>38</td>\n",
|
565 |
+
" <td>37</td>\n",
|
566 |
+
" <td>36</td>\n",
|
567 |
+
" <td>43</td>\n",
|
568 |
+
" </tr>\n",
|
569 |
+
" <tr>\n",
|
570 |
+
" <th>1</th>\n",
|
571 |
+
" <td>Sajith Premadasa</td>\n",
|
572 |
+
" <td>22</td>\n",
|
573 |
+
" <td>39</td>\n",
|
574 |
+
" <td>38</td>\n",
|
575 |
+
" <td>36</td>\n",
|
576 |
+
" <td>32</td>\n",
|
577 |
+
" <td>27</td>\n",
|
578 |
+
" </tr>\n",
|
579 |
+
" <tr>\n",
|
580 |
+
" <th>2</th>\n",
|
581 |
+
" <td>Ranil Wickremesinghe</td>\n",
|
582 |
+
" <td>18</td>\n",
|
583 |
+
" <td>15</td>\n",
|
584 |
+
" <td>18</td>\n",
|
585 |
+
" <td>23</td>\n",
|
586 |
+
" <td>33</td>\n",
|
587 |
+
" <td>22</td>\n",
|
588 |
+
" </tr>\n",
|
589 |
+
" <tr>\n",
|
590 |
+
" <th>3</th>\n",
|
591 |
+
" <td>other</td>\n",
|
592 |
+
" <td>14</td>\n",
|
593 |
+
" <td>7</td>\n",
|
594 |
+
" <td>6</td>\n",
|
595 |
+
" <td>4</td>\n",
|
596 |
+
" <td>3</td>\n",
|
597 |
+
" <td>8</td>\n",
|
598 |
+
" </tr>\n",
|
599 |
+
" </tbody>\n",
|
600 |
+
"</table>\n",
|
601 |
+
"</div>"
|
602 |
+
],
|
603 |
+
"text/plain": [
|
604 |
+
" Candidate April_2024 May_2024 June_2024 July_2024 \\\n",
|
605 |
+
"0 AK Dissanayake 46 39 38 37 \n",
|
606 |
+
"1 Sajith Premadasa 22 39 38 36 \n",
|
607 |
+
"2 Ranil Wickremesinghe 18 15 18 23 \n",
|
608 |
+
"3 other 14 7 6 4 \n",
|
609 |
+
"\n",
|
610 |
+
" August_2024 September_2024 \n",
|
611 |
+
"0 36 43 \n",
|
612 |
+
"1 32 27 \n",
|
613 |
+
"2 33 22 \n",
|
614 |
+
"3 3 8 "
|
615 |
+
]
|
616 |
+
},
|
617 |
+
"execution_count": 6,
|
618 |
+
"metadata": {},
|
619 |
+
"output_type": "execute_result"
|
620 |
+
}
|
621 |
+
],
|
622 |
+
"source": [
|
623 |
+
"# 2024 poll data\n",
|
624 |
+
"data_2024 = {\n",
|
625 |
+
" 'Candidate': ['AK Dissanayake', 'Sajith Premadasa', 'Ranil Wickremesinghe', 'other'],\n",
|
626 |
+
" 'April_2024':[46,22,18,14],\n",
|
627 |
+
" 'May_2024': [39, 39, 15, 7],\n",
|
628 |
+
" 'June_2024': [38, 38, 18, 6],\n",
|
629 |
+
" 'July_2024': [37, 36, 23, 4],\n",
|
630 |
+
" 'August_2024': [36, 32, 33, 3],\n",
|
631 |
+
" 'September_2024': [43, 27, 22, 8]\n",
|
632 |
+
"}\n",
|
633 |
+
"\n",
|
634 |
+
"# Create DataFrame\n",
|
635 |
+
"df_2024 = pd.DataFrame(data_2024)\n",
|
636 |
+
"\n",
|
637 |
+
"df_2024"
|
638 |
+
]
|
639 |
+
},
|
640 |
+
{
|
641 |
+
"cell_type": "code",
|
642 |
+
"execution_count": null,
|
643 |
+
"id": "728f6ade",
|
644 |
+
"metadata": {
|
645 |
+
"id": "728f6ade",
|
646 |
+
"outputId": "7380ddd8-f221-4efd-cb9c-d09d8f8c50aa"
|
647 |
+
},
|
648 |
+
"outputs": [
|
649 |
+
{
|
650 |
+
"name": "stdout",
|
651 |
+
"output_type": "stream",
|
652 |
+
"text": [
|
653 |
+
"Epoch 1/100\n",
|
654 |
+
"1/1 [==============================] - 2s 2s/step - loss: 1.0014\n",
|
655 |
+
"Epoch 2/100\n",
|
656 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0007\n",
|
657 |
+
"Epoch 3/100\n",
|
658 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
|
659 |
+
"Epoch 4/100\n",
|
660 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
661 |
+
"Epoch 5/100\n",
|
662 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
663 |
+
"Epoch 6/100\n",
|
664 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
|
665 |
+
"Epoch 7/100\n",
|
666 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0002\n",
|
667 |
+
"Epoch 8/100\n",
|
668 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
|
669 |
+
"Epoch 9/100\n",
|
670 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0003\n",
|
671 |
+
"Epoch 10/100\n",
|
672 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0003\n",
|
673 |
+
"Epoch 11/100\n",
|
674 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0002\n",
|
675 |
+
"Epoch 12/100\n",
|
676 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
|
677 |
+
"Epoch 13/100\n",
|
678 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
679 |
+
"Epoch 14/100\n",
|
680 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
681 |
+
"Epoch 15/100\n",
|
682 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
683 |
+
"Epoch 16/100\n",
|
684 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
685 |
+
"Epoch 17/100\n",
|
686 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
687 |
+
"Epoch 18/100\n",
|
688 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
|
689 |
+
"Epoch 19/100\n",
|
690 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
|
691 |
+
"Epoch 20/100\n",
|
692 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0001\n",
|
693 |
+
"Epoch 21/100\n",
|
694 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0001\n",
|
695 |
+
"Epoch 22/100\n",
|
696 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0001\n",
|
697 |
+
"Epoch 23/100\n",
|
698 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
699 |
+
"Epoch 24/100\n",
|
700 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
701 |
+
"Epoch 25/100\n",
|
702 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
703 |
+
"Epoch 26/100\n",
|
704 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
705 |
+
"Epoch 27/100\n",
|
706 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
707 |
+
"Epoch 28/100\n",
|
708 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
709 |
+
"Epoch 29/100\n",
|
710 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
711 |
+
"Epoch 30/100\n",
|
712 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
713 |
+
"Epoch 31/100\n",
|
714 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
715 |
+
"Epoch 32/100\n",
|
716 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
717 |
+
"Epoch 33/100\n",
|
718 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
719 |
+
"Epoch 34/100\n",
|
720 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
721 |
+
"Epoch 35/100\n",
|
722 |
+
"1/1 [==============================] - 0s 13ms/step - loss: 1.0000\n",
|
723 |
+
"Epoch 36/100\n",
|
724 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
725 |
+
"Epoch 37/100\n",
|
726 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
727 |
+
"Epoch 38/100\n",
|
728 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
729 |
+
"Epoch 39/100\n",
|
730 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
731 |
+
"Epoch 40/100\n",
|
732 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
733 |
+
"Epoch 41/100\n",
|
734 |
+
"1/1 [==============================] - 0s 14ms/step - loss: 1.0000\n",
|
735 |
+
"Epoch 42/100\n",
|
736 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
737 |
+
"Epoch 43/100\n",
|
738 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
739 |
+
"Epoch 44/100\n",
|
740 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
741 |
+
"Epoch 45/100\n",
|
742 |
+
"1/1 [==============================] - 0s 12ms/step - loss: 1.0000\n",
|
743 |
+
"Epoch 46/100\n",
|
744 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
745 |
+
"Epoch 47/100\n",
|
746 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
747 |
+
"Epoch 48/100\n",
|
748 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
749 |
+
"Epoch 49/100\n",
|
750 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
751 |
+
"Epoch 50/100\n",
|
752 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
753 |
+
"Epoch 51/100\n",
|
754 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
755 |
+
"Epoch 52/100\n",
|
756 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
757 |
+
"Epoch 53/100\n",
|
758 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
759 |
+
"Epoch 54/100\n",
|
760 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
761 |
+
"Epoch 55/100\n",
|
762 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
763 |
+
"Epoch 56/100\n",
|
764 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
765 |
+
"Epoch 57/100\n",
|
766 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
767 |
+
"Epoch 58/100\n",
|
768 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
769 |
+
"Epoch 59/100\n",
|
770 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
771 |
+
"Epoch 60/100\n",
|
772 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
773 |
+
"Epoch 61/100\n",
|
774 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
775 |
+
"Epoch 62/100\n",
|
776 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
777 |
+
"Epoch 63/100\n",
|
778 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
779 |
+
"Epoch 64/100\n",
|
780 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
781 |
+
"Epoch 65/100\n",
|
782 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
783 |
+
"Epoch 66/100\n",
|
784 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
785 |
+
"Epoch 67/100\n",
|
786 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
787 |
+
"Epoch 68/100\n",
|
788 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
789 |
+
"Epoch 69/100\n",
|
790 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
791 |
+
"Epoch 70/100\n",
|
792 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
793 |
+
"Epoch 71/100\n",
|
794 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
795 |
+
"Epoch 72/100\n",
|
796 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
797 |
+
"Epoch 73/100\n",
|
798 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
799 |
+
"Epoch 74/100\n",
|
800 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
801 |
+
"Epoch 75/100\n",
|
802 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
803 |
+
"Epoch 76/100\n",
|
804 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
805 |
+
"Epoch 77/100\n",
|
806 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
807 |
+
"Epoch 78/100\n",
|
808 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
809 |
+
"Epoch 79/100\n",
|
810 |
+
"1/1 [==============================] - 0s 13ms/step - loss: 1.0000\n",
|
811 |
+
"Epoch 80/100\n",
|
812 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
813 |
+
"Epoch 81/100\n",
|
814 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
815 |
+
"Epoch 82/100\n",
|
816 |
+
"1/1 [==============================] - 0s 6ms/step - loss: 1.0000\n",
|
817 |
+
"Epoch 83/100\n",
|
818 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
819 |
+
"Epoch 84/100\n",
|
820 |
+
"1/1 [==============================] - 0s 12ms/step - loss: 1.0000\n",
|
821 |
+
"Epoch 85/100\n",
|
822 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
823 |
+
"Epoch 86/100\n",
|
824 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
825 |
+
"Epoch 87/100\n",
|
826 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
827 |
+
"Epoch 88/100\n",
|
828 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
829 |
+
"Epoch 89/100\n",
|
830 |
+
"1/1 [==============================] - 0s 10ms/step - loss: 1.0000\n",
|
831 |
+
"Epoch 90/100\n",
|
832 |
+
"1/1 [==============================] - 0s 11ms/step - loss: 1.0000\n",
|
833 |
+
"Epoch 91/100\n",
|
834 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
835 |
+
"Epoch 92/100\n",
|
836 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
837 |
+
"Epoch 93/100\n",
|
838 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
839 |
+
"Epoch 94/100\n",
|
840 |
+
"1/1 [==============================] - 0s 9ms/step - loss: 1.0000\n",
|
841 |
+
"Epoch 95/100\n",
|
842 |
+
"1/1 [==============================] - 0s 8ms/step - loss: 1.0000\n",
|
843 |
+
"Epoch 96/100\n",
|
844 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
845 |
+
"Epoch 97/100\n",
|
846 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
847 |
+
"Epoch 98/100\n",
|
848 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
849 |
+
"Epoch 99/100\n",
|
850 |
+
"1/1 [==============================] - 0s 7ms/step - loss: 1.0000\n",
|
851 |
+
"Epoch 100/100\n",
|
852 |
+
"1/1 [==============================] - 0s 6ms/step - loss: 1.0000\n",
|
853 |
+
"1/1 [==============================] - 1s 553ms/step\n",
|
854 |
+
"Predicted Final Results for 2024 (percentages):\n",
|
855 |
+
"AK Dissanayake: 39.57%\n",
|
856 |
+
"Sajith Premadasa: 32.12%\n",
|
857 |
+
"Ranil Wickremesinghe: 21.36%\n",
|
858 |
+
"other: 6.95%\n",
|
859 |
+
"\n",
|
860 |
+
"Second Preference Redistribution:\n",
|
861 |
+
"AKD Final (after redistribution): 44.27%\n",
|
862 |
+
"Sajith Final (after redistribution): 39.59%\n",
|
863 |
+
"AKD wins after second preference votes.\n",
|
864 |
+
"\n",
|
865 |
+
"Final Vote Counts for 17.1 Million People:\n",
|
866 |
+
"AKD Votes: 7569928\n",
|
867 |
+
"Sajith Votes: 6770571\n"
|
868 |
+
]
|
869 |
+
}
|
870 |
+
],
|
871 |
+
"source": [
|
872 |
+
"import numpy as np\n",
|
873 |
+
"import pandas as pd\n",
|
874 |
+
"from sklearn.preprocessing import StandardScaler\n",
|
875 |
+
"from tensorflow.keras.models import Sequential\n",
|
876 |
+
"from tensorflow.keras.layers import LSTM, Dense\n",
|
877 |
+
"\n",
|
878 |
+
"\n",
|
879 |
+
"# Prepare the 2024 poll data (transpose to match time steps)\n",
|
880 |
+
"polls_2024 = df_2024[['April_2024','May_2024', 'June_2024', 'July_2024', 'August_2024', 'September_2024']].values.T\n",
|
881 |
+
"\n",
|
882 |
+
"# Scaling the 2024 poll data\n",
|
883 |
+
"scaler = StandardScaler()\n",
|
884 |
+
"polls_2024_scaled = scaler.fit_transform(polls_2024)\n",
|
885 |
+
"\n",
|
886 |
+
"# Reshape the data to fit the LSTM model input format (samples, time steps, features)\n",
|
887 |
+
"polls_2024_scaled = np.reshape(polls_2024_scaled, (1, polls_2024_scaled.shape[0], polls_2024_scaled.shape[1]))\n",
|
888 |
+
"\n",
|
889 |
+
"# Define a simple LSTM model\n",
|
890 |
+
"model = Sequential()\n",
|
891 |
+
"model.add(LSTM(50, return_sequences=False, input_shape=(polls_2024_scaled.shape[1], polls_2024_scaled.shape[2])))\n",
|
892 |
+
"model.add(Dense(4)) # Output 4 values (one for each candidate)\n",
|
893 |
+
"\n",
|
894 |
+
"# Compile the model\n",
|
895 |
+
"model.compile(optimizer='adam', loss='mean_squared_error')\n",
|
896 |
+
"\n",
|
897 |
+
"# Since we don't have final results, we're using the same polls for training and prediction (this is just an example)\n",
|
898 |
+
"model.fit(polls_2024_scaled, polls_2024_scaled, epochs=100, batch_size=1, verbose=1)\n",
|
899 |
+
"\n",
|
900 |
+
"# Predict the final results for 2024 based on the polls\n",
|
901 |
+
"predicted_final_2024_scaled = model.predict(polls_2024_scaled)\n",
|
902 |
+
"\n",
|
903 |
+
"# Rescale the predictions back to the original scale\n",
|
904 |
+
"predicted_final_2024_rescaled = scaler.inverse_transform(predicted_final_2024_scaled)\n",
|
905 |
+
"\n",
|
906 |
+
"# Normalize the predictions so that they sum to 100%\n",
|
907 |
+
"predicted_final_2024_sum = np.sum(predicted_final_2024_rescaled, axis=1, keepdims=True)\n",
|
908 |
+
"predicted_final_2024_normalized = (predicted_final_2024_rescaled / predicted_final_2024_sum) * 100\n",
|
909 |
+
"\n",
|
910 |
+
"# Display the normalized final results for 2024\n",
|
911 |
+
"print(\"Predicted Final Results for 2024 (percentages):\")\n",
|
912 |
+
"for i, candidate in enumerate(df_2024['Candidate']):\n",
|
913 |
+
" print(f\"{candidate}: {predicted_final_2024_normalized[0][i]:.2f}%\")\n",
|
914 |
+
"\n",
|
915 |
+
"# ---- Second Preference Calculation ---- #\n",
|
916 |
+
"# Define second preference redistribution\n",
|
917 |
+
"second_preference = {\n",
|
918 |
+
" 'AKD_from_Ranil': 0.22,\n",
|
919 |
+
" 'Sajith_from_Ranil': 0.35,\n",
|
920 |
+
" 'AKD_from_Sajith': 0.29,\n",
|
921 |
+
" 'Ranil_from_Sajith': 0.32,\n",
|
922 |
+
" 'Sajith_from_AKD': 0.09,\n",
|
923 |
+
" 'Ranil_from_AKD': 0.11\n",
|
924 |
+
"}\n",
|
925 |
+
"\n",
|
926 |
+
"# First-round results\n",
|
927 |
+
"akd_first_round = predicted_final_2024_normalized[0][0]\n",
|
928 |
+
"sajith_first_round = predicted_final_2024_normalized[0][1]\n",
|
929 |
+
"ranil_first_round = predicted_final_2024_normalized[0][2]\n",
|
930 |
+
"other_first_round = predicted_final_2024_normalized[0][3]\n",
|
931 |
+
"\n",
|
932 |
+
"# Check if a candidate won outright in the first round (>50%)\n",
|
933 |
+
"if akd_first_round > 50 or sajith_first_round > 50:\n",
|
934 |
+
" print(\"First-round winner: No need for second preference votes.\")\n",
|
935 |
+
"else:\n",
|
936 |
+
" # Assume Ranil is eliminated and his votes are redistributed\n",
|
937 |
+
" akd_final = akd_first_round + second_preference['AKD_from_Ranil'] * ranil_first_round\n",
|
938 |
+
" sajith_final = sajith_first_round + second_preference['Sajith_from_Ranil'] * ranil_first_round\n",
|
939 |
+
"\n",
|
940 |
+
" print(\"\\nSecond Preference Redistribution:\")\n",
|
941 |
+
" print(f\"AKD Final (after redistribution): {akd_final:.2f}%\")\n",
|
942 |
+
" print(f\"Sajith Final (after redistribution): {sajith_final:.2f}%\")\n",
|
943 |
+
"\n",
|
944 |
+
" # Determine final winner\n",
|
945 |
+
" if akd_final > sajith_final:\n",
|
946 |
+
" print(\"AKD wins after second preference votes.\")\n",
|
947 |
+
" else:\n",
|
948 |
+
" print(\"Sajith wins after second preference votes.\")\n",
|
949 |
+
"\n",
|
950 |
+
"# ---- Adjust Final Results for Population ---- #\n",
|
951 |
+
"population_size = 17100000 # 17.1 million people\n",
|
952 |
+
"\n",
|
953 |
+
"# Convert percentages to absolute numbers based on the total population\n",
|
954 |
+
"akd_final_votes = (akd_final / 100) * population_size\n",
|
955 |
+
"sajith_final_votes = (sajith_final / 100) * population_size\n",
|
956 |
+
"\n",
|
957 |
+
"print(\"\\nFinal Vote Counts for 17.1 Million People:\")\n",
|
958 |
+
"print(f\"AKD Votes: {akd_final_votes:.0f}\")\n",
|
959 |
+
"print(f\"Sajith Votes: {sajith_final_votes:.0f}\")\n"
|
960 |
+
]
|
961 |
+
},
|
962 |
+
{
|
963 |
+
"cell_type": "code",
|
964 |
+
"execution_count": null,
|
965 |
+
"id": "0b11609b",
|
966 |
+
"metadata": {
|
967 |
+
"id": "0b11609b"
|
968 |
+
},
|
969 |
+
"outputs": [],
|
970 |
+
"source": []
|
971 |
+
}
|
972 |
+
],
|
973 |
+
"metadata": {
|
974 |
+
"kernelspec": {
|
975 |
+
"display_name": "Python 3 (ipykernel)",
|
976 |
+
"language": "python",
|
977 |
+
"name": "python3"
|
978 |
+
},
|
979 |
+
"language_info": {
|
980 |
+
"codemirror_mode": {
|
981 |
+
"name": "ipython",
|
982 |
+
"version": 3
|
983 |
+
},
|
984 |
+
"file_extension": ".py",
|
985 |
+
"mimetype": "text/x-python",
|
986 |
+
"name": "python",
|
987 |
+
"nbconvert_exporter": "python",
|
988 |
+
"pygments_lexer": "ipython3",
|
989 |
+
"version": "3.11.3"
|
990 |
+
},
|
991 |
+
"colab": {
|
992 |
+
"provenance": [],
|
993 |
+
"include_colab_link": true
|
994 |
+
}
|
995 |
+
},
|
996 |
+
"nbformat": 4,
|
997 |
+
"nbformat_minor": 5
|
998 |
+
}
|
webapp/.dart_tool/chrome-device/Default/Affiliation Database
ADDED
Binary file (53.2 kB). View file
|
|
webapp/.dart_tool/chrome-device/Default/Affiliation Database-journal
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/AutofillStrikeDatabase/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/BrowsingTopicsSiteData
ADDED
Binary file (28.7 kB). View file
|
|
webapp/.dart_tool/chrome-device/Default/BrowsingTopicsSiteData-journal
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/BrowsingTopicsState
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"epochs": [ {
|
3 |
+
"calculation_time": "13371013225605854",
|
4 |
+
"config_version": 0,
|
5 |
+
"model_version": "0",
|
6 |
+
"padded_top_topics_start_index": 0,
|
7 |
+
"taxonomy_version": 0,
|
8 |
+
"top_topics_and_observing_domains": [ ]
|
9 |
+
} ],
|
10 |
+
"hex_encoded_hmac_key": "C3CC511CB3EBFBBED1024FB468CB5DD24640AE34E0232CE92B945F8568E4DBCA",
|
11 |
+
"next_scheduled_calculation_time": "13371618025606087"
|
12 |
+
}
|
webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/BudgetDatabase/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/ClientCertificates/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/DIPS
ADDED
Binary file (36.9 kB). View file
|
|
webapp/.dart_tool/chrome-device/Default/DIPS-journal
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Download Service/EntryDB/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Extension Rules/000003.log
ADDED
Binary file (76 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Extension Rules/CURRENT
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
MANIFEST-000001
|
webapp/.dart_tool/chrome-device/Default/Extension Rules/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Extension Rules/LOG
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
2024/09/17-07:50:22.228 e524 Creating DB C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.a4b1993d\flutter_tools_chrome_device.9ace255e\Default\Extension Rules since it was missing.
|
2 |
+
2024/09/17-07:50:22.242 e524 Reusing MANIFEST C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.a4b1993d\flutter_tools_chrome_device.9ace255e\Default\Extension Rules/MANIFEST-000001
|
webapp/.dart_tool/chrome-device/Default/Extension Rules/MANIFEST-000001
ADDED
Binary file (41 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Extension Scripts/000003.log
ADDED
Binary file (76 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Extension Scripts/CURRENT
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
MANIFEST-000001
|
webapp/.dart_tool/chrome-device/Default/Extension Scripts/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Extension Scripts/LOG
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
2024/09/17-07:50:22.245 e524 Creating DB C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.a4b1993d\flutter_tools_chrome_device.9ace255e\Default\Extension Scripts since it was missing.
|
2 |
+
2024/09/17-07:50:22.252 e524 Reusing MANIFEST C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.a4b1993d\flutter_tools_chrome_device.9ace255e\Default\Extension Scripts/MANIFEST-000001
|
webapp/.dart_tool/chrome-device/Default/Extension Scripts/MANIFEST-000001
ADDED
Binary file (41 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Extension State/000003.log
ADDED
Binary file (228 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Extension State/CURRENT
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
MANIFEST-000001
|
webapp/.dart_tool/chrome-device/Default/Extension State/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Extension State/LOG
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
2024/09/18-11:47:53.640 d8a0 Reusing MANIFEST C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.f0fb131c\flutter_tools_chrome_device.b750d91b\Default\Extension State/MANIFEST-000001
|
2 |
+
2024/09/18-11:47:53.641 d8a0 Recovering log #3
|
3 |
+
2024/09/18-11:47:53.641 d8a0 Reusing old log C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.f0fb131c\flutter_tools_chrome_device.b750d91b\Default\Extension State/000003.log
|
webapp/.dart_tool/chrome-device/Default/Extension State/LOG.old
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
2024/09/18-11:26:04.098 cf60 Reusing MANIFEST C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.2d1568ee\flutter_tools_chrome_device.fc475e15\Default\Extension State/MANIFEST-000001
|
2 |
+
2024/09/18-11:26:04.100 cf60 Recovering log #3
|
3 |
+
2024/09/18-11:26:04.101 cf60 Reusing old log C:\Users\Nilakna\AppData\Local\Temp\flutter_tools.2d1568ee\flutter_tools_chrome_device.fc475e15\Default\Extension State/000003.log
|
webapp/.dart_tool/chrome-device/Default/Extension State/MANIFEST-000001
ADDED
Binary file (41 Bytes). View file
|
|
webapp/.dart_tool/chrome-device/Default/Favicons
ADDED
Binary file (57.3 kB). View file
|
|
webapp/.dart_tool/chrome-device/Default/Favicons-journal
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/AvailabilityDB/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOCK
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOG
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/Feature Engagement Tracker/EventDB/LOG.old
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/GCM Store/Encryption/000003.log
ADDED
File without changes
|
webapp/.dart_tool/chrome-device/Default/GCM Store/Encryption/CURRENT
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
MANIFEST-000001
|