diff --git a/Analysis/CCC_analysis.ipynb b/Analysis/CCC_analysis.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..8b5c6715be57e6fec5e87a1b40c7e8f73f3c15ae --- /dev/null +++ b/Analysis/CCC_analysis.ipynb @@ -0,0 +1,1679 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "id": "b07b3d8e", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/kprasath/anaconda3/lib/python3.10/site-packages/fuzzywuzzy/fuzz.py:11: UserWarning: Using slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning\n", + " warnings.warn('Using slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning')\n", + "[nltk_data] Downloading package vader_lexicon to\n", + "[nltk_data] /home/kprasath/nltk_data...\n", + "[nltk_data] Package vader_lexicon is already up-to-date!\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import json\n", + "import pandas as pd\n", + "import numpy as np\n", + "import re\n", + "import nltk\n", + "from nltk.sentiment.vader import SentimentIntensityAnalyzer\n", + "import emoji\n", + "from textblob import TextBlob\n", + "from fuzzywuzzy import process\n", + "import matplotlib.pyplot as plt\n", + "from wordcloud import WordCloud\n", + "\n", + "\n", + "nltk.download('vader_lexicon')" + ] + }, + { + "cell_type": "markdown", + "id": "a5829c2a", + "metadata": {}, + "source": [ + "## Getting the Data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c36304cb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>a40_abduction_and_related_offences</th>\n", + " <th>b30_burglary_break_and_enter</th>\n", + " <th>a10_homicide_and_related_offences</th>\n", + " <th>f30_other_government_regulatory_offences</th>\n", + " <th>lga_code11</th>\n", + " <th>total_division_c_offences</th>\n", + " <th>a30_sexual_offences</th>\n", + " <th>a70_stalking_harassment_and_threatening_behaviour</th>\n", + " <th>e10_justice_procedures</th>\n", + " <th>total_division_f_offences</th>\n", + " <th>...</th>\n", + " <th>total_division_e_offences</th>\n", + " <th>e20_breaches_of_orders</th>\n", + " <th>f10_regulatory_driving_offences</th>\n", + " <th>a60_blackmail_and_extortion</th>\n", + " <th>b40_theft</th>\n", + " <th>c90_other_drug_offences</th>\n", + " <th>f20_transport_regulation_offences</th>\n", + " <th>a20_assault_and_related_offences</th>\n", + " <th>b60_bribery</th>\n", + " <th>c10_drug_dealing_and_trafficking</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>1.0</td>\n", + " <td>27</td>\n", + " <td>0.0</td>\n", + " <td>1.0</td>\n", + " <td>20110</td>\n", + " <td>53</td>\n", + " <td>95</td>\n", + " <td>11</td>\n", + " <td>11</td>\n", + " <td>1</td>\n", + " <td>...</td>\n", + " <td>68</td>\n", + " <td>57</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>90</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>81</td>\n", + " <td>0.0</td>\n", + " <td>9.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>0.0</td>\n", + " <td>69</td>\n", + " <td>0.0</td>\n", + " <td>1.0</td>\n", + " <td>20260</td>\n", + " <td>137</td>\n", + " <td>58</td>\n", + " <td>38</td>\n", + " <td>84</td>\n", + " <td>2</td>\n", + " <td>...</td>\n", + " <td>411</td>\n", + " <td>327</td>\n", + " <td>0.0</td>\n", + " <td>5.0</td>\n", + " <td>222</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>176</td>\n", + " <td>0.0</td>\n", + " <td>24.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>21.0</td>\n", + " <td>983</td>\n", + " <td>4.0</td>\n", + " <td>1.0</td>\n", + " <td>20570</td>\n", + " <td>414</td>\n", + " <td>345</td>\n", + " <td>236</td>\n", + " <td>376</td>\n", + " <td>23</td>\n", + " <td>...</td>\n", + " <td>1884</td>\n", + " <td>1508</td>\n", + " <td>0.0</td>\n", + " <td>7.0</td>\n", + " <td>3501</td>\n", + " <td>5.0</td>\n", + " <td>4.0</td>\n", + " <td>1007</td>\n", + " <td>0.0</td>\n", + " <td>68.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>9.0</td>\n", + " <td>832</td>\n", + " <td>4.0</td>\n", + " <td>1.0</td>\n", + " <td>20660</td>\n", + " <td>513</td>\n", + " <td>185</td>\n", + " <td>266</td>\n", + " <td>192</td>\n", + " <td>13</td>\n", + " <td>...</td>\n", + " <td>2038</td>\n", + " <td>1846</td>\n", + " <td>0.0</td>\n", + " <td>4.0</td>\n", + " <td>2931</td>\n", + " <td>1.0</td>\n", + " <td>3.0</td>\n", + " <td>611</td>\n", + " <td>0.0</td>\n", + " <td>47.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>0.0</td>\n", + " <td>205</td>\n", + " <td>2.0</td>\n", + " <td>2.0</td>\n", + " <td>20740</td>\n", + " <td>154</td>\n", + " <td>74</td>\n", + " <td>119</td>\n", + " <td>48</td>\n", + " <td>5</td>\n", + " <td>...</td>\n", + " <td>378</td>\n", + " <td>330</td>\n", + " <td>0.0</td>\n", + " <td>2.0</td>\n", + " <td>640</td>\n", + " <td>1.0</td>\n", + " <td>2.0</td>\n", + " <td>277</td>\n", + " <td>0.0</td>\n", + " <td>29.0</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>5 rows × 37 columns</p>\n", + "</div>" + ], + "text/plain": [ + " a40_abduction_and_related_offences b30_burglary_break_and_enter \\\n", + "0 1.0 27 \n", + "1 0.0 69 \n", + "2 21.0 983 \n", + "3 9.0 832 \n", + "4 0.0 205 \n", + "\n", + " a10_homicide_and_related_offences \\\n", + "0 0.0 \n", + "1 0.0 \n", + "2 4.0 \n", + "3 4.0 \n", + "4 2.0 \n", + "\n", + " f30_other_government_regulatory_offences lga_code11 \\\n", + "0 1.0 20110 \n", + "1 1.0 20260 \n", + "2 1.0 20570 \n", + "3 1.0 20660 \n", + "4 2.0 20740 \n", + "\n", + " total_division_c_offences a30_sexual_offences \\\n", + "0 53 95 \n", + "1 137 58 \n", + "2 414 345 \n", + "3 513 185 \n", + "4 154 74 \n", + "\n", + " a70_stalking_harassment_and_threatening_behaviour \\\n", + "0 11 \n", + "1 38 \n", + "2 236 \n", + "3 266 \n", + "4 119 \n", + "\n", + " e10_justice_procedures total_division_f_offences ... \\\n", + "0 11 1 ... \n", + "1 84 2 ... \n", + "2 376 23 ... \n", + "3 192 13 ... \n", + "4 48 5 ... \n", + "\n", + " total_division_e_offences e20_breaches_of_orders \\\n", + "0 68 57 \n", + "1 411 327 \n", + "2 1884 1508 \n", + "3 2038 1846 \n", + "4 378 330 \n", + "\n", + " f10_regulatory_driving_offences a60_blackmail_and_extortion b40_theft \\\n", + "0 0.0 0.0 90 \n", + "1 0.0 5.0 222 \n", + "2 0.0 7.0 3501 \n", + "3 0.0 4.0 2931 \n", + "4 0.0 2.0 640 \n", + "\n", + " c90_other_drug_offences f20_transport_regulation_offences \\\n", + "0 0.0 0.0 \n", + "1 0.0 0.0 \n", + "2 5.0 4.0 \n", + "3 1.0 3.0 \n", + "4 1.0 2.0 \n", + "\n", + " a20_assault_and_related_offences b60_bribery \\\n", + "0 81 0.0 \n", + "1 176 0.0 \n", + "2 1007 0.0 \n", + "3 611 0.0 \n", + "4 277 0.0 \n", + "\n", + " c10_drug_dealing_and_trafficking \n", + "0 9.0 \n", + "1 24.0 \n", + "2 68.0 \n", + "3 47.0 \n", + "4 29.0 \n", + "\n", + "[5 rows x 37 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#crime data\n", + "crime_data = pd.read_csv('crime_data.csv')\n", + "crime_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "63621eda", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'pd' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#state data\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m state_data \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241m.\u001b[39mread_csv(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mstate_data.csv\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 3\u001b[0m state_data\u001b[38;5;241m.\u001b[39mhead()\n", + "\u001b[0;31mNameError\u001b[0m: name 'pd' is not defined" + ] + } + ], + "source": [ + "#state data\n", + "state_data = pd.read_csv('state_data.csv')\n", + "state_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "005002d0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ae7cac44", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 4.27 s, sys: 1.02 s, total: 5.29 s\n", + "Wall time: 5.28 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "#using a bigger data \n", + "with open('smallTwitter.json', 'r') as f:\n", + " data = json.load(f)\n", + "\n", + "filtered_data = []\n", + "\n", + "for tweet in data:\n", + " if 'places' in tweet['includes']:\n", + " for place in tweet['includes']['places']:\n", + " if place['full_name'].endswith(', Victoria'):\n", + " area_name, _, _ = place['full_name'].partition(', ')\n", + " if '-' in area_name:\n", + " area_name = area_name.split('-')[0].strip()\n", + "\n", + " filtered_data.append({\n", + " '_id': tweet['_id'],\n", + " #'author_id': tweet['data']['author_id'],\n", + " 'text': tweet['data']['text'],\n", + " 'sentiment': tweet['data'].get('sentiment', None), # returns None if 'sentiment' key doesn't exist\n", + " 'language': tweet['data']['lang'],\n", + " 'area_name': area_name\n", + " })\n", + "\n", + "main_data = pd.DataFrame(filtered_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa806077", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6f5483bb", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "main_data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "067228db", + "metadata": {}, + "source": [ + "## Data cleaning and transformation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c046c5de", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "print(crime_data.isna().sum())\n", + "print(state_data.isna().sum())\n", + "print(main_data.isna().sum())\n", + "\n", + "#Only sentiment has missing values,\n", + "#but we can ignore for now cuz we will be engineering this variable later" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e615112", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "#Same here\n", + "print(crime_data.isnull().sum())\n", + "print(state_data.isnull().sum())\n", + "print(main_data.isnull().sum())" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0f64e183", + "metadata": {}, + "outputs": [], + "source": [ + "# Variable Type Adjustments\n", + "\n", + "#For consistency \n", + "crime_data.columns = crime_data.columns.str.strip()\n", + "state_data.columns = state_data.columns.str.strip()\n", + "main_data.columns = main_data.columns.str.strip()\n", + "\n", + "crime_data['lga_code11'] = crime_data['lga_code11'].astype(int)\n", + "state_data['lga_code'] = state_data['lga_code'].astype(int)\n", + "main_data['_id'] = main_data['_id'].astype(str)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b1117bb", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e98d301", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "3598d554", + "metadata": {}, + "source": [ + "### Text Cleaning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba4a5991", + "metadata": {}, + "outputs": [], + "source": [ + "main_data[['text']].head(5)" + ] + }, + { + "cell_type": "markdown", + "id": "62a7dc99", + "metadata": {}, + "source": [ + "Cleaning the data:\n", + "\n", + "- Remove URLs: Since URLs generally don't contribute to sentiment, we can remove them.\n", + "- Remove mentions: Mentions (@username) may or may not contribute to sentiment, but they can be problematic for analysis due to their variability.\n", + "- Remove special characters: These generally don't contribute to sentiment and can make analysis more difficult.\n", + "- Remove numbers: Numbers don't contribute to sentiment and can be safely removed.\n", + "- Convert to lowercase: Case doesn't matter for sentiment, and converting to lowercase can simplify subsequent analysis.\n", + "- Remove extra spaces: Cleaning up extra spaces will make the text more consistent for analysis.\n", + "\n", + "Feature extraction:\n", + "\n", + "- Number of hashtags: Hashtags can be indicators of the topic or intensity of a tweet, so we'll count them.\n", + "- Number of words: The length of a tweet can be a useful feature.\n", + "- Number of characters: This can also be a useful feature.\n", + "- Sentiment analysis: We will use NLTK's VADER sentiment analysis tool to compute sentiment scores for each cleaned tweet." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c2098a0", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "main_data.language.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "aa9b575d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 7.76 s, sys: 3.76 ms, total: 7.76 s\n", + "Wall time: 7.76 s\n" + ] + }, + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>_id</th>\n", + " <th>text</th>\n", + " <th>sentiment</th>\n", + " <th>language</th>\n", + " <th>area_name</th>\n", + " <th>cleaned_text</th>\n", + " <th>num_hashtags</th>\n", + " <th>num_words</th>\n", + " <th>num_chars</th>\n", + " <th>num_emojis</th>\n", + " <th>subjectivity</th>\n", + " <th>sentiment_score</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>1414031972041588744</td>\n", + " <td>Stella is spending the day with her cousin Mon...</td>\n", + " <td>0.000000</td>\n", + " <td>en</td>\n", + " <td>Ocean Grove</td>\n", + " <td>stella is spending the day with her cousin monty</td>\n", + " <td>0</td>\n", + " <td>9</td>\n", + " <td>48</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>1414032158197354497</td>\n", + " <td>@eleaud Oh no! I hope they don’t go up any fur...</td>\n", + " <td>0.090909</td>\n", + " <td>en</td>\n", + " <td>Ocean Grove</td>\n", + " <td>oh no i hope they dont go up any further</td>\n", + " <td>0</td>\n", + " <td>10</td>\n", + " <td>40</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.1779</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>1414036352308445186</td>\n", + " <td>Sunday @afl R17: #aflgiantssuns #afldogsswans ...</td>\n", + " <td>0.000000</td>\n", + " <td>en</td>\n", + " <td>Drysdale</td>\n", + " <td>sunday r aflgiantssuns afldogsswans afltigerspies</td>\n", + " <td>0</td>\n", + " <td>5</td>\n", + " <td>49</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>1414044890040733699</td>\n", + " <td>@BlancheVerlie Sorry to watch the declining si...</td>\n", + " <td>0.058824</td>\n", + " <td>en</td>\n", + " <td>Ocean Grove</td>\n", + " <td>sorry to watch the declining situation up ther...</td>\n", + " <td>0</td>\n", + " <td>33</td>\n", + " <td>166</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.7717</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>1414057294950649861</td>\n", + " <td>@VicGovAu One lady had over 40 saved photos of...</td>\n", + " <td>0.090909</td>\n", + " <td>en</td>\n", + " <td>Drysdale</td>\n", + " <td>one lady had over saved photos of login cube s...</td>\n", + " <td>0</td>\n", + " <td>20</td>\n", + " <td>99</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.4215</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " _id text \\\n", + "0 1414031972041588744 Stella is spending the day with her cousin Mon... \n", + "1 1414032158197354497 @eleaud Oh no! I hope they don’t go up any fur... \n", + "2 1414036352308445186 Sunday @afl R17: #aflgiantssuns #afldogsswans ... \n", + "3 1414044890040733699 @BlancheVerlie Sorry to watch the declining si... \n", + "4 1414057294950649861 @VicGovAu One lady had over 40 saved photos of... \n", + "\n", + " sentiment language area_name \\\n", + "0 0.000000 en Ocean Grove \n", + "1 0.090909 en Ocean Grove \n", + "2 0.000000 en Drysdale \n", + "3 0.058824 en Ocean Grove \n", + "4 0.090909 en Drysdale \n", + "\n", + " cleaned_text num_hashtags num_words \\\n", + "0 stella is spending the day with her cousin monty 0 9 \n", + "1 oh no i hope they dont go up any further 0 10 \n", + "2 sunday r aflgiantssuns afldogsswans afltigerspies 0 5 \n", + "3 sorry to watch the declining situation up ther... 0 33 \n", + "4 one lady had over saved photos of login cube s... 0 20 \n", + "\n", + " num_chars num_emojis subjectivity sentiment_score \n", + "0 48 0 0.0 0.0000 \n", + "1 40 0 0.5 0.1779 \n", + "2 49 0 0.0 0.0000 \n", + "3 166 0 0.5 0.7717 \n", + "4 99 0 0.5 0.4215 " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time \n", + "\n", + "# Initialize the sentiment analyzer\n", + "sia = SentimentIntensityAnalyzer()\n", + "\n", + "def clean_text(text):\n", + " text = re.sub(r'http\\S+|www.\\S+', '', text) \n", + " text = re.sub(r'@\\w+', '', text) \n", + " text = re.sub(r'[^A-Za-z\\s]', '', text) \n", + " text = re.sub(r'\\d+', '', text) \n", + " text = re.sub(r'\\s{2,}', ' ', text) \n", + " text = text.lower() \n", + " return text.strip() \n", + "\n", + "def extract_features(text):\n", + " num_hashtags = text.count('#')\n", + " num_words = len(text.split())\n", + " num_chars = len(text)\n", + " num_emojis = emoji.emoji_count(text)\n", + " return num_hashtags, num_words, num_chars, num_emojis\n", + "\n", + "def extract_subjectivity(text):\n", + " return TextBlob(text).sentiment.subjectivity\n", + "\n", + "def get_sentiment_score(text):\n", + " return sia.polarity_scores(text)['compound']\n", + "\n", + "# Filter out the non-English tweets from the main data\n", + "main_data = main_data[main_data['language'] == 'en'].copy()\n", + "\n", + "# Apply the cleaning function to the 'text' column\n", + "main_data.loc[:, 'cleaned_text'] = main_data['text'].apply(clean_text)\n", + "\n", + "# Apply the feature extraction function to the cleaned text and create new columns\n", + "main_data['num_hashtags'], main_data['num_words'], main_data['num_chars'], main_data['num_emojis'] = zip(*main_data['cleaned_text'].map(extract_features))\n", + "\n", + "# Apply sentiment analyzer to get the polarity scores and create a new column for that\n", + "main_data['subjectivity'] = main_data['cleaned_text'].apply(extract_subjectivity)\n", + "\n", + "# Add sentiment score\n", + "main_data['sentiment_score'] = main_data['cleaned_text'].apply(get_sentiment_score)\n", + "\n", + "\n", + "main_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a4d5c90b", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>area_name</th>\n", + " <th>cleaned_text</th>\n", + " <th>num_hashtags</th>\n", + " <th>num_words</th>\n", + " <th>num_chars</th>\n", + " <th>num_emojis</th>\n", + " <th>subjectivity</th>\n", + " <th>sentiment_score</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>Ocean Grove</td>\n", + " <td>stella is spending the day with her cousin monty</td>\n", + " <td>0</td>\n", + " <td>9</td>\n", + " <td>48</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>Ocean Grove</td>\n", + " <td>oh no i hope they dont go up any further</td>\n", + " <td>0</td>\n", + " <td>10</td>\n", + " <td>40</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.1779</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>Drysdale</td>\n", + " <td>sunday r aflgiantssuns afldogsswans afltigerspies</td>\n", + " <td>0</td>\n", + " <td>5</td>\n", + " <td>49</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>Ocean Grove</td>\n", + " <td>sorry to watch the declining situation up ther...</td>\n", + " <td>0</td>\n", + " <td>33</td>\n", + " <td>166</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.7717</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>Drysdale</td>\n", + " <td>one lady had over saved photos of login cube s...</td>\n", + " <td>0</td>\n", + " <td>20</td>\n", + " <td>99</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.4215</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " area_name cleaned_text \\\n", + "0 Ocean Grove stella is spending the day with her cousin monty \n", + "1 Ocean Grove oh no i hope they dont go up any further \n", + "2 Drysdale sunday r aflgiantssuns afldogsswans afltigerspies \n", + "3 Ocean Grove sorry to watch the declining situation up ther... \n", + "4 Drysdale one lady had over saved photos of login cube s... \n", + "\n", + " num_hashtags num_words num_chars num_emojis subjectivity \\\n", + "0 0 9 48 0 0.0 \n", + "1 0 10 40 0 0.5 \n", + "2 0 5 49 0 0.0 \n", + "3 0 33 166 0 0.5 \n", + "4 0 20 99 0 0.5 \n", + "\n", + " sentiment_score \n", + "0 0.0000 \n", + "1 0.1779 \n", + "2 0.0000 \n", + "3 0.7717 \n", + "4 0.4215 " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text_data = main_data.drop(['_id', 'text', 'sentiment', 'language'], axis=1)\n", + "text_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af84dddc", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'state_data' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstate_data\u001b[49m\u001b[38;5;241m.\u001b[39mdtypes\n", + "\u001b[0;31mNameError\u001b[0m: name 'state_data' is not defined" + ] + } + ], + "source": [ + "state_data.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0ef3468a", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'state_data' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstate_data\u001b[49m\u001b[38;5;241m.\u001b[39mhead()\n", + "\u001b[0;31mNameError\u001b[0m: name 'state_data' is not defined" + ] + } + ], + "source": [ + "state_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d970d153", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>a40_abduction_and_related_offences</th>\n", + " <th>b30_burglary_break_and_enter</th>\n", + " <th>a10_homicide_and_related_offences</th>\n", + " <th>f30_other_government_regulatory_offences</th>\n", + " <th>lga_code11</th>\n", + " <th>total_division_c_offences</th>\n", + " <th>a30_sexual_offences</th>\n", + " <th>a70_stalking_harassment_and_threatening_behaviour</th>\n", + " <th>e10_justice_procedures</th>\n", + " <th>total_division_f_offences</th>\n", + " <th>...</th>\n", + " <th>total_division_e_offences</th>\n", + " <th>e20_breaches_of_orders</th>\n", + " <th>f10_regulatory_driving_offences</th>\n", + " <th>a60_blackmail_and_extortion</th>\n", + " <th>b40_theft</th>\n", + " <th>c90_other_drug_offences</th>\n", + " <th>f20_transport_regulation_offences</th>\n", + " <th>a20_assault_and_related_offences</th>\n", + " <th>b60_bribery</th>\n", + " <th>c10_drug_dealing_and_trafficking</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>1.0</td>\n", + " <td>27</td>\n", + " <td>0.0</td>\n", + " <td>1.0</td>\n", + " <td>20110</td>\n", + " <td>53</td>\n", + " <td>95</td>\n", + " <td>11</td>\n", + " <td>11</td>\n", + " <td>1</td>\n", + " <td>...</td>\n", + " <td>68</td>\n", + " <td>57</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>90</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>81</td>\n", + " <td>0.0</td>\n", + " <td>9.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>0.0</td>\n", + " <td>69</td>\n", + " <td>0.0</td>\n", + " <td>1.0</td>\n", + " <td>20260</td>\n", + " <td>137</td>\n", + " <td>58</td>\n", + " <td>38</td>\n", + " <td>84</td>\n", + " <td>2</td>\n", + " <td>...</td>\n", + " <td>411</td>\n", + " <td>327</td>\n", + " <td>0.0</td>\n", + " <td>5.0</td>\n", + " <td>222</td>\n", + " <td>0.0</td>\n", + " <td>0.0</td>\n", + " <td>176</td>\n", + " <td>0.0</td>\n", + " <td>24.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>21.0</td>\n", + " <td>983</td>\n", + " <td>4.0</td>\n", + " <td>1.0</td>\n", + " <td>20570</td>\n", + " <td>414</td>\n", + " <td>345</td>\n", + " <td>236</td>\n", + " <td>376</td>\n", + " <td>23</td>\n", + " <td>...</td>\n", + " <td>1884</td>\n", + " <td>1508</td>\n", + " <td>0.0</td>\n", + " <td>7.0</td>\n", + " <td>3501</td>\n", + " <td>5.0</td>\n", + " <td>4.0</td>\n", + " <td>1007</td>\n", + " <td>0.0</td>\n", + " <td>68.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>9.0</td>\n", + " <td>832</td>\n", + " <td>4.0</td>\n", + " <td>1.0</td>\n", + " <td>20660</td>\n", + " <td>513</td>\n", + " <td>185</td>\n", + " <td>266</td>\n", + " <td>192</td>\n", + " <td>13</td>\n", + " <td>...</td>\n", + " <td>2038</td>\n", + " <td>1846</td>\n", + " <td>0.0</td>\n", + " <td>4.0</td>\n", + " <td>2931</td>\n", + " <td>1.0</td>\n", + " <td>3.0</td>\n", + " <td>611</td>\n", + " <td>0.0</td>\n", + " <td>47.0</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>0.0</td>\n", + " <td>205</td>\n", + " <td>2.0</td>\n", + " <td>2.0</td>\n", + " <td>20740</td>\n", + " <td>154</td>\n", + " <td>74</td>\n", + " <td>119</td>\n", + " <td>48</td>\n", + " <td>5</td>\n", + " <td>...</td>\n", + " <td>378</td>\n", + " <td>330</td>\n", + " <td>0.0</td>\n", + " <td>2.0</td>\n", + " <td>640</td>\n", + " <td>1.0</td>\n", + " <td>2.0</td>\n", + " <td>277</td>\n", + " <td>0.0</td>\n", + " <td>29.0</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>5 rows × 37 columns</p>\n", + "</div>" + ], + "text/plain": [ + " a40_abduction_and_related_offences b30_burglary_break_and_enter \\\n", + "0 1.0 27 \n", + "1 0.0 69 \n", + "2 21.0 983 \n", + "3 9.0 832 \n", + "4 0.0 205 \n", + "\n", + " a10_homicide_and_related_offences \\\n", + "0 0.0 \n", + "1 0.0 \n", + "2 4.0 \n", + "3 4.0 \n", + "4 2.0 \n", + "\n", + " f30_other_government_regulatory_offences lga_code11 \\\n", + "0 1.0 20110 \n", + "1 1.0 20260 \n", + "2 1.0 20570 \n", + "3 1.0 20660 \n", + "4 2.0 20740 \n", + "\n", + " total_division_c_offences a30_sexual_offences \\\n", + "0 53 95 \n", + "1 137 58 \n", + "2 414 345 \n", + "3 513 185 \n", + "4 154 74 \n", + "\n", + " a70_stalking_harassment_and_threatening_behaviour e10_justice_procedures \\\n", + "0 11 11 \n", + "1 38 84 \n", + "2 236 376 \n", + "3 266 192 \n", + "4 119 48 \n", + "\n", + " total_division_f_offences ... total_division_e_offences \\\n", + "0 1 ... 68 \n", + "1 2 ... 411 \n", + "2 23 ... 1884 \n", + "3 13 ... 2038 \n", + "4 5 ... 378 \n", + "\n", + " e20_breaches_of_orders f10_regulatory_driving_offences \\\n", + "0 57 0.0 \n", + "1 327 0.0 \n", + "2 1508 0.0 \n", + "3 1846 0.0 \n", + "4 330 0.0 \n", + "\n", + " a60_blackmail_and_extortion b40_theft c90_other_drug_offences \\\n", + "0 0.0 90 0.0 \n", + "1 5.0 222 0.0 \n", + "2 7.0 3501 5.0 \n", + "3 4.0 2931 1.0 \n", + "4 2.0 640 1.0 \n", + "\n", + " f20_transport_regulation_offences a20_assault_and_related_offences \\\n", + "0 0.0 81 \n", + "1 0.0 176 \n", + "2 4.0 1007 \n", + "3 3.0 611 \n", + "4 2.0 277 \n", + "\n", + " b60_bribery c10_drug_dealing_and_trafficking \n", + "0 0.0 9.0 \n", + "1 0.0 24.0 \n", + "2 0.0 68.0 \n", + "3 0.0 47.0 \n", + "4 0.0 29.0 \n", + "\n", + "[5 rows x 37 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crime_data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "bb62f0d1", + "metadata": {}, + "source": [ + "## Data integration & Mapping" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0960e5a5", + "metadata": {}, + "outputs": [], + "source": [ + "state_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "076dd0c3", + "metadata": {}, + "outputs": [], + "source": [ + "lga_code_mapping = state_data.set_index('scc_name')['lga_code']\n", + "\n", + "text_data['lga_code'] = text_data['area_name'].map(lga_code_mapping)\n", + "\n", + "state_data_unique = state_data.groupby('lga_code').agg({\n", + " 'lga_name': 'first',\n", + " 'lat': 'mean',\n", + " 'lon': 'mean'\n", + "}).reset_index()\n", + "\n", + "text_data = text_data.merge(state_data_unique, on='lga_code', how='left')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "eb8d7900", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>area_name</th>\n", + " <th>cleaned_text</th>\n", + " <th>num_hashtags</th>\n", + " <th>num_words</th>\n", + " <th>num_chars</th>\n", + " <th>num_emojis</th>\n", + " <th>subjectivity</th>\n", + " <th>sentiment_score</th>\n", + " <th>lga_code</th>\n", + " <th>lga_name</th>\n", + " <th>lat</th>\n", + " <th>lon</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>Ocean Grove</td>\n", + " <td>stella is spending the day with her cousin monty</td>\n", + " <td>0</td>\n", + " <td>9</td>\n", + " <td>48</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " <td>22750.0</td>\n", + " <td>Greater Geelong</td>\n", + " <td>-38.145829</td>\n", + " <td>144.416254</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>Ocean Grove</td>\n", + " <td>oh no i hope they dont go up any further</td>\n", + " <td>0</td>\n", + " <td>10</td>\n", + " <td>40</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.1779</td>\n", + " <td>22750.0</td>\n", + " <td>Greater Geelong</td>\n", + " <td>-38.145829</td>\n", + " <td>144.416254</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>Drysdale</td>\n", + " <td>sunday r aflgiantssuns afldogsswans afltigerspies</td>\n", + " <td>0</td>\n", + " <td>5</td>\n", + " <td>49</td>\n", + " <td>0</td>\n", + " <td>0.0</td>\n", + " <td>0.0000</td>\n", + " <td>22750.0</td>\n", + " <td>Greater Geelong</td>\n", + " <td>-38.145829</td>\n", + " <td>144.416254</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>Ocean Grove</td>\n", + " <td>sorry to watch the declining situation up ther...</td>\n", + " <td>0</td>\n", + " <td>33</td>\n", + " <td>166</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.7717</td>\n", + " <td>22750.0</td>\n", + " <td>Greater Geelong</td>\n", + " <td>-38.145829</td>\n", + " <td>144.416254</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>Drysdale</td>\n", + " <td>one lady had over saved photos of login cube s...</td>\n", + " <td>0</td>\n", + " <td>20</td>\n", + " <td>99</td>\n", + " <td>0</td>\n", + " <td>0.5</td>\n", + " <td>0.4215</td>\n", + " <td>22750.0</td>\n", + " <td>Greater Geelong</td>\n", + " <td>-38.145829</td>\n", + " <td>144.416254</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " area_name cleaned_text \\\n", + "0 Ocean Grove stella is spending the day with her cousin monty \n", + "1 Ocean Grove oh no i hope they dont go up any further \n", + "2 Drysdale sunday r aflgiantssuns afldogsswans afltigerspies \n", + "3 Ocean Grove sorry to watch the declining situation up ther... \n", + "4 Drysdale one lady had over saved photos of login cube s... \n", + "\n", + " num_hashtags num_words num_chars num_emojis subjectivity \\\n", + "0 0 9 48 0 0.0 \n", + "1 0 10 40 0 0.5 \n", + "2 0 5 49 0 0.0 \n", + "3 0 33 166 0 0.5 \n", + "4 0 20 99 0 0.5 \n", + "\n", + " sentiment_score lga_code lga_name lat lon \n", + "0 0.0000 22750.0 Greater Geelong -38.145829 144.416254 \n", + "1 0.1779 22750.0 Greater Geelong -38.145829 144.416254 \n", + "2 0.0000 22750.0 Greater Geelong -38.145829 144.416254 \n", + "3 0.7717 22750.0 Greater Geelong -38.145829 144.416254 \n", + "4 0.4215 22750.0 Greater Geelong -38.145829 144.416254 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "91fcfdbb", + "metadata": {}, + "outputs": [], + "source": [ + "#crim data merging\n", + "\n", + "# Assuming crime_data and state_data are your two dataframes\n", + "# and 'lga_code' is the name of the column with the LGA code in both dataframes\n", + "# and 'lga_code11' is the column name in crime_data\n", + "\n", + "# First, make sure the 'lga_code' columns in both dataframes are of the same type\n", + "crime_data['lga_code11'] = crime_data['lga_code11'].astype(str)\n", + "state_data['lga_code'] = state_data['lga_code'].astype(str)\n", + "\n", + "# Then, merge the dataframes\n", + "merged_data = pd.merge(crime_data, state_data, left_on='lga_code11', right_on='lga_code', how='left')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a31d6efe", + "metadata": {}, + "outputs": [], + "source": [ + "#merged_data.to_csv('crime_spatial.csv', index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3e96a60f", + "metadata": {}, + "outputs": [], + "source": [ + "#text_data.to_csv('textdatafor_spatial.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "id": "e3c87512", + "metadata": {}, + "source": [ + "# Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "68f5899b", + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "\"['new_sentiment', 'compound'] not in index\"", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[12], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mtext_data\u001b[49m\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnum_hashtags\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnum_words\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnum_chars\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnew_sentiment\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnum_emojis\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mcompound\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43msubjectivity\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241m.\u001b[39mdescribe()\n", + "File \u001b[0;32m~/anaconda3/lib/python3.10/site-packages/pandas/core/frame.py:3813\u001b[0m, in \u001b[0;36mDataFrame.__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 3811\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_iterator(key):\n\u001b[1;32m 3812\u001b[0m key \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(key)\n\u001b[0;32m-> 3813\u001b[0m indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_indexer_strict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcolumns\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m[\u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 3815\u001b[0m \u001b[38;5;66;03m# take() does not accept boolean indexers\u001b[39;00m\n\u001b[1;32m 3816\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(indexer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdtype\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mbool\u001b[39m:\n", + "File \u001b[0;32m~/anaconda3/lib/python3.10/site-packages/pandas/core/indexes/base.py:6070\u001b[0m, in \u001b[0;36mIndex._get_indexer_strict\u001b[0;34m(self, key, axis_name)\u001b[0m\n\u001b[1;32m 6067\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 6068\u001b[0m keyarr, indexer, new_indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reindex_non_unique(keyarr)\n\u001b[0;32m-> 6070\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_raise_if_missing\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeyarr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6072\u001b[0m keyarr \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtake(indexer)\n\u001b[1;32m 6073\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, Index):\n\u001b[1;32m 6074\u001b[0m \u001b[38;5;66;03m# GH 42790 - Preserve name from an Index\u001b[39;00m\n", + "File \u001b[0;32m~/anaconda3/lib/python3.10/site-packages/pandas/core/indexes/base.py:6133\u001b[0m, in \u001b[0;36mIndex._raise_if_missing\u001b[0;34m(self, key, indexer, axis_name)\u001b[0m\n\u001b[1;32m 6130\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNone of [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkey\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] are in the [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maxis_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m]\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 6132\u001b[0m not_found \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(ensure_index(key)[missing_mask\u001b[38;5;241m.\u001b[39mnonzero()[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39munique())\n\u001b[0;32m-> 6133\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnot_found\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in index\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[0;31mKeyError\u001b[0m: \"['new_sentiment', 'compound'] not in index\"" + ] + } + ], + "source": [ + "#text_data[['num_hashtags', 'num_words', 'num_chars', 'new_sentiment', 'num_emojis', 'compound', 'subjectivity']].describe()\n" + ] + }, + { + "cell_type": "markdown", + "id": "5db957df", + "metadata": {}, + "source": [ + "plt.hist(text_data['new_sentiment'], bins=20, alpha=0.5)\n", + "plt.xlabel('Sentiment Score')\n", + "plt.ylabel('Frequency')\n", + "plt.title('Sentiment Distribution')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "4b8425bb", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABxHklEQVR4nO3deVxUZf//8ffIJqCMKyCJaOWaWi7dilZYrinaboWhppl9LQ2XLOsutbu0LJfKFitTb5f0brHVSCu1DNylcklbyCVBzRC0FFSu3x/+ODoOKExwgPH1fDx4PJwznznnus7AnMv3XOcchzHGCAAAAAAAALBRhdJuAAAAAAAAAC48hFIAAAAAAACwHaEUAAAAAAAAbEcoBQAAAAAAANsRSgEAAAAAAMB2hFIAAAAAAACwHaEUAAAAAAAAbEcoBQAAAAAAANsRSgEAAAAAAMB2hFKAl1izZo1uuukm1alTRwEBAQoLC1N0dLRGjhxZotv9+++/NW7cOK1YscLtudmzZ8vhcOi3334r0Tb8UwsWLNC0adMKXd+hQwc5HA45HA5VqFBBlStX1qWXXqrbbrtN7777rnJzc91eU7duXfXv379I7UpKStK4ceN06NChIr3u7G2tWLFCDodD7777bpHWcy7e8L4DAC4cxT1OyjvWrV+//ry1/fv3V926dT3aTmEsWbJE48aNy/c5T8Yf0umxw5nH+XNt559gXMW4Chc239JuAIB/7tNPP1WvXr3UoUMHTZo0SbVq1VJaWprWr1+vhQsXavLkySW27b///lvjx4+XdGpQcaYePXooOTlZtWrVKrHtF4cFCxZo8+bNSkhIKPRrLr74Ys2fP1+S9Ndffyk1NVUffPCBbrvtNl199dX6+OOP5XQ6rfrFixcrJCSkSO1KSkrS+PHj1b9/f1WpUqXQr/NkW0XlDe87AODCUJrjJEl6/PHH9eCDD5bY+pcsWaKXX34538DI0zFBy5YtlZycrCZNmhRqO/8U4yrGVbhwEUoBXmDSpEmqV6+ePv/8c/n6nv6zvuOOOzRp0qRSa1fNmjVVs2bNUtt+SQoMDFTbtm1dlt1zzz2aNWuWBgwYoHvvvVeLFi2ynmvRokWJt+no0aMKDAy0ZVvn4s3vOwCg/CntcdIll1xS4tsoiKdjgpCQELdxTkliXFUwxlXwdpy+B3iBgwcPqkaNGi4DrTwVKrj/mS9atEjR0dEKDg5WpUqV1LVrV23atMmlpn///qpUqZJ+/vlnde/eXZUqVVJkZKRGjhyp7OxsSdJvv/1mHSTHjx9vTb3Om+Kc33TjDh06qGnTpkpOTla7du0UGBiounXratasWZJOfZvZsmVLBQUFqVmzZkpMTHRr/08//aS4uDiFhoYqICBAjRs31ssvv+xSkze1+u2339Zjjz2miIgIhYSEqFOnTtq+fbtLez799FPt3LnTar/D4SjEXs/f3Xffre7du+udd97Rzp07reVnT/3Ozc3VU089pYYNGyowMFBVqlRR8+bN9cILL0iSxo0bp4ceekiSVK9ePatdedO669atq9jYWL3//vtq0aKFKlasaH3DVtCU9mPHjmnEiBEKDw9XYGCgYmJi3N73Dh06uH1DJ7meeuDJ+y5Jb731li6//HJVrFhR1apV00033aRt27a5bed8v3cAABRFUcZJDocj35lABR1bMzIydPfdd6tatWoKDg5Wz5499euvv7rU5Hf6njFGr7zyiq644goFBgaqatWquvXWW91eK0mJiYnq2LGjnE6ngoKC1LhxY02cONFad94Y6MxxTN4x+Mx2HzhwQP7+/nr88cfdtvHjjz/K4XDoxRdflOR++t65ttOxY0c1atRIxhi3Pl566aXq0aOH2/YKi3EV4yp4P0IpwAtER0drzZo1GjZsmNasWaPjx48XWDthwgTdeeedatKkif73v/9p7ty5Onz4sK6++mpt3brVpfb48ePq1auXOnbsqA8//FADBgzQ1KlT9eyzz0qSatWqZYVGAwcOVHJyspKTk/Md7JwpPT1dd999t+655x59+OGHatasmQYMGKAnn3xSY8aM0ejRo/Xee++pUqVKuvHGG7V3717rtVu3btWVV16pzZs3a/Lkyfrkk0/Uo0cPDRs2zBo8nOnRRx/Vzp079eabb+r111/XTz/9pJ49e+rkyZOSpFdeeUXt27dXeHi41f7k5OTC7fgC9OrVS8YYffPNNwXWTJo0SePGjdOdd96pTz/9VIsWLdLAgQOt6xzcc889Gjp0qCTp/ffft9rVsmVLax0bN27UQw89pGHDhikxMVG33HLLOdv16KOP6tdff9Wbb76pN998U3v37lWHDh3yHQCfiyfv+8SJEzVw4EBddtllev/99/XCCy/o+++/V3R0tH766SeX2vP93gEAUBRFGScV1cCBA1WhQgXr+pRr165Vhw4dznvdosGDByshIUGdOnXSBx98oFdeeUVbtmxRu3bttG/fPqtu5syZ6t69u3Jzc/Xaa6/p448/1rBhw7Rnzx5Jp04NvPXWWyXJZRyT36leNWvWVGxsrObMmeN2naZZs2bJ399fffr0ybe959rOgw8+qO3bt+vLL790ec1nn32mX375Rffff/+5d+J5MK5yx7gKXsUAKPf++OMPc9VVVxlJRpLx8/Mz7dq1MxMnTjSHDx+26nbt2mV8fX3N0KFDXV5/+PBhEx4ebnr37m0t69evn5Fk/ve//7nUdu/e3TRs2NB6fODAASPJjB071q1ds2bNMpJMamqqtSwmJsZIMuvXr7eWHTx40Pj4+JjAwEDz+++/W8tTUlKMJPPiiy9ay7p27Wpq165tMjMzXbb1wAMPmIoVK5o///zTGGPM8uXLjSTTvXt3l7r//e9/RpJJTk62lvXo0cNERUW5tb8gMTEx5rLLLivw+c8++8xIMs8++6y1LCoqyvTr1896HBsba6644opzbue5555z239nrs/Hx8ds37493+fO3FbevmjZsqXJzc21lv/222/Gz8/P3HPPPS59i4mJcVtnv379XPZRUd73jIwMExgY6PZe7Nq1ywQEBJi4uDiX7RTm9w4AgMIq7DjJGFPgse3sY2vese6mm25yqfv222+NJPPUU09Zy84+hiYnJxtJZvLkyS6v3b17twkMDDSjR482xpwan4WEhJirrrrK5fh9tvvvv98U9N+6s9v90UcfGUlm6dKl1rITJ06YiIgIc8stt1jL8sYOy5cvP+92Tp48aS6++GJzww03uCy//vrrzSWXXHLOthvDuMoYxlW4sDFTCvAC1atX1zfffKN169bpmWee0Q033KAdO3ZozJgxatasmf744w9J0ueff64TJ06ob9++OnHihPVTsWJFxcTEuN3xw+FwqGfPni7Lmjdv7jJ92hO1atVSq1atrMfVqlVTaGiorrjiCkVERFjLGzduLEnW9o4dO6Yvv/xSN910k4KCglz60L17dx07dkyrV6922VavXr3c2n/mOkuCOWv6en7+9a9/6bvvvtOQIUP0+eefKysrq8jbad68uRo0aFDo+ri4OJdTE6OiotSuXTstX768yNsuiuTkZB09etRt6ntkZKSuu+46t29WS+r3DgBwYSrsOMkTZ88sateunaKios55bP3kk0/kcDh01113uYxlwsPDdfnll1vjsaSkJGVlZWnIkCH/6NICZ7r++usVHh5uXTZBOjU+3Lt3rwYMGODROitUqKAHHnhAn3zyiXbt2iVJ+uWXX5SYmFgsbWdc5YpxFbwNoRTgRVq3bq2HH35Y77zzjvbu3avhw4frt99+sy7imTcd/Morr5Sfn5/Lz6JFi9wGZUFBQapYsaLLsoCAAB07duwftbNatWpuy/z9/d2W+/v7S5K1vYMHD+rEiRN66aWX3NrfvXt3SXLrQ/Xq1d3aL526eGVJyTvInxmwnW3MmDF6/vnntXr1al1//fWqXr26OnbsWKhbS+cp6l1YwsPD81128ODBIq2nqPLWn197IyIi3LZfUr93AIAL2/nGSZ7w5Ni6b98+GWMUFhbmNp5ZvXq1NZY5cOCAJKl27doet+9svr6+io+P1+LFi61T22bPnq1atWqpa9euHq93wIABCgwM1GuvvSZJevnllxUYGOhx0HUmxlWuGFfB2xBKAV7Kz89PY8eOlSRt3rxZklSjRg1J0rvvvqt169a5/axZs6bU2lsYVatWlY+Pj/r3759v+9etW2eFU6Xpo48+ksPh0DXXXFNgja+vr0aMGKGNGzfqzz//1Ntvv63du3era9eu+vvvvwu1naJ+85ienp7vsjODu4oVK+Z74ct/8i1y3vrT0tLcntu7d6/1ewkAgF3yGydJp/6znt9xsKCgoTDH1rPVqFFDDodDq1atyncs88EHH0iSdfHrvOtHFZe7775bx44d08KFC5WRkaGPPvpIffv2lY+Pj8frdDqd6tevn9588039+eefmjVrluLi4lSlSpV/3F7GVa4YV8HbEEoBXiC/g5Ik6w4ced8sde3aVb6+vvrll1/UunXrfH+Kyo6ZR3mCgoJ07bXXatOmTWrevHm+7T/XILAgAQEBxdb+WbNm6bPPPtOdd96pOnXqFOo1VapU0a233qr7779ff/75p3V3leLet2+//bbLFPidO3cqKSnJ5a4wdevW1Y4dO1wGUAcPHlRSUpLLuorStujoaAUGBmrevHkuy/fs2aOvvvpKHTt29KQ7AAAUSmHHSdKp4+D333/vUvfVV1/pyJEj+a5j/vz5Lo+TkpK0c+fOfO+4lic2NlbGGP3+++/5jmWaNWsm6dSpgE6nU6+99to5T2Er6nihcePGatOmjWbNmqUFCxYoOztbd99993lfd77tDBs2TH/88YduvfVWHTp0SA888ECh2nMujKvcMa6Ct3G/LyqAcqdr166qXbu2evbsqUaNGik3N1cpKSmaPHmyKlWqpAcffFDSqQPjk08+qccee0y//vqrunXrpqpVq2rfvn1au3atgoOD872D3blUrlxZUVFR+vDDD9WxY0dVq1ZNNWrUcLv1cXF54YUXdNVVV+nqq6/W//3f/6lu3bo6fPiwfv75Z3388cf66quvirzOZs2a6f3339err76qVq1aqUKFCucN6I4ePWpdv+ro0aP69ddf9cEHH+iTTz5RTEyMNX29ID179lTTpk3VunVr1axZUzt37tS0adMUFRWl+vXrW+3K63O/fv3k5+enhg0bqnLlykXuoyTt379fN910kwYNGqTMzEyNHTtWFStW1JgxY6ya+Ph4zZgxQ3fddZcGDRqkgwcPatKkSQoJCXFZV1He9ypVqujxxx/Xo48+qr59++rOO+/UwYMHNX78eFWsWNH6phoAgJJQ2HGSdOo4+Pjjj+uJJ55QTEyMtm7dqunTp8vpdOa77vXr1+uee+7Rbbfdpt27d+uxxx7TRRddpCFDhhTYnvbt2+vee+/V3XffrfXr1+uaa65RcHCw0tLStGrVKjVr1kz/93//p0qVKmny5Mm655571KlTJw0aNEhhYWH6+eef9d1332n69OmSTo8Xnn32WV1//fXy8fFR8+bNrcsg5GfAgAEaPHiw9u7dq3bt2qlhw4bn3Y/n206DBg3UrVs3ffbZZ7rqqqt0+eWXn3edeRhXMa7CBawUL7IOoJgsWrTIxMXFmfr165tKlSoZPz8/U6dOHRMfH2+2bt3qVv/BBx+Ya6+91oSEhJiAgAATFRVlbr31VvPFF19YNf369TPBwcFurx07dqzbnVe++OIL06JFCxMQEGAkWXcoKejue/ndYSUqKsr06NHDbbkkc//997ssS01NNQMGDDAXXXSR8fPzMzVr1jTt2rVzudNN3p1R3nnnHbfXSjKzZs2ylv3555/m1ltvNVWqVDEOh6PAO9ic2Qf9/zv4SDLBwcHm4osvNrfeeqt55513zMmTJ/Pt35l3bpk8ebJp166dqVGjhvH39zd16tQxAwcONL/99pvL68aMGWMiIiJMhQoVXO6CU9D+ym9befti7ty5Ztiw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yul0WjUAAAAAAAAoPmU6lPr111/16quvqn79+vr888913333adiwYfrvf/8rSUpPT5ckhYWFubwuLCzMei49PV3+/v6qWrXqOWtCQ0Pdth8aGmrV5Cc7O1tZWVkuPwAAAAAAADi/Mn36Xm5urlq3bq0JEyZIklq0aKEtW7bo1VdfVd++fa06h8Ph8jpjjNuys51dk1/9+dYzceJEjR8/vlB9AQAAAAAAwGkezZRKTU0t7nbkq1atWmrSpInLssaNG2vXrl2SpPDwcElym820f/9+a/ZUeHi4cnJylJGRcc6affv2uW3/wIEDbrOwzjRmzBhlZmZaP7t37y5iDwEAwIXErjEUAABAeeBRKHXppZfq2muv1bx583Ts2LHibpOlffv22r59u8uyHTt2KCoqSpJUr149hYeHa9myZdbzOTk5Wrlypdq1aydJatWqlfz8/Fxq0tLStHnzZqsmOjpamZmZWrt2rVWzZs0aZWZmWjX5CQgIUEhIiMsPAABAQewaQwEAAJQHHoVS3333nVq0aKGRI0cqPDxcgwcPdgl0isvw4cO1evVqTZgwQT///LMWLFig119/Xffff7+kU6fcJSQkaMKECVq8eLE2b96s/v37KygoSHFxcZIkp9OpgQMHauTIkfryyy+1adMm3XXXXWrWrJl1N77GjRurW7duGjRokFavXq3Vq1dr0KBBio2N5c57AACg2Ng1hpKk33//XXfddZeqV6+uoKAgXXHFFdqwYYP1vDFG48aNU0REhAIDA9WhQwdt2bLFZR3Z2dkaOnSoatSooeDgYPXq1Ut79uxxqcnIyFB8fLycTqecTqfi4+N16NChEukTAADwLh6FUk2bNtWUKVP0+++/a9asWUpPT9dVV12lyy67TFOmTNGBAweKpXFXXnmlFi9erLfffltNmzbVf/7zH02bNk19+vSxakaPHq2EhAQNGTJErVu31u+//66lS5eqcuXKVs3UqVN14403qnfv3mrfvr2CgoL08ccfy8fHx6qZP3++mjVrpi5duqhLly5q3ry55s6dWyz9AAAAkOwbQ2VkZKh9+/by8/PTZ599pq1bt2ry5MmqUqWKVTNp0iRNmTJF06dP17p16xQeHq7OnTvr8OHDVk1CQoIWL16shQsXatWqVTpy5IhiY2N18uRJqyYuLk4pKSlKTExUYmKiUlJSFB8fXyz9AAAA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Tx+98cYbqlq1qrXcGKNp06bpscce080336ymTZtqzpw5+vvvv7VgwQJJUmZmpmbOnKnJkyerU6dOatGihebNm6cffvhBX3zxhSRp27ZtSkxM1Jtvvqno6GhFR0frjTfe0CeffKLt27eXSp8BAAAAAAC8WbkIpe6//3716NFDnTp1clmempqq9PR0denSxVoWEBCgmJgYJSUlSZI2bNig48ePu9RERESoadOmVk1ycrKcTqfatGlj1bRt21ZOp9OqAQAAAAAAQPHxLe0GnM/ChQu1ceNGrVu3zu259PR0SVJYWJjL8rCwMO3cudOq8ff3d5lhlVeT9/r09HSFhoa6rT80NNSqyU92drays7Otx1lZWYXsFQAAAAAAwIWtTM+U2r17tx588EHNmzdPFStWLLDO4XC4PDbGuC0729k1+dWfbz0TJ060LozudDoVGRl5zm0CAAAAAADglDIdSm3YsEH79+9Xq1at5OvrK19fX61cuVIvvviifH19rRlSZ89m2r9/v/VceHi4cnJylJGRcc6affv2uW3/wIEDbrOwzjRmzBhlZmZaP7t37/5H/QUAACgJ3MEYAACURWU6lOrYsaN++OEHpaSkWD+tW7dWnz59lJKSoosvvljh4eFatmyZ9ZqcnBytXLlS7dq1kyS1atVKfn5+LjVpaWnavHmzVRMdHa3MzEytXbvWqlmzZo0yMzOtmvwEBAQoJCTE5QcAAKAs4Q7GAACgrCrT15SqXLmymjZt6rIsODhY1atXt5YnJCRowoQJql+/vurXr68JEyYoKChIcXFxkiSn06mBAwdq5MiRql69uqpVq6ZRo0apWbNm1oXTGzdurG7dumnQoEGaMWOGJOnee+9VbGysGjZsaGOPAQAAis+ZdzB+6qmnrOVn38FYkubMmaOwsDAtWLBAgwcPtu5gPHfuXGvMNG/ePEVGRuqLL75Q165drTsYr1692rphzBtvvKHo6Ght376dcRQAADinMj1TqjBGjx6thIQEDRkyRK1bt9bvv/+upUuXqnLlylbN1KlTdeONN6p3795q3769goKC9PHHH8vHx8eqmT9/vpo1a6YuXbqoS5cuat68uebOnVsaXQIAACgWZfEOxtnZ2crKynL5AQAAF6YyPVMqPytWrHB57HA4NG7cOI0bN67A11SsWFEvvfSSXnrppQJrqlWrpnnz5hVTKwEA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AAC2I5QCAAAAAACA7QilAHidFStWyOFw6NChQ6XdFAAAgBJVmHGPXWOjDh06KCEhodD1/fv314033lhi7QFQ9hFKASgR+/fv1+DBg1WnTh0FBAQoPDxcXbt2VXJycrFuJ7/BT7t27ZSWlian01ms2/JEYQdbdu0vAABQdth1/C/usVFBIdf777+v//znP4VezwsvvKDZs2dbj4saahXkr7/+0sMPP6yLL75YFStWVM2aNdWhQwd98skn/3jdAIqXb2k3AIB3uuWWW3T8+HHNmTNHF198sfbt26cvv/xSf/75Z4lv29/fX+Hh4SW+neJUGvsrJydH/v7+JbZ+AABwbnYd/+0aG1WrVq1I9SX1BeJ9992ntWvXavr06WrSpIkOHjyopKQkHTx4sES2JzGuAjxmAKCYZWRkGElmxYoV56w7dOiQGTRokKlZs6apXLmyufbaa01KSor1/NixY83ll19u/vvf/5qoqCgTEhJibr/9dpOVlWWMMaZfv35GkstPamqqWb58uZFkMjIyjDHGzJo1yzidTvPxxx+bBg0amMDAQHPLLbeYI0eOmNmzZ5uoqChTpUoV88ADD5gTJ05Y28/OzjYPPfSQiYiIMEFBQeZf//qXWb58ufV83noTExNNo0aNTHBwsOnatavZu3ev1f6z23fm64u6vzIyMsygQYNMaGioCQgIMJdddpn5+OOPreffffdd06RJE+Pv72+ioqLM888/7/L6qKgo85///Mf069fPhISEmL59+xpjjPn222/N1VdfbSpWrGhq165thg4dao4cOXLOtgAAgH+mMMf/1NRUI8ls2rTJ7XV5Y4q8cc8nn3ximjdvbgICAsy//vUv8/3331uvOXtsZMz5j//Hjh0zDz30kKldu7bx9/c3l156qXnzzTetNp35069fP2OMMTExMebBBx80xhjzyCOPmDZt2rj1qVmzZuaJJ54wxpway91www3Wv89e76+//mouueQS89xzz7ms44cffjAOh8P8/PPP+e43p9NpZs+eXeB+PVf/8qxYscJceeWVxt/f34SHh5uHH37YHD9+3Ho+JibG3H///Wb48OGmevXq5pprrjHGGLNlyxZz/fXXm+DgYBMaGmruuusuc+DAgXO2BbiQcfoegGJXqVIlVapUSR988IGys7PzrTHGqEePHkpPT9eSJUu0YcMGtWzZUh07dnT5dvCXX37RBx98oE8++USffPKJVq5cqWeeeUbSqSnf0dHRGjRokNLS0pSWlqbIyMh8t/f333/rxRdf1MKFC5WYmKgVK1bo5ptv1pIlS7RkyRLNnTtXr7/+ut59913rNXfffbe+/fZbLVy4UN9//71uu+02devWTT/99JPLep9//nnNnTtXX3/9tXbt2qVRo0ZJkkaNGqXevXurW7duVvvatWvn0f7Kzc3V9ddfr6SkJM2bN09bt27VM888Ix8fH0nShg0b1Lt3b91xxx364YcfNG7cOD3++OMuU+Il6bnnnlPTpk21YcMGPf744/rhhx/UtWtX3Xzzzfr++++1aNEirVq1Sg888EC+7QAAAMWjMMf/onjooYf0/PPPa926dQoNDVWvXr10/PjxfGsLc/zv27evFi5cqBdffFHbtm3Ta6+9pkqVKikyMlLvvfeeJGn79u1KS0vTCy+84LaNPn36aM2aNfrll1+sZVu2bNEPP/ygPn36uNXnN66rU6eOBgwYoFmzZrnUvvXWW7r66qt1ySWX5Nu/8PBwLVmyRIcPHy5wfxXUP0n6/fff1b17d1155ZX67rvv9Oqrr2rmzJl66qmnXNYxZ84c+fr66ttvv9WMGTOUlpammJgYXXHFFVq/fr0SExO1b98+9e7du8B2ABe80k7FAHind99911StWtVUrFjRtGvXzowZM8Z899131vNffvmlCQkJMceOHXN53SWXXGJmzJhhjDk10ygoKMiaGWWMMQ899JDLt25nfiOXJ7+ZUpJcvk0bPHiwCQoKMocPH7aWde3a1QwePNgYY8zPP/9sHA6H+f33313W3bFjRzNmzJgC1/vyyy+bsLAw6/GZ3wD+k/31+eefmwoVKpjt27fn+/q4uDjTuXNnl2UPPfSQadKkifU4KirK3HjjjS418fHx5t5773VZ9s0335gKFSqYo0ePnrfdAADAc+c7/hdlptTChQutmoMHD5rAwECzaNEil5q8sdH5jv/bt283ksyyZcvybXd+M6+McR+XNW/e3Dz55JPW4zFjxpgrr7zSenz2OCm/cd3evXuNj4+PWbNmjTHGmJycHFOzZs1zzoRauXKlqV27tvHz8zOtW7c2CQkJZtWqVdbz5+vfo48+aho2bGhyc3OtZS+//LKpVKmSOXnypNXWK664wuV1jz/+uOnSpYvLst27dxtJBY7hgAsd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\n", + "text/plain": [ + "<Figure size 1200x600 with 2 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(12, 6))\n", + "\n", + "# Plot 1: Sentiment Distribution\n", + "axes[0].hist(text_data['sentiment_score'], bins=20, alpha=0.5)\n", + "axes[0].set_xlabel('Sentiment Score')\n", + "axes[0].set_ylabel('Frequency')\n", + "axes[0].set_title('Sentiment Distribution')\n", + "\n", + "# Plot 2: Subjectivity Distribution\n", + "axes[1].hist(text_data['subjectivity'], bins=20, alpha=0.5)\n", + "axes[1].set_xlabel('Subjectivity Score')\n", + "axes[1].set_ylabel('Frequency')\n", + "axes[1].set_title('Subjectivity Distribution')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6385dcdb", + "metadata": {}, + "outputs": [], + "source": [ + "# takes way too long, wont be scalable in big data\n", + "'''from wordcloud import WordCloud\n", + "\n", + "wordcloud = WordCloud(width = 800, height = 800, \n", + " background_color ='white', \n", + " stopwords = None, \n", + " min_font_size = 10).generate(' '.join(text_data['cleaned_text']))\n", + "\n", + "plt.figure(figsize = (8, 8), facecolor = None) \n", + "plt.imshow(wordcloud) \n", + "plt.axis(\"off\") \n", + "plt.tight_layout(pad = 0) \n", + "plt.show()'''\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2b43468", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "#taking a very long time to run\n", + "\n", + "import geopandas as gpd\n", + "\n", + "gdf = gpd.GeoDataFrame(text_data, geometry=gpd.points_from_xy(text_data.lon_x, text_data.lat_x))\n", + "\n", + "fig, ax = plt.subplots()\n", + "gdf.plot(ax=ax, color='blue')\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "697b8a18", + "metadata": {}, + "outputs": [], + "source": [ + "text_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80f4bd71", + "metadata": {}, + "outputs": [], + "source": [ + "!pip3 install geoplot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6814b63c", + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "import geopandas as gpd\n", + "import geoplot as gplt\n", + "import geoplot.crs as gcrs\n", + "import pandas as pd\n", + "from shapely import wkt\n", + "\n", + "def load_wkt(value):\n", + " if isinstance(value, str):\n", + " return wkt.loads(value)\n", + " return None\n", + "\n", + "text_data['geometry_y'] = text_data['geometry_y'].apply(load_wkt) # convert POLYGON string to geometry\n", + "gdf = gpd.GeoDataFrame(text_data, geometry='geometry_y') # convert DataFrame to GeoDataFrame\n", + "\n", + "# Group by 'scc_name_x' and calculate mean sentiment\n", + "gdf['new_sentiment'] = pd.to_numeric(gdf['new_sentiment'], errors='coerce')\n", + "grouped_gdf = gdf.groupby('scc_name_x').agg({'new_sentiment': 'mean'})\n", + "\n", + "# Join the original gdf with grouped_gdf to get the mean sentiment for each row\n", + "gdf = gdf.merge(grouped_gdf, on='scc_name_x')\n", + "\n", + "# Create a KDE plot and overlay it on a polygon plot\n", + "ax = gplt.kdeplot(\n", + " gdf,\n", + " clip=gdf.geometry,\n", + " shade=True,\n", + " cmap='Reds',\n", + " projection=gcrs.AlbersEqualArea(),\n", + ")\n", + "gplt.polyplot(gdf, ax=ax, zorder=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac8ec1f6", + "metadata": {}, + "outputs": [], + "source": [ + "text_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "586cf916", + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "import geopandas as gpd\n", + "import geoplot as gplt\n", + "import geoplot.crs as gcrs\n", + "from shapely.geometry import Point\n", + "\n", + "# Convert lat/lon to a shapely Point object\n", + "text_data['geometry'] = text_data.apply(lambda row: Point(row.lon, row.lat), axis=1)\n", + "\n", + "# Convert DataFrame to GeoDataFrame\n", + "gdf = gpd.GeoDataFrame(text_data, geometry='geometry')\n", + "\n", + "# Group by 'lga_name' and calculate mean sentiment_score\n", + "gdf['sentiment_score'] = pd.to_numeric(gdf['sentiment_score'], errors='coerce')\n", + "grouped_gdf = gdf.groupby('lga_name').agg({'sentiment_score': 'mean'})\n", + "\n", + "# Join the original gdf with grouped_gdf to get the mean sentiment for each row\n", + "gdf = gdf.merge(grouped_gdf, on='lga_name', suffixes=('', '_mean'))\n", + "\n", + "# Create a KDE plot and overlay it on a polygon plot\n", + "ax = gplt.kdeplot(\n", + " gdf,\n", + " hue='sentiment_score_mean',\n", + " clip=gdf.geometry,\n", + " shade=True,\n", + " cmap='coolwarm',\n", + " projection=gcrs.AlbersEqualArea(),\n", + ")\n", + "gplt.polyplot(gdf, ax=ax, zorder=1)\n" + ] + } + ], + "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.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}