Skip to content

Commit 2b7d1b7

Browse files
committed
new article
1 parent 2b5a11a commit 2b7d1b7

2 files changed

Lines changed: 170 additions & 0 deletions

File tree

1.22 KB
Loading
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<!-- wp:paragraph -->
2+
<p>In this post, I am going to download and analyze the tweets regarding Bitcoin tweets from the last two weeks and perform sentiment analysis to gather market intelligence. What are people's opinions about Bitcoin tweets?</p>
3+
<!-- /wp:paragraph -->
4+
5+
<!-- wp:heading {"textColor":"secondary"} -->
6+
<h2 class="has-secondary-color has-text-color" id="what-is-sentiment-analysis">What is Sentiment Analysis?</h2>
7+
<!-- /wp:heading -->
8+
9+
<!-- wp:paragraph -->
10+
<p>To do this, I will need to use Natural Language Processing as a way to gain insights into my data. One of the most common forms of analysis we can exploit using NLP is called sentiment analysis, and it consists of converting a text into a score that estimates its sentiment. There are several models we can use to perform sentiment analysis, but they all fulfill the same purpose.</p>
11+
<!-- /wp:paragraph -->
12+
13+
<!-- wp:paragraph -->
14+
<p>The most common use case of sentiment analysis is to estimate the demand of the market for a certain product, hopefully entering into a trend just when it begins. In Finance, this is one of the most searched ML applications.</p>
15+
<!-- /wp:paragraph -->
16+
17+
<!-- wp:paragraph -->
18+
<p>The project will be following these steps:</p>
19+
<!-- /wp:paragraph -->
20+
21+
<!-- wp:list {"ordered":true} -->
22+
<ol><li>Download data from Twitter</li><li>Preprocess the data</li><li>Perform sentiment analysis</li><li>Analyze results</li></ol>
23+
<!-- /wp:list -->
24+
25+
<!-- wp:heading {"textColor":"secondary"} -->
26+
<h2 class="has-secondary-color has-text-color" id="1-download-data-from-twitter">1. Download data from Twitter</h2>
27+
<!-- /wp:heading -->
28+
29+
<!-- wp:paragraph -->
30+
<p>To download data from Twitter without using its metered API, hence without any limit on the volume of data I wish to scrape, I can use different libraries. One of the most common is called <strong>twint</strong>, however, after the latest Twitter updates, has not been working very well. </p>
31+
<!-- /wp:paragraph -->
32+
33+
<!-- wp:paragraph -->
34+
<p>As a valid and also simpler alternative, I will be using <strong>snscrape</strong>. </p>
35+
<!-- /wp:paragraph -->
36+
37+
<!-- wp:code {"backgroundColor":"primary"} -->
38+
<pre class="wp-block-code has-primary-background-color has-background"><code>!pip install snscrape</code></pre>
39+
<!-- /wp:code -->
40+
41+
<!-- wp:paragraph -->
42+
<p>After installing the library with pip, I will need to declare which are the search parameters. Because I may need to use it on more queries, for example, I could search for the sentiment on the top 10 Billionaires, I want to be able to have a control panel that gives instruction to the program. </p>
43+
<!-- /wp:paragraph -->
44+
45+
<!-- wp:paragraph -->
46+
<p>As such, I will use movie_dict as a variable to store all the instructions to perform multiple searches. For each search, a csv will be created with all the data I have been able to scrape from Twitter:</p>
47+
<!-- /wp:paragraph -->
48+
49+
<!-- wp:code {"backgroundColor":"primary"} -->
50+
<pre class="wp-block-code has-primary-background-color has-background"><code>import snscrape.modules.twitter as sntwitter
51+
import pandas as pd
52+
import progressbar
53+
from time import sleep
54+
from datetime import datetime
55+
import os
56+
57+
{'bitcoin': ['bitcoin since:2022-01-01 until:2022-01-17', 1000]}
58+
</code></pre>
59+
<!-- /wp:code -->
60+
61+
<!-- wp:paragraph -->
62+
<p>The following is the code that executes the scrape:</p>
63+
<!-- /wp:paragraph -->
64+
65+
<!-- wp:code {"backgroundColor":"primary"} -->
66+
<pre class="wp-block-code has-primary-background-color has-background"><code>today = datetime.today().strftime('%Y%m%d')&#91;2:]+'_'
67+
for index, movie_name in enumerate(movie_dict):
68+
print(movie_name, '%')
69+
tweets_list1 = &#91;]
70+
bar = progressbar.ProgressBar(maxval=movie_dict&#91;movie_name]&#91;1]+2, widgets=&#91;progressbar.Bar('=', '&#91;', ']'), ' ', progressbar.Percentage()])
71+
bar.start()
72+
for i,tweet in enumerate(sntwitter.TwitterSearchScraper(f'{movie_dict&#91;movie_name]&#91;0]}').get_items()): #declare a username
73+
bar.update(i+1)
74+
if i&gt;movie_dict&#91;movie_name]&#91;1]: #number of tweets you want to scrape
75+
break
76+
#print(movie_name, i, tweet)
77+
tweets_list1.append(&#91;tweet.date, tweet.id, tweet.content, tweet.user.username]) #declare the attributes to be returned
78+
tweets_df1 = pd.DataFrame(tweets_list1, columns=&#91;'Datetime', 'Tweet Id', 'Text', 'Username'])
79+
80+
tweets_df1&#91;&#91;'Datetime', 'Text']].to_csv(f'{index}.csv')
81+
bar.finish()</code></pre>
82+
<!-- /wp:code -->
83+
84+
<!-- wp:paragraph -->
85+
<p>This code is an improved version of the <a href="https://medium.com/dataseries/how-to-scrape-millions-of-tweets-using-snscrape-195ee3594721">standard code used to run a query</a> to filter the tweets you wish to download from Twitter. You can use it to download not only one query, but a list of query</p>
86+
<!-- /wp:paragraph -->
87+
88+
<!-- wp:heading {"textColor":"secondary"} -->
89+
<h2 class="has-secondary-color has-text-color" id="2-preprocess-the-data">2. Preprocess the data</h2>
90+
<!-- /wp:heading -->
91+
92+
<!-- wp:paragraph -->
93+
<p>Now that a csv file has been created for every query in my control panel, let us look at the raw data of a single query:</p>
94+
<!-- /wp:paragraph -->
95+
96+
<!-- wp:code {"backgroundColor":"primary"} -->
97+
<pre class="wp-block-code has-primary-background-color has-background"><code>import pandas as pd
98+
99+
#when importing empty rows, they are transformed to nan, so we need to drop them here
100+
df = pd.read_csv('download/merged.csv')&#91;&#91;'text']]
101+
df</code></pre>
102+
<!-- /wp:code -->
103+
104+
<!-- wp:paragraph -->
105+
<p>Because some of the rows may be null when importing the dataset, I am dropping them and resetting the index. I am also going to apply a small preprocessing snippet. Preprocessing is a step that you can customize depending on your needs. In this case, because I only want to get rid of links and non-ascii characters, I am going to use the following two functions:</p>
106+
<!-- /wp:paragraph -->
107+
108+
<!-- wp:code {"backgroundColor":"primary"} -->
109+
<pre class="wp-block-code has-primary-background-color has-background"><code>#get rid of links and hashtags
110+
df&#91;"text"] = df&#91;"text"].apply(lambda x : ' '.join(&#91;s for s in x.split(' ') if s.find('@') == -1 and s.find('www') == -1 and s.find('https') == -1]))
111+
112+
#get rid of non-ascii characters
113+
df = df.replace(r'\W+', ' ', regex=True)
114+
df</code></pre>
115+
<!-- /wp:code -->
116+
117+
<!-- wp:paragraph -->
118+
<p>This is a screenshot of the dataframe after preprocessing:</p>
119+
<!-- /wp:paragraph -->
120+
121+
<!-- wp:image {"align":"center","width":480,"height":616,"sizeSlug":"large","className":"is-style-default"} -->
122+
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large is-resized"><img src="https://raw.githubusercontent.com/arditoibryan/pythonkai/main/_content/articles/220118_bitcoin_tweet/df.png" alt="" width="390" height="616"/><figcaption>df raw</figcaption></figure></div>
123+
<!-- /wp:image -->
124+
125+
<!-- wp:heading {"textColor":"secondary"} -->
126+
<h2 class="has-secondary-color has-text-color" id="3-perform-sentiment-analysis">3. Perform sentiment analysis</h2>
127+
<!-- /wp:heading -->
128+
129+
<!-- wp:paragraph -->
130+
<p>I am now going to apply a sentiment analysis to our cleaned data. There is a myriad of sentiment analysis libraries you can use to perform the same task, from <strong>transformers</strong>, <strong>textblob</strong>, <strong>spacy</strong>. For this tutorial I am going to use the latest version of spacy, and its extension called <a href="https://spacy.io/universe/project/spacy-textblob" target="_blank" rel="noreferrer noopener">spacytextblob</a>.</p>
131+
<!-- /wp:paragraph -->
132+
133+
<!-- wp:paragraph -->
134+
<p>To install it, I will need to run the following commands and restart the notebook:</p>
135+
<!-- /wp:paragraph -->
136+
137+
<!-- wp:code {"backgroundColor":"primary"} -->
138+
<pre class="wp-block-code has-primary-background-color has-background"><code>!pip install spacytexblob==3.0.1
139+
!pip install spacy==3.2.1
140+
!python -m textblob.download_corpora
141+
!python -m spacy download en_core_web_sm</code></pre>
142+
<!-- /wp:code -->
143+
144+
<!-- wp:paragraph -->
145+
<p>Once the installation is complete, we can run the sentiment analysis and append the score to our dataframe:</p>
146+
<!-- /wp:paragraph -->
147+
148+
<!-- wp:code {"backgroundColor":"primary"} -->
149+
<pre class="wp-block-code has-primary-background-color has-background"><code>import spacy
150+
from spacytextblob.spacytextblob import SpacyTextBlob
151+
152+
nlp = spacy.load('en_core_web_sm')
153+
nlp.add_pipe("spacytextblob")
154+
155+
df&#91;'sentiment'] = df&#91;'text'].apply(lambda x : nlp(x)._.polarity)
156+
df_sentiment = df.sort_values('sentiment').reset_index(drop=True)
157+
df_sentiment</code></pre>
158+
<!-- /wp:code -->
159+
160+
<!-- wp:paragraph -->
161+
<p>As we can see, this is the final result:</p>
162+
<!-- /wp:paragraph -->
163+
164+
<!-- wp:image {"align":"center","width":480,"height":616,"sizeSlug":"large","className":"is-style-default"} -->
165+
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large is-resized"><img src="https://raw.githubusercontent.com/arditoibryan/pythonkai/main/_content/articles/220118_bitcoin_tweet/df_sentiment.png" alt="" width="480" height="616"/><figcaption>sentiment</figcaption></figure></div>
166+
<!-- /wp:image -->
167+
168+
<!-- wp:paragraph -->
169+
<p>I decided to sort the values from the most negative, so that we could see some of the most shocking comments regarding Bitcoin tweets.</p>
170+
<!-- /wp:paragraph -->

0 commit comments

Comments
 (0)