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

Построение данных Spotify

В этом посте я покажу вам, как играть с вашими данными прослушивания Spotify; Мы скопируем красивый сюжет, вдохновленный GitHub. Tagged Seaborn, Matplotlib, Python, DataViz.

Вдохновленный Нерудистом Разместите на веб -сайте Tacos de Datos (на испанском) Я попросил Spotify для моих данных и начал делать с ними несколько сюжетов. Если вы хотите сделать то же самое, перейдите к Эта страница ; После того, как вы запросите его, потребуется пару дней, чтобы быть доступным. А пока вы можете использовать это Google Colab Я создал подмножество моих данных для вас.

Среди всей информации, которую вы получите, будут указаны некоторые файлы с использованием этого шаблона: Streaminghistoryxx.json И это те, которые мы будем использовать в этом посте.

Данные

Файлы, упомянутые выше, содержат что -то вроде этого:

[
  {
    "endTime" : "2019-02-04 17:14",
    "artistName" : "MGMT",
    "trackName" : "Time to Pretend",
    "msPlayed" : 261000
  },
  {
    "endTime" : "2019-02-04 17:18",
    "artistName" : "MGMT",
"..." 

Где значения:

  • Конечное время : День и время, когда песня закончилась, в формате UTC.
  • ArtistName : Имя художника песни.
  • TrackName : Название песни.
  • msplayed : Как долго (в миллисекундах) была сыграна песня.

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

from glob import glob
import json
import pandas as pd

def read_history():
    history = []
    for file in sorted(glob("StreamingHistory*.json")):
        with open(file) as readable:
            history.extend(json.load(readable))
    history = pd.DataFrame(history)
    history["endTime"] = pd.to_datetime(history["endTime"])
    return history

streaming_history = read_history()
streaming_history.head(5)

Что должно дать нам что -то подобное, как только мы его выполняем:

2019-02-04 17:14:00 261000 Время притворяться 0 Mgmt
2019-02-04 17:18:00 263880 Когда ты умрешь 1 Mgmt
2019-02-04 17:23:00 201518 Super Smash Bros. Brawl Main Theme (от “Super Smash Bros. Brawl”) [Капелла] 2 Мистер Дувс

Гистограмма.

Я всегда был поклонником того, как GitHub демонстрирует вклад разработчиков, и данные, которые мы получили от Spotify, кажется идеальным кандидатом, чтобы создать что -то подобное; Тем не менее, нам нужно сначала выполнить некоторые преобразования.

Поскольку мы не заинтересованы в том времени, когда каждая песня закончила, мы избавимся от временной части Конечное время :

streaming_history["date"] = streaming_history["endTime"].dt.floor('d')

Тогда мы получим количество песен в день, используя GroupBy :

by_date = streaming_history.groupby("date")[["trackName"]].count()
by_date = by_date.sort_index()

Для участия, нам нужно знать, какой день недели ссылается каждая дата, мы можем использовать свойства неделя и будний день :

by_date["weekday"] = by_date.index.weekday
by_date["week"] = by_date.index.week

В конце концов, наша дата должна выглядеть так:

2019-02-04 6 0 5
2019-02-05 6 1 8
2019-02-07 6 3 60

У нас есть почти все, что нам нужно, следующим шагом является получение непрерывной последовательности чисел за каждую неделю. В DataFrame выше 6 -й недели 2016 года должна быть неделя 0, 7 -я должна быть неделя 1 … Я не могу придумать лучшего способа сделать это, чем для петля:

week = 0
prev_week = by_date.iloc[0]["week"]
continuous_week = np.zeros(len(by_date)).astype(int)
sunday_dates = []
for i, (_, row) in enumerate(by_date.iterrows()):
    if row["week"] != prev_week:
        week += 1
        prev_week = row["week"]
    continuous_week[i] = week
by_date["continuous_week"] = continuous_week 
by_date.head()
2019-02-04 6 0 5 0
2019-02-05 6 1 8 0
2019-02-07 6 3 60 0

Наш следующий шаг – генерировать матрицу с Дни ✕ недель В качестве измерений, где каждая из записей будет количество песен, которые мы слушали в тот день и неделю:

songs = np.full((7, continuous_week.max()+1), np.nan)

for index, row in by_date.iterrows():
    songs[row["weekday"]][row["continuous_week"]] = row["trackName"]

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

fig = plt.figure(figsize=(20,5))
ax = plt.subplot()
mask = np.isnan(songs)
sns.heatmap(songs, ax = ax)

Но результат не так уж и хорош:

Если мы хотим, чтобы это выглядело лучше, нам все еще нужен код, первое, что нужно сделать, это очистить этикетки оси:

min_date = streaming_history["endTime"].min()
first_monday = min_date - timedelta(min_date.weekday())
mons = [first_monday + timedelta(weeks=wk) for wk in range(continuous_week.max())]
x_labels = [calendar.month_abbr[mons[0].month]]
x_labels.extend([
    calendar.month_abbr[mons[i].month] if mons[i-1].month != mons[i].month else "" 
    for i in range(1, len(mons))])

y_labels = ["Mon", "", "Wed", "", "Fri", "", "Sun"]

Метки оси x гораздо сложнее, чем у y; Это связано с тем, что, в отличие от Y, ось x не является фиксированной и непрерывной, как таковая, они должны рассчитывать на основе данных. Если вы хотите более подробное объяснение, расскажите мне в комментариях или на меня в Твиттере по адресу @io_exception )

После этого мы выполним некоторые модификации с цветами и осью:

fig = plt.figure(figsize=(20,5))
ax = plt.subplot()

ax.set_title("My year on Spotify", fontsize=20,pad=40)
ax.xaxis.tick_top()
ax.tick_params(axis='both', which='both',length=0)
ax.set_facecolor("#ebedf0") 
fig.patch.set_facecolor('white')

И, наконец, мы можем использовать Seaborn’s Тепловая карта Опять же, на этот раз с несколькими привычками, которые я объясню позже:

sns.heatmap(songs, linewidths=2, linecolor='white', square=True,
            mask=np.isnan(songs), cmap="Greens",
            vmin=0, vmax=100, cbar=False, ax=ax)

ax.set_yticklabels(y_labels, rotation=0)
ax.set_xticklabels(x_labels, ha="left")

Аргументы следующие:

  • песни : Наша матрица с формой Дни ✕ недель с графами песен в день,
  • ширина Line : Размер интервала между каждым патчем,
  • LineColor : Цвет расстояния между каждым пятном,
  • квадрат : Это говорит о функции, что мы хотим сохранить соотношение сторон 1: 1 Для каждого патча,
  • Маска : Очень интересный аргумент, он поможет нам «маскировать» патчи, для которых нет записанного значения, этот аргумент должен быть логической матрицей тех же измерений, что и нанесенные данные, где каждый Верно означает, что это конкретное значение должно быть замаскировано,
  • CMAP : Colormap Для использования, к счастью для нас, значение «зелень» сочетается с цветовой палитрой, выбранной GitHub,
  • Вмин : значение, которое следует рассматривать как минимум среди наших значений,
  • Vmax : Значение, которое следует рассматривать как максимальное среди наших значений, я бы считал 100 максимумом, хотя моя запись находится в 190 году в день!
  • CBAR : a логический Значение, чтобы указать, хотим ли мы показать цветовую полосу, которая обычно поставляется с Тепловая карта В
  • AX : топоры Наш заговор должен быть замышлен.

И Вуаля , наш сюжет готов:

Вам решать, чтобы изменить сюжет, может быть добавлено информацию о количестве песен или показать цвету … отличная идея – воссоздать этот сюжет в таком рамках, как D3.JS, но это вполне может принадлежать к другому посту. Опять же, не стесняйтесь отправиться в этот колаб и свяжитесь со мной через Twitter @io_exception Анкет

Оригинал: “https://dev.to/fferegrino/plotting-your-spotify-data-2km8”