Вдохновленный Нерудистом Разместите на веб -сайте 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”