A demó telepítése Linux rendszereken a következő lépésekből áll:
import nltk
nltk.download()
és letölteni a punkt, illetve a stopwords korpuszokat.
Az adat itt érhető el regisztráció után: https://www.kaggle.com/semioniy/predictemall/downloads/predictemall.zip
Elvileg Windows és OSX rendszereken is ugyanígy telepíthető minden, de ezeket nem teszteltem.
In [1]:
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import nltk
from wordcloud import WordCloud, STOPWORDS
# tegyük szebbé a grafikonokat
matplotlib.style.use('ggplot')
matplotlib.pyplot.rcParams['figure.figsize'] = (25, 13)
matplotlib.pyplot.rcParams['font.family'] = 'sans-serif'
matplotlib.pyplot.rcParams['font.size'] = 20
In [2]:
df = pd.read_csv('tweets.csv', parse_dates=['time'])
In [3]:
kept_columns = ['text', 'is_retweet', 'original_author', 'time', 'retweet_count', 'favorite_count', 'handle']
df = df[kept_columns]
df.head(2)
Out[3]:
In [4]:
df['author'] = "Trump"
df.loc[df['handle'].str.contains("Hill"), "author"] = "Clinton"
In [5]:
df.groupby(by=[df.time.dt.year, df.time.dt.month]).count()
Out[5]:
In [6]:
df.groupby(by=[df.time.dt.year, df.time.dt.month]).count().plot(y='author', kind='bar')
Out[6]:
In [7]:
df.groupby(by=[df.author, df.time.dt.year, df.time.dt.month]).count().unstack('author')['handle'].plot(kind='bar', y=['Clinton', 'Trump'])
Out[7]:
In [8]:
df.groupby(by=[df.author, df.time.dt.hour]).count().unstack('author')['handle'].plot(kind='bar', y=['Clinton', 'Trump'])
Out[8]:
In [ ]:
In [ ]:
In [ ]:
In [9]:
df.plot(x='time', y='retweet_count')
Out[9]:
In [10]:
threshold = df.retweet_count.quantile(0.95)
df[df.retweet_count < threshold].plot(x='time', y='retweet_count')
Out[10]:
Sokkal egyenletesebb eloszlást kaptunk, úgy tűnik, hogy a retweetek eloszlása lecsengő, tehát sok kisebb érték van és néhány nagyon nagy. Ábrázoljuk hisztogramon.
In [11]:
df.retweet_count.hist()
Out[11]:
In [12]:
df.sort_values('retweet_count').tail()
Out[12]:
In [13]:
df.plot(x='time', y=['author', 'favorite_count'])
Out[13]:
Első ránézésre nem igazán tér el a retweet_count-tól. Mentsük a kettő különbségét egy új oszlopba:
In [14]:
df['r_minus_f'] = df.retweet_count - df.favorite_count
In [15]:
df.r_minus_f.describe()
Out[15]:
In [16]:
df.plot(x='time', y='r_minus_f')
Out[16]:
Ahol a legnagyobb a különbség:
In [17]:
df.sort_values(by='r_minus_f').head()
Out[17]:
In [ ]:
In [ ]:
In [ ]:
In [18]:
def filter_and_tokenize(text):
from string import punctuation
stopwords = nltk.corpus.stopwords.words('english')
blacklist = {
"...", "—", "'s", "''", "—hillary", "hillaryclinton",
"http", "https", "amp",
"trump", "trump2016", "donald", "clinton", "hillary",
"realdonaldtrump", "let", "go"
}
out_tokens = []
for token in nltk.tokenize.word_tokenize(text):
token = token.lower()
if token not in punctuation and token not in stopwords and token not in blacklist:
out_tokens.append(token)
return out_tokens
def draw_wordcloud(text):
tokens = filter_and_tokenize(text)
text = " ".join(tokens)
wordcloud_hc = WordCloud(max_font_size=40, stopwords=STOPWORDS, background_color='white').generate(text)
plt.figure()
plt.imshow(wordcloud_hc)
plt.axis("off")
plt.show()
In [19]:
%%time
df['char_count'] = df.text.str.len()
df['tokens'] = df.text.apply(filter_and_tokenize)
df['types'] = df.tokens.apply(set)
df['type_count'] = df.types.apply(len)
df['token_count'] = df.tokens.apply(len)
df['ttr'] = df.type_count / df.token_count
A két jelöltre összegezve:
In [20]:
df[['token_count', 'char_count', 'type_count', 'author']].groupby('author').sum()
Out[20]:
A két jelöltre átlagolva (amit van értelme átlagolni):
In [21]:
df[['token_count', 'char_count', 'type_count', 'ttr', 'author']].groupby('author').mean()
Out[21]:
In [22]:
df[['token_count', 'author']].hist(by='author', sharex=True)
Out[22]:
Az átlag ugyan majdnem ugyanaz a két jelölt közt, de Trumpnál jóval nagyobb arányban fordulnak elő a 10 szónál hosszabb tweetek.
In [23]:
clinton_tokens = filter_and_tokenize(df[df.author=="Clinton"].text.str.cat())
trump_tokens = filter_and_tokenize(df[df.author=="Trump"].text.str.cat())
A két jelölt "szókincse":
In [24]:
len(set(clinton_tokens)), len(set(trump_tokens))
Out[24]:
In [25]:
from collections import Counter
clinton_counter = Counter(clinton_tokens)
trump_counter = Counter(trump_tokens)
diff = {k: clinton_counter.get(k, 0)-trump_counter.get(k, 0) for k in set(clinton_counter.keys()) | set(trump_counter.keys())}
In [26]:
s = sorted(diff.items(), key=lambda x: abs(x[1]), reverse=True)
In [27]:
topn = 30
for word, freqdiff in s[:topn]:
print("{0} --\t {1} --\t Clinton:{2} vs. Trump:{3}".format(word, "Clinton" if freqdiff > 0 else "Trump",
clinton_counter.get(word, 0), trump_counter.get(word, 0)))
In [28]:
top200 = set(w[0] for w in s[:200])
df['frequent'] = df.tokens.apply(lambda x: len(list(filter(lambda y: y in top200, x))) / len(x))
df.groupby(by=[df.time.dt.year, df.time.dt.week]).mean().plot(y='frequent')
Out[28]:
In [29]:
top200 = set(w[0] for w in s[:200])
df['frequent'] = df.tokens.apply(lambda x: len(list(filter(lambda y: y in top200, x))) / len(x))
df[df.author=="Trump"].groupby(by=[df.time.dt.year, df.time.dt.week]).mean().plot(y='frequent')
Out[29]:
In [30]:
top200 = set(w[0] for w in s[:200])
df['frequent'] = df.tokens.apply(lambda x: len(list(filter(lambda y: y in top200, x))) / len(x))
df[df.author=="Clinton"].groupby(by=[df.time.dt.year, df.time.dt.week]).mean().plot(y='frequent')
Out[30]:
In [31]:
t = df[df.author=="Clinton"]['text'].str.cat().lower()
draw_wordcloud(t)
In [32]:
t = df[df.author=="Trump"]['text'].str.cat().lower()
draw_wordcloud(t)
In [33]:
d = df[df.author=="Clinton"]
th = d.favorite_count.quantile(.95)
draw_wordcloud(d[d.favorite_count>th].text.str.cat())
In [34]:
d = df[df.author=="Trump"]
th = d.favorite_count.quantile(.95)
draw_wordcloud(d[d.favorite_count>th].text.str.cat())