Рубрики
Без рубрики

Анализ настроений в твитах Трампа с использованием Python 🐍

Анализ настроений в твитах Трампа с использованием учебника по Python.

Автор оригинала: Rodolfo Ferro.

ОПИСАНИЕ: В этой статье мы будем:

  1. Извлеките данные Twitter с помощью tweepy и узнайте, как обращаться с ними с помощью панд.
  2. Сделайте некоторые базовые статистические данные и визуализации с помощью numpy, matplotlib и seaborn.
  3. Сделайте анализ настроений извлеченных твитов (Трампа) с помощью textblob.

Фу! Давненько я не писал ничего хорошего. Я надеюсь, что вы найдете это немного полезным и/или интересным. Это основано на семинаре, который я преподавал в Мехико . Я объясню весь пост вместе с кодом самым простым из возможных способов. Во всяком случае, оригинальный пост в блоге можно найти в моем блоге , а весь код можно найти в репо, которое я использовал для этого семинара .

Прежде всего, нам нужно установить Python . Я почти уверен, что весь код будет работать на Python 2.7, но я буду использовать Python 3.6. Я настоятельно рекомендую установить Anaconda , который является очень полезным дистрибутивом Python для управления пакетами, который включает в себя множество полезных инструментов, таких как Записные книжки Jupyter . Я объясню код, предполагая, что мы будем использовать записную книжку Jupyter, но код будет выполняться, если вы программируете простой скрипт из своего текстового редактора. Вам просто нужно будет адаптировать его (это не сложно).

Требования, которые нам нужно будет установить, следующие:

  • NumPy : Это фундаментальный пакет для научных вычислений с использованием Python. Помимо очевидного научного использования, NumPy также может использоваться в качестве эффективного многомерного контейнера общих данных.
  • Pandas : Это библиотека с открытым исходным кодом, предоставляющая высокопроизводительные, простые в использовании структуры данных и инструменты анализа данных.
  • Tweepy : Это простая в использовании библиотека Python для доступа к API Twitter.
  • Matplotlib : Это библиотека 2D-графики Python, которая создает показатели качества публикации в различных форматах печатной печати и интерактивных средах на разных платформах.
  • Seaborn : Это библиотека визуализации Python, основанная на matplotlib. Он обеспечивает высокоуровневый интерфейс для рисования привлекательной статистической графики.
  • Text blob : Это библиотека Python для обработки текстовых данных. Он предоставляет простой API для погружения в общие задачи обработки естественного языка (NLP).

Все они являются ” pip устанавливаемыми “. В конце этой статьи вы сможете найти больше ссылок на эти библиотеки Python.

Теперь, когда у нас есть все требования, давайте начнем!

1.1. Импорт наших библиотек

Это будет самая трудная часть всего поста… – Просто шучу, очевидно, что нет. Это будет так же просто, как скопировать и вставить следующий код в свой блокнот:

# General:
import tweepy           # To consume Twitter's API
import pandas as pd     # To handle data
import numpy as np      # For number computing

# For plotting and visualization:
from IPython.display import display
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

Отлично! Теперь мы можем просто запустить эту ячейку кода и перейти к следующему подразделу.

1.2. Создание приложения Twitter

Чтобы извлечь твиты для последующего анализа, нам нужно получить доступ к нашей учетной записи Twitter и создать приложение. Веб-сайт для этого https://apps.twitter.com/ . (Если вы не знаете, как это сделать, вы можете следовать этому учебному видео , чтобы создать учетную запись и приложение.)

Из этого приложения, которое мы создаем, мы сохраним следующую информацию в скрипте под названием credentials.py :

  • Ключ потребителя (ключ API)
  • Секрет потребителя (Секрет API)
  • Токен доступа
  • Секрет маркера доступа

Примером этого сценария является следующее:

# Twitter App access keys for @user

# Consume:
CONSUMER_KEY    = ''
CONSUMER_SECRET = ''

# Access:
ACCESS_TOKEN  = ''
ACCESS_SECRET = ''

Причина создания этого дополнительного файла заключается в том, что мы хотим экспортировать только значения этих переменных, но невидимые в нашем основном коде (нашей записной книжке). Теперь мы можем использовать API Twitter. Для этого мы создадим функцию, позволяющую нам аутентифицировать наши ключи. Мы добавим эту функцию в другую ячейку кода и запустим ее:

# We import our access keys:
from credentials import *    # This will allow us to use the keys as variables

# API's setup:
def twitter_setup():
    """
    Utility function to setup the Twitter's API
    with our access keys provided.
    """
    # Authentication and access using keys:
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

    # Return API with authentication:
    api = tweepy.API(auth)
    return api

До сих пор все было так просто, верно? Мы готовы извлечь твиты в следующем разделе.

1.3. Извлечение твитов

Теперь, когда мы создали функцию для настройки API Twitter, мы можем использовать эту функцию для создания объекта ” extractor “. После этого мы будем использовать функцию Tweepy extractor.user_timeline(screen_name, count) для извлечения из screen_name пользователя количества count твитов.

Как указано в названии, я выбрал @realDonaldTrump в качестве пользователя для извлечения данных для последующего анализа. Да, мы хотим, чтобы это было интересно, ЛОЛ.

Способ извлечения данных Twitter заключается в следующем:

# We create an extractor object:
extractor = twitter_setup()

# We create a tweet list as follows:
tweets = extractor.user_timeline(screen_name="realDonaldTrump", count=200)
print("Number of tweets extracted: {}.\n".format(len(tweets)))

# We print the most recent 5 tweets:
print("5 recent tweets:\n")
for tweet in tweets[:5]:
    print(tweet.text)
    print()

При этом у нас будет результат, аналогичный этому, и мы сможем сравнить результат с учетной записью Twitter (чтобы проверить, насколько мы последовательны): Количество извлеченных твитов: 200. 5 последних твитов: От имени @FLOTUS Melania и меня, СПАСИБО за сегодняшнее обновление и ОТЛИЧНУЮ РАБОТУ! #SouthernBaptist @SendRelief,... https://t.co/4yZCeXCt6n Завтра я поеду в Техас и Луизиану с Первой леди. Большой прогресс достигнут! Проводил выходные, работая в Белом доме. Фондовый рынок растет 5 месяцев подряд! 'Президент Дональд Дж. Трамп объявляет 3 сентября 2017 года Национальным днем молитвы " #HurricaneHarvey #PrayForTexas… https://t.co/tOMfFWwEsN Техас быстро выздоравливает благодаря всем великим мужчинам и женщинам, которые так усердно работали. Но еще так много нужно сделать. Вернусь завтра!

Теперь у нас есть экстрактор и извлеченные данные, которые перечислены в переменной tweets . Здесь я должен упомянуть, что каждый элемент в этом списке является объектом tweet от Tweepy, и мы узнаем, как обрабатывать эти данные в следующем подразделе.

1.4. Создание фрейма данных (pandas)

Теперь у нас есть исходная информация для создания фрейма данных pandas , чтобы очень легко манипулировать информацией.

Функция display IPython строит вывод удобным способом, а метод head фрейма данных позволяет нам визуализировать первые 5 элементов фрейма данных (или первое число элементов, которые передаются в качестве аргумента).

Итак, используя понимание списка Python:

# We create a pandas dataframe as follows:
data = pd.DataFrame(data=[tweet.text for tweet in tweets], columns=['Tweets'])

# We display the first 10 elements of the dataframe:
display(data.head(10))

Это создаст результат, подобный этому:

От имени @FLOTUS Melania и меня, ТХА… 0
Завтра я поеду в Техас и Луизиану… 1
Фондовый рынок растет 5 месяцев подряд! 2
“Президент Дональд Трамп Объявляет Сентябрь… 3
Техас быстро выздоравливает благодаря всем gre… 4
…делайте все в рекордно короткие сроки. Много больших … 5
Генерал Джон Келли отлично справляется с ролью чи… 6
Вау, похоже, Джеймс Коми оправдал Хиллари… 7
СПАСИБО всем невероятным ГЕРОЯМ в Т… 8
RT @FoxNews: .@KellyannePolls на Harvey recove… 9

Итак, теперь у нас есть хорошая таблица с упорядоченными данными.

Интересная вещь-это количество внутренних методов, которые структура tweet имеет в Tweepy:

# Internal methods of a single tweet object:
print(dir(tweets[0]))

Это выводит следующий список элементов: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__','_____________________________________________________________________________________________________________________, "_api", "_json", "автор", "участники", "координаты", "created_at", "уничтожить", "сущности", "избранное", "favorite_count", "избранное", "гео", "id", "id_str", "in_reply_to_screen_name", "in_reply_to_status_id", "in_reply_to_status_id_str", "in_reply_to_user_id", "in_reply_to_user_id_str", "is_quote_status", "lang", "parse", "parse_list", "place", "possibly_sensitive", "retweet", "retweet_count", "retweeted", "retweets", "источник", "source_url", "текст", "усеченный", "пользователь"]

Самое интересное здесь-количество метаданных, содержащихся в одном твите. Если мы хотим получить такие данные, как дата создания или источник создания, мы можем получить доступ к информации с помощью этих атрибутов. Примером может служить следующее:

# We print info from the first tweet:
print(tweets[0].id)
print(tweets[0].created_at)
print(tweets[0].source)
print(tweets[0].favorite_count)
print(tweets[0].retweet_count)
print(tweets[0].geo)
print(tweets[0].coordinates)
print(tweets[0].entities)

Получение вывода, подобного этому: 903778130850131970 2017-09-02 00:34:32 Twitter для iPhone 24572 5585 Нет Нет {'хэштеги': [{'текст': 'SouthernBaptist', 'индексы': [90, 106]}], 'символы': [], 'user_mentions': [{'screen_name': 'FLOTUS', 'name': 'Melania Trump', 'id': 818876014390603776, 'id_str': '818876014390603776', 'индексы': [13, 20]}, {'screen_name': 'sendrelief', 'name': 'Send Relief', 'id': 3228928584, 'id_str': '3228928584', 'индексы': [107, 118]}], 'urls': [{'url': 'https://t.co/4yZCeXCt6n', 'expanded_url': 'https://twitter.com/i/web/status/903778130850131970', 'display_url': 'twitter.com/i/web/status/9...", "индексы": [121, 144]}]}

Теперь мы можем заказать соответствующие данные и добавить их в наш фрейм данных.

1.5. Добавление релевантной информации в наш фрейм данных

Как мы видим, мы можем получить много данных из одного твита. Но не все эти данные всегда полезны для конкретных вещей. В нашем случае мы просто добавим некоторые данные в наш фрейм данных. Для этого мы будем использовать понимание списка Pythons, и новый столбец будет добавлен в фрейм данных, просто добавив имя содержимого в квадратные скобки и назначив содержимое. Код выглядит следующим образом…:

# We add relevant data:
data['len']  = np.array([len(tweet.text) for tweet in tweets])
data['ID']   = np.array([tweet.id for tweet in tweets])
data['Date'] = np.array([tweet.created_at for tweet in tweets])
data['Source'] = np.array([tweet.source for tweet in tweets])
data['Likes']  = np.array([tweet.favorite_count for tweet in tweets])
data['RTs']    = np.array([tweet.retweet_count for tweet in tweets])

И чтобы снова отобразить фрейм данных, чтобы увидеть изменения, мы просто…:

# Display of first 10 elements from dataframe:
display(data.head(10))
903778130850131970 5585 144 2017-09-02 00:34:32 24572 Twitter для iPhone От имени @FLOTUS Melania и меня, ТХА… 0
903770196388831233 8825 132 2017-09-02 00:03:00 44748 Twitter для iPhone Завтра я поеду в Техас и Луизиану… 1
903766326631698432 9134 34 2017-09-01 23:47:38 44518 Twitter для iPhone Фондовый рынок растет 5 месяцев подряд! 2
903705867891204096 15127 140 2017-09-01 19:47:23 47009 Медиа-студия “Президент Дональд Трамп Объявляет Сентябрь… 3
903603043714957312 15398 143 2017-09-01 12:58:48 77680 Twitter для iPhone Техас быстро выздоравливает благодаря всем gre… 4
903600265420578819 11424 113 2017-09-01 12:47:46 54664 Twitter для iPhone …делайте все в рекордно короткие сроки. Много больших … 5
903597166249246720 11678 140 2017-09-01 12:35:27 59840 Twitter для iPhone Генерал Джон Келли отлично справляется с ролью чи… 6
903587428488839170 35936 130 2017-09-01 11:56:45 110667 Twitter для iPhone Вау, похоже, Джеймс Коми оправдал Хиллари… 7
903348312421670912 29064 110 2017-08-31 20:06:35 112012 Twitter для iPhone СПАСИБО всем невероятным ГЕРОЯМ в Т… 8
903234878124249090 6638 140 2017-08-31 12:35:50 0 Twitter для iPhone RT @FoxNews: .@KellyannePolls на Harvey recove… 9

Теперь, когда мы извлекли и упорядочили данные в удобном для обработки порядке, мы готовы сделать еще немного манипуляций, чтобы визуализировать некоторые графики и собрать некоторые статистические данные. Первая часть поста закончена.

2.1. Средние показатели и популярность

Сначала мы хотим рассчитать некоторые основные статистические данные, такие как среднее значение длины символов всех твитов, твит с большим количеством лайков и ретвитов и т. Д.

С этого момента я просто добавлю некоторый входной код и вывод прямо под кодом.

Чтобы получить среднее значение, используя numpy:

# We extract the mean of lenghts:
mean = np.mean(data['len'])

print("The lenght's average in tweets: {}".format(mean))

Средняя длина в твитах: 125,925

Чтобы извлечь больше данных, мы будем использовать некоторые функции панд:

# We extract the tweet with more FAVs and more RTs:

fav_max = np.max(data['Likes'])
rt_max  = np.max(data['RTs'])

fav = data[data.Likes == fav_max].index[0]
rt  = data[data.RTs == rt_max].index[0]

# Max FAVs:
print("The tweet with more likes is: \n{}".format(data['Tweets'][fav]))
print("Number of likes: {}".format(fav_max))
print("{} characters.\n".format(data['len'][fav]))

# Max RTs:
print("The tweet with more retweets is: \n{}".format(data['Tweets'][rt]))
print("Number of retweets: {}".format(rt_max))
print("{} characters.\n".format(data['len'][rt]))

Твит с большим количеством лайков: Соединенные Штаты осуждают теракт в Барселоне, Испания, и сделают все необходимое, чтобы помочь. Будьте жесткими и сильными, мы любим вас! Количество лайков: 222205 144 символа.

Твит с большим количеством ретвитов: Соединенные Штаты осуждают теракт в Барселоне, Испания, и сделают все необходимое, чтобы помочь. Будьте жесткими и сильными, мы любим вас! Количество ретвитов: 66099 144 символа.

Это обычное дело, но это не обязательно произойдет: твит с большим количеством лайков-это твит с большим количеством ретвитов. То, что мы делаем, заключается в том, что мы находим максимальное количество лайков из столбца ‘Likes’ и максимальное количество ретвитов из ‘RTs’ , используя функцию numpy max . При этом мы просто ищем индекс в каждом из обоих столбцов, который удовлетворяет максимуму. Поскольку более одного может иметь одинаковое количество лайков/ретвитов (максимум), нам просто нужно взять первый найденный, и именно поэтому мы используем .index[0] для присвоения индекса переменным fav и rt . Чтобы напечатать твит, который удовлетворяет, мы обращаемся к данным так же, как к матрице или любому индексированному объекту.

Теперь мы готовы кое-что спланировать.

2.2. Временные ряды

У Панд есть свой собственный объект для временных рядов. Поскольку у нас есть целый вектор с датами создания, мы можем построить временные ряды с учетом длины твитов, лайков и ретвитов.

То, как мы это делаем,:

# We create time series for data:

tlen = pd.Series(data=data['len'].values, index=data['Date'])
tfav = pd.Series(data=data['Likes'].values, index=data['Date'])
tret = pd.Series(data=data['RTs'].values, index=data['Date'])

И если мы хотим построить временной ряд, у панды уже есть свой собственный метод в объекте. Мы можем построить временной ряд следующим образом:

# Lenghts along time:
tlen.plot(figsize=(16,4), color='r');

Это создает следующий вывод:

Длины по времени

И построить график лайков по сравнению с ретвитами в одном и том же графике:

# Likes vs retweets visualization:
tfav.plot(figsize=(16,4), label="Likes", legend=True)
tret.plot(figsize=(16,4), label="Retweets", legend=True);

Это создаст следующий вывод:

Лайки против ретвитов

2.3. Круговые диаграммы источников

Мы почти закончили со вторым разделом поста. Теперь мы построим источники в виде круговой диаграммы, так как мы поняли, что не каждый твит отправляется из одного и того же источника ( 😱 🤔 ). Сначала мы очищаем все источники:

# We obtain all possible sources:
sources = []
for source in data['Source']:
    if source not in sources:
        sources.append(source)

# We print sources list:
print("Creation of content sources:")
for source in sources:
    print("* {}".format(source))

С помощью следующего вывода мы понимаем, что в основном эта учетная запись twitter имеет два источника: Создание источников контента: * Twitter для iPhone * Media Studio

Теперь мы подсчитываем количество каждого источника и создаем круговую диаграмму. Вы заметите, что эта ячейка кода не является самой оптимизированной… Пожалуйста, имейте в виду, что было 4 часа утра, когда я проектировал этот семинар. 😅

# We create a numpy vector mapped to labels:
percent = np.zeros(len(sources))

for source in data['Source']:
    for index in range(len(sources)):
        if source == sources[index]:
            percent[index] += 1
            pass

percent /= 100

# Pie chart:
pie_chart = pd.Series(percent, index=sources, name='Sources')
pie_chart.plot.pie(fontsize=11, autopct='%.2f', figsize=(6, 6));

С помощью этого мы получаем результат, подобный этому:

Круговая диаграмма источников

И мы можем видеть процент твитов на источник.

Теперь мы можем приступить к анализу настроений.

3.1. Импорт текстового блока

Как мы уже упоминали в начале этого поста, textblob позволит нам провести анализ настроений очень простым способом. Мы также будем использовать библиотеку re из Python, которая используется для работы с регулярными выражениями . Для этого я предоставлю вам две полезные функции: а) очистить текст (что означает, что любой символ, отличный от буквенно-цифрового значения, будет переназначен в новый, удовлетворяющий этому условию), и б) создать классификатор для анализа полярности каждого твита после очистки текста в нем. Я не буду объяснять конкретный способ, которым работает функция очистки, поскольку она будет расширена и может быть лучше понята в официальной re документации .

Код, который я предоставляю, это:

from textblob import TextBlob
import re

def clean_tweet(tweet):
    '''
    Utility function to clean the text in a tweet by removing 
    links and special characters using regex.
    '''
    return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", tweet).split())

def analize_sentiment(tweet):
    '''
    Utility function to classify the polarity of a tweet
    using textblob.
    '''
    analysis = TextBlob(clean_tweet(tweet))
    if analysis.sentiment.polarity > 0:
        return 1
    elif analysis.sentiment.polarity == 0:
        return 0
    else:
        return -1

Это работает так, что textblob уже предоставляет обученный анализатор (круто, правда?). Текстовый blob может работать с различными моделями машинного обучения , используемыми в обработке естественного языка . Если вы хотите обучить свой собственный классификатор (или, по крайней мере, проверить, как он работает), не стесняйтесь проверить следующую ссылку /. Это может быть актуально, поскольку мы работаем с предварительно обученной моделью (для которой мы не используем данные, которые были использованы).

В любом случае, возвращаясь к коду, мы просто добавим дополнительный столбец к нашим данным. Этот столбец будет содержать анализ настроений, и мы можем построить фрейм данных, чтобы увидеть обновление:

# We create a column with the result of the analysis:
data['SA'] = np.array([ analize_sentiment(tweet) for tweet in data['Tweets'] ])

# We display the updated dataframe with the new column:
display(data.head(10))

Получение нового результата:

903778130850131970 1 5585 144 2017-09-02 00:34:32 24572 Twitter для iPhone От имени @FLOTUS Melania и меня, ТХА… 0
903770196388831233 1 8825 132 2017-09-02 00:03:00 44748 Twitter для iPhone Завтра я поеду в Техас и Луизиану… 1
903766326631698432 0 9134 34 2017-09-01 23:47:38 44518 Twitter для iPhone Фондовый рынок растет 5 месяцев подряд! 2
903705867891204096 0 15127 140 2017-09-01 19:47:23 47009 Медиа-студия “Президент Дональд Трамп Объявляет Сентябрь… 3
903603043714957312 1 15398 143 2017-09-01 12:58:48 77680 Twitter для iPhone Техас быстро выздоравливает благодаря всем gre… 4
903600265420578819 1 11424 113 2017-09-01 12:47:46 54664 Twitter для iPhone …делайте все в рекордно короткие сроки. Много больших … 5
903597166249246720 1 11678 140 2017-09-01 12:35:27 59840 Twitter для iPhone Генерал Джон Келли отлично справляется с ролью чи… 6
903587428488839170 1 35936 130 2017-09-01 11:56:45 110667 Twitter для iPhone Вау, похоже, Джеймс Коми оправдал Хиллари… 7
903348312421670912 1 29064 110 2017-08-31 20:06:35 112012 Twitter для iPhone СПАСИБО всем невероятным ГЕРОЯМ в Т… 8
903234878124249090 0 6638 140 2017-08-31 20:06:35 0 Twitter для iPhone RT @FoxNews: .@KellyannePolls на Harvey recove… 9

Как мы видим, последний столбец содержит анализ настроений ( SA ). Теперь нам просто нужно проверить результаты.

3.2. Анализ результатов

Чтобы иметь простой способ проверить результаты, мы подсчитаем количество нейтральных, положительных и отрицательных твитов и извлекем проценты.

# We construct lists with classified tweets:

pos_tweets = [ tweet for index, tweet in enumerate(data['Tweets']) if data['SA'][index] > 0]
neu_tweets = [ tweet for index, tweet in enumerate(data['Tweets']) if data['SA'][index] == 0]
neg_tweets = [ tweet for index, tweet in enumerate(data['Tweets']) if data['SA'][index] < 0]

Теперь, когда у нас есть списки, мы просто печатаем проценты:

# We print percentages:

print("Percentage of positive tweets: {}%".format(len(pos_tweets)*100/len(data['Tweets'])))
print("Percentage of neutral tweets: {}%".format(len(neu_tweets)*100/len(data['Tweets'])))
print("Percentage de negative tweets: {}%".format(len(neg_tweets)*100/len(data['Tweets'])))

Получение следующего результата: Процент положительных твитов: 51,0% Процент нейтральных твитов: 27,0% Процент отрицательных твитов: 22,0%

Мы должны учитывать, что мы работаем только с 200 самыми последними твитами от Д. Трампа (последнее обновление: 2 сентября). Для более точных результатов мы можем рассмотреть больше твитов. Интересная вещь (приглашение читателям) состоит в том, чтобы проанализировать полярность твитов из разных источников, это может быть детерминировано тем, что, рассматривая только твиты из одного источника, полярность приведет к более положительному/отрицательному результату. В любом случае, я надеюсь, что это будет интересно.

Как мы видели, с помощью Python мы можем извлекать, манипулировать, визуализировать и анализировать данные очень простым способом. Я надеюсь, что это оставляет некоторую неопределенность у читателя для дальнейшего изучения с помощью этих инструментов.

Возможно, удастся найти небольшие ошибки в переводе материала (я разработал семинар на испанском языке, первоначально 😅 ). Пожалуйста, не стесняйтесь комментировать или предлагать все, что приходит вам в голову. Это дополнит некоторые идеи, которые я уже имею в виду для дальнейшей работы. 😀

Теперь я оставлю некоторые ссылки на документацию и учебные пособия по используемым библиотекам. Надеюсь услышать от вас!

Рекомендации: