Анализ данных PornHub или двойное проникновение в визуализацию

Добрый день, уважаемые читатели. Недавно мне на глаза попался отрывок статистики PornHub, где хранились данные про 190к видеоматериалов. Сам датасет находится на kaggle. Мы проведём анализ данных PornHub и визуализируем результаты статистики.

Сегодня мы узнаем, какие самые высокооцениваемые, продолжительные или просматриваемые категории.

Подпишись на группу Вконтакте и Телеграм-канал. Там еще больше полезного контента для программистов.
А на YouTube-канале ты найдешь обучающие видео по программированию. Подписывайся!

Загрузка данных

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

In[1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

Загрузим данные в таблицу pandas и извлечём размер таблицы.

In[2]:
df = pd.read_csv('data.csv')
total_size = len(df)

df.head()

Каждый раз я буду вызывать метод head() для проверки корректности операций над таблицей.
Удалим ненужные столбцы с помощью конструкции del:

In[3]:
del df['Unnamed: 0']
del df['img_source'] 
del df['video_link']
del df['tags']
df.head()

Отбор категорий

Вся сложность в распределении видео по категориям состоит в том, что поле category содержит строки вида «Category1__Category2__…».
И чтобы правильно присвоить каждому видео несколько категорий, нам необходим особый механизм, который мы сейчас и реализуем.
Чтобы создать список всех категорий, выполним следующий фрагмент кода:

In[4]:
categories = list()

for category in df['categories'].values:
category = str(category)
for tag in category.split('__'):
if not tag in categories:
categories.append(tag)

categories[:5]

Out[5]:
['Blowjob', 'Threesome ', 'Brunette', 'Blonde', 'MILF ']

Примечание. Я не буду переводить название категорий в виду своей неполной компетентности в этом вопросе :) Кто знает, тот поймёт.

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

In[5]:
for tag in categories:
df[tag] = np.zeros(total_size)

df.head()

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

Теперь по следующему алгоритму заполним столбцы:

  • пройдёмся по всем названиям категорий
  • разделяем значение поля category по ‘__’ для каждого видео
  • если одна из категорий соответствует текущему, то присваиваем соответствующему элементу столбца значение 1
  • передаём новый столбец в таблицу
In[6]:
for tag in categories:
column = np.zeros(total_size)
for i, category in enumerate(df[categories]):
if tag in category.split('__'):
column[i] = 1
df[tag] = column

df.head()

Визуализация

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

In[7]:
votes = [(tag, df[df[tag] == 1]['voting'].values.mean()) for tag in categories]
votes.sort(reverse=True, key=lambda set: set[1])
votes = votes[:15]; votes.reverse()

scores = [set[1] for set in votes]
labels = [set[0] for set in votes]
plt.figure(figsize=(20, 10))
plt.yticks(range(15), labels, fontsize=20)
plt.title('Most voited categories on PornHub', fontsize=20)
plt.xlabel('Vote', fontsize=20); plt.ylabel('Category', fontsize=20)
plt.barh(range(15), scores, height=0.5, color='blue')
plt.savefig('votes.png')
Самые оцениваемые категории
In[8]:
views = [(tag, df[df[tag] == 1]['nb_views'].values.mean()) for tag in categories]
views.sort(reverse=True, key=lambda set: set[1])
views = views[:15]; views.reverse()

view = [set[1] / 10**6 for set in views]
labels = [set[0] for set in views]

plt.figure(figsize=(20, 10))
plt.yticks(range(15), labels, fontsize=20)
plt.title('Most viewed categories on PornHub', fontsize=20)
plt.xlabel('Mean views (in millions)', fontsize=20);
plt.ylabel('Category', fontsize=20)
plt.barh(range(15), view, height=0.5, color='blue')
plt.savefig('views.png')
Самые просматриваемые категории

Warning! Вас тоже смущает значительный отрыв категории «Babe»? Скорее всего это связанно с выбросом в данных. Попробуйте самостоятельно разобрать этот момент.

In[9]:
lengths = [(tag, df[df[tag] == 1]['length'].values.mean()) for tag in categories]
lengths.sort(reverse=True, key=lambda set: set[1])
lengths = lengths[:15]; lengths.reverse()

length = [set[1] / 60 for set in lengths]
labels = [set[0] for set in lengths]

plt.figure(figsize=(20, 10))
plt.yticks(range(15), labels, fontsize=20)
plt.title('Most "longest" categories on PornHub', fontsize=20)
plt.xlabel('Mean length (in minutes)', fontsize=20);
plt.ylabel('Category', fontsize=20)
plt.barh(range(15), length, height=0.5, color='blue')

plt.savefig('lengths.png')
Самые «длинные» видео по категориям

Заключение про анализ данных PornHub

Как мы можем заметить, исследование статистики порносайтов порой приносят интересные наблюдения. В таблице много «полей», которые вы можете исследовать. Подкидываю пищу для размышлений: попробуйте выяснить, какие слова наиболее часто встречаются в названиях порнографии (естественно, слова по типу I, and, too не должны учитываться)?

Ссылка на документ с кодом, который вы можете просмотреть и изменить на своё усмотрение, используя Jupyter Notebook.

Также рекомендую прочитать статью Функциональный API библиотеки Keras. А также подписывайтесь на группу ВКонтакте, Telegram и YouTube-канал. Там еще больше полезного и интересного для программистов.