{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Collecting Data from the Spotify Web API using Spotipy\n", "\n", "## About the Spotipy Library:\n", "\n", "From the [official Spotipy docs](https://spotipy.readthedocs.io/en/latest/): \n", ">\"Spotipy is a lightweight Python library for the Spotify Web API. With Spotipy you get full access to all of the music data provided by the Spotify platform.\"\n", "\n", "\n", "## About using the Spotify Web API:\n", "\n", "Spotify offers a number of [API endpoints](https://beta.developer.spotify.com/documentation/web-api/reference/) to access the Spotify data. In this notebook, I used the following:\n", "\n", "- [search endpoint](https://beta.developer.spotify.com/documentation/web-api/reference/search/search/) to get the track IDs \n", "- [audio features endpoint](https://beta.developer.spotify.com/documentation/web-api/reference/tracks/get-several-audio-features/) to get the corresponding audio features.\n", "\n", "The data was collected on several days during the months of April, May and August 2018.\n", "\n", "\n", "## Goal of this notebook:\n", "\n", "The goal is to show how to collect audio features data for tracks from the [official Spotify Web API](https://beta.developer.spotify.com/documentation/web-api/) in order to use it for further analysis/ machine learning which will be part of another notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Setting Up\n", "\n", "The below code is sufficient to set up Spotipy for querying the API endpoint. A more detailed explanation of the whole procedure is available in the [official docs](https://spotipy.readthedocs.io/en/latest/#installation)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import spotipy\n", "from spotipy.oauth2 import SpotifyClientCredentials\n", "\n", "cid =\"xx\" \n", "secret = \"xx\"\n", "\n", "client_credentials_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)\n", "sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. Get the Track ID Data\n", "\n", "The data collection is divided into 2 parts: the track IDs and the audio features. In this step, I'm going to collect 10.000 track IDs from the Spotify API.\n", "\n", "The [search endpoint](https://beta.developer.spotify.com/documentation/web-api/reference/search/search/) used in this step had a few limitations:\n", "\n", "- limit: a maximum of 50 results can be returned per query\n", "- offset: this is the index of the first result to return, so if you want to get the results with the index 50-100 you will need to set the offset to 50 etc.\n", "\n", "Spotify cut down the maximum offset to 10.000 (as of May 2018?), I was lucky enough to do my first collection attempt while it was still 100.000\n", "\n", "My solution: using a nested for loop, I increased the offset by 50 in the outer loop until the maxium limit/ offset was reached. The inner for loop did the actual querying and appending the returned results to appropriate lists which I used afterwards to create my dataframe." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time to run this code (in seconds): 242.2539935503155\n" ] } ], "source": [ "# timeit library to measure the time needed to run this code\n", "import timeit\n", "start = timeit.default_timer()\n", "\n", "# create empty lists where the results are going to be stored\n", "artist_name = []\n", "track_name = []\n", "popularity = []\n", "track_id = []\n", "\n", "for i in range(0,10000,50):\n", " track_results = sp.search(q='year:2018', type='track', limit=50,offset=i)\n", " for i, t in enumerate(track_results['tracks']['items']):\n", " artist_name.append(t['artists'][0]['name'])\n", " track_name.append(t['name'])\n", " track_id.append(t['id'])\n", " popularity.append(t['popularity'])\n", " \n", "\n", "stop = timeit.default_timer()\n", "print ('Time to run this code (in seconds):', stop - start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. EDA + Data Preparation\n", "\n", "In the next few cells, I'm going to do some exploratory data analysis as well as data preparation of the newly gained data.\n", "\n", "A quick check for the track_id list:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number of elements in the track_id list: 10000\n" ] } ], "source": [ "print('number of elements in the track_id list:', len(track_id))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looks good. Now loading the lists in a dataframe." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(10000, 4)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
artist_namepopularitytrack_idtrack_name
0Drake1002G7V7zsVDxg1yRsu7Ew9RJIn My Feelings
1XXXTENTACION973ee8Jmje8o58CHK66QrVC2SAD!
2Tyga965IaHrVsrferBYDm0bDyAByTaste (feat. Offset)
3Cardi B9758q2HKrzhC3ozto2nDdN4zI Like It
4XXXTENTACION950JP9xo3adEtGSdUEISiszLMoonlight
\n", "
" ], "text/plain": [ " artist_name popularity track_id track_name\n", "0 Drake 100 2G7V7zsVDxg1yRsu7Ew9RJ In My Feelings\n", "1 XXXTENTACION 97 3ee8Jmje8o58CHK66QrVC2 SAD!\n", "2 Tyga 96 5IaHrVsrferBYDm0bDyABy Taste (feat. Offset)\n", "3 Cardi B 97 58q2HKrzhC3ozto2nDdN4z I Like It\n", "4 XXXTENTACION 95 0JP9xo3adEtGSdUEISiszL Moonlight" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "df_tracks = pd.DataFrame({'artist_name':artist_name,'track_name':track_name,'track_id':track_id,'popularity':popularity})\n", "print(df_tracks.shape)\n", "df_tracks.head()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 10000 entries, 0 to 9999\n", "Data columns (total 4 columns):\n", "artist_name 10000 non-null object\n", "popularity 10000 non-null int64\n", "track_id 10000 non-null object\n", "track_name 10000 non-null object\n", "dtypes: int64(1), object(3)\n", "memory usage: 312.6+ KB\n" ] } ], "source": [ "df_tracks.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sometimes, the same track is returned under different track IDs (single, as part of an album etc.).\n", "\n", "This needs to be checked for and corrected if needed." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "524" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# group the entries by artist_name and track_name and check for duplicates\n", "\n", "grouped = df_tracks.groupby(['artist_name','track_name'], as_index=True).size()\n", "grouped[grouped > 1].count()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are 524 duplicate entries which will be dropped in the next cell:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "df_tracks.drop_duplicates(subset=['artist_name','track_name'], inplace=True)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# doing the same grouping as before to verify the solution\n", "grouped_after_dropping = df_tracks.groupby(['artist_name','track_name'], as_index=True).size()\n", "grouped_after_dropping[grouped_after_dropping > 1].count()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This time the results are empty. Another way of checking this:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "artist_name 0\n", "popularity 0\n", "track_id 0\n", "track_name 0\n", "dtype: int64" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_tracks[df_tracks.duplicated(subset=['artist_name','track_name'],keep=False)].count()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Checking how many tracks are left now:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(9460, 4)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_tracks.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4: Get the Audio Features Data\n", "\n", "With the [audio features endpoint](https://beta.developer.spotify.com/documentation/web-api/reference/tracks/get-several-audio-features/) I will now get the audio features data for my 9460 track IDs.\n", "\n", "The limitation for this endpoint is that a maximum of 100 track IDs can be submitted per query.\n", "\n", "Again, I used a nested for loop. This time the outer loop was pulling track IDs in batches of size 100 and the inner for loop was doing the query and appending the results to the rows list.\n", "\n", "Additionaly, I had to implement a check when a track ID didn't return any audio features (i.e. None was returned) as this was causing issues." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of tracks where no audio features were available: 86\n", "Time to run this code (in seconds): 11.267732854001224\n" ] } ], "source": [ "# again measuring the time\n", "start = timeit.default_timer()\n", "\n", "# empty list, batchsize and the counter for None results\n", "rows = []\n", "batchsize = 100\n", "None_counter = 0\n", "\n", "for i in range(0,len(df_tracks['track_id']),batchsize):\n", " batch = df_tracks['track_id'][i:i+batchsize]\n", " feature_results = sp.audio_features(batch)\n", " for i, t in enumerate(feature_results):\n", " if t == None:\n", " None_counter = None_counter + 1\n", " else:\n", " rows.append(t)\n", " \n", "print('Number of tracks where no audio features were available:',None_counter)\n", "\n", "stop = timeit.default_timer()\n", "print ('Time to run this code (in seconds):',stop - start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5. EDA + Data Preparation\n", "\n", "Same as with the first dataset, checking how the rows list looks like:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number of elements in the track_id list: 9374\n" ] } ], "source": [ "print('number of elements in the track_id list:', len(rows))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, I will load the audio features in a dataframe." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape of the dataset: (9374, 18)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
acousticnessanalysis_urldanceabilityduration_msenergyidinstrumentalnesskeylivenessloudnessmodespeechinesstempotime_signaturetrack_hreftypeurivalence
00.00669https://api.spotify.com/v1/audio-analysis/2G7V...0.7382179330.4662G7V7zsVDxg1yRsu7Ew9RJ0.0102080.449-9.43310.1370181.9924https://api.spotify.com/v1/tracks/2G7V7zsVDxg1...audio_featuresspotify:track:2G7V7zsVDxg1yRsu7Ew9RJ0.401
10.25800https://api.spotify.com/v1/audio-analysis/3ee8...0.7401666060.6133ee8Jmje8o58CHK66QrVC20.0037280.123-4.88010.145075.0234https://api.spotify.com/v1/tracks/3ee8Jmje8o58...audio_featuresspotify:track:3ee8Jmje8o58CHK66QrVC20.473
20.02360https://api.spotify.com/v1/audio-analysis/5IaH...0.8842329590.5595IaHrVsrferBYDm0bDyABy0.0000000.101-7.44210.120097.9944https://api.spotify.com/v1/tracks/5IaHrVsrferB...audio_featuresspotify:track:5IaHrVsrferBYDm0bDyABy0.342
30.09900https://api.spotify.com/v1/audio-analysis/58q2...0.8162533900.72658q2HKrzhC3ozto2nDdN4z0.0000050.372-3.99800.1290136.0484https://api.spotify.com/v1/tracks/58q2HKrzhC3o...audio_featuresspotify:track:58q2HKrzhC3ozto2nDdN4z0.650
40.55600https://api.spotify.com/v1/audio-analysis/0JP9...0.9211350900.5370JP9xo3adEtGSdUEISiszL0.0040490.102-5.72300.0804128.0094https://api.spotify.com/v1/tracks/0JP9xo3adEtG...audio_featuresspotify:track:0JP9xo3adEtGSdUEISiszL0.711
\n", "
" ], "text/plain": [ " acousticness analysis_url \\\n", "0 0.00669 https://api.spotify.com/v1/audio-analysis/2G7V... \n", "1 0.25800 https://api.spotify.com/v1/audio-analysis/3ee8... \n", "2 0.02360 https://api.spotify.com/v1/audio-analysis/5IaH... \n", "3 0.09900 https://api.spotify.com/v1/audio-analysis/58q2... \n", "4 0.55600 https://api.spotify.com/v1/audio-analysis/0JP9... \n", "\n", " danceability duration_ms energy id \\\n", "0 0.738 217933 0.466 2G7V7zsVDxg1yRsu7Ew9RJ \n", "1 0.740 166606 0.613 3ee8Jmje8o58CHK66QrVC2 \n", "2 0.884 232959 0.559 5IaHrVsrferBYDm0bDyABy \n", "3 0.816 253390 0.726 58q2HKrzhC3ozto2nDdN4z \n", "4 0.921 135090 0.537 0JP9xo3adEtGSdUEISiszL \n", "\n", " instrumentalness key liveness loudness mode speechiness tempo \\\n", "0 0.01020 8 0.449 -9.433 1 0.1370 181.992 \n", "1 0.00372 8 0.123 -4.880 1 0.1450 75.023 \n", "2 0.00000 0 0.101 -7.442 1 0.1200 97.994 \n", "3 0.00000 5 0.372 -3.998 0 0.1290 136.048 \n", "4 0.00404 9 0.102 -5.723 0 0.0804 128.009 \n", "\n", " time_signature track_href \\\n", "0 4 https://api.spotify.com/v1/tracks/2G7V7zsVDxg1... \n", "1 4 https://api.spotify.com/v1/tracks/3ee8Jmje8o58... \n", "2 4 https://api.spotify.com/v1/tracks/5IaHrVsrferB... \n", "3 4 https://api.spotify.com/v1/tracks/58q2HKrzhC3o... \n", "4 4 https://api.spotify.com/v1/tracks/0JP9xo3adEtG... \n", "\n", " type uri valence \n", "0 audio_features spotify:track:2G7V7zsVDxg1yRsu7Ew9RJ 0.401 \n", "1 audio_features spotify:track:3ee8Jmje8o58CHK66QrVC2 0.473 \n", "2 audio_features spotify:track:5IaHrVsrferBYDm0bDyABy 0.342 \n", "3 audio_features spotify:track:58q2HKrzhC3ozto2nDdN4z 0.650 \n", "4 audio_features spotify:track:0JP9xo3adEtGSdUEISiszL 0.711 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_audio_features = pd.DataFrame.from_dict(rows,orient='columns')\n", "print(\"Shape of the dataset:\", df_audio_features.shape)\n", "df_audio_features.head()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 9374 entries, 0 to 9373\n", "Data columns (total 18 columns):\n", "acousticness 9374 non-null float64\n", "analysis_url 9374 non-null object\n", "danceability 9374 non-null float64\n", "duration_ms 9374 non-null int64\n", "energy 9374 non-null float64\n", "id 9374 non-null object\n", "instrumentalness 9374 non-null float64\n", "key 9374 non-null int64\n", "liveness 9374 non-null float64\n", "loudness 9374 non-null float64\n", "mode 9374 non-null int64\n", "speechiness 9374 non-null float64\n", "tempo 9374 non-null float64\n", "time_signature 9374 non-null int64\n", "track_href 9374 non-null object\n", "type 9374 non-null object\n", "uri 9374 non-null object\n", "valence 9374 non-null float64\n", "dtypes: float64(9), int64(4), object(5)\n", "memory usage: 1.3+ MB\n" ] } ], "source": [ "df_audio_features.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some columns are not needed for the analysis so I will drop them.\n", "\n", "Also the ID column will be renamed to track_id so that it matches the column name from the first dataframe." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(9374, 14)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "columns_to_drop = ['analysis_url','track_href','type','uri']\n", "df_audio_features.drop(columns_to_drop, axis=1,inplace=True)\n", "\n", "df_audio_features.rename(columns={'id': 'track_id'}, inplace=True)\n", "\n", "df_audio_features.shape" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape of the dataset: (9374, 14)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
artist_namepopularitytrack_idtrack_nameacousticnessdanceabilityduration_msenergyinstrumentalnesskeylivenessloudnessmodespeechinesstempotime_signaturevalence
0Drake1002G7V7zsVDxg1yRsu7Ew9RJIn My Feelings0.006690.7382179330.4660.0102080.449-9.43310.1370181.99240.401
1XXXTENTACION973ee8Jmje8o58CHK66QrVC2SAD!0.258000.7401666060.6130.0037280.123-4.88010.145075.02340.473
2Tyga965IaHrVsrferBYDm0bDyAByTaste (feat. Offset)0.023600.8842329590.5590.0000000.101-7.44210.120097.99440.342
3Cardi B9758q2HKrzhC3ozto2nDdN4zI Like It0.099000.8162533900.7260.0000050.372-3.99800.1290136.04840.650
4XXXTENTACION950JP9xo3adEtGSdUEISiszLMoonlight0.556000.9211350900.5370.0040490.102-5.72300.0804128.00940.711
\n", "
" ], "text/plain": [ " artist_name popularity track_id track_name \\\n", "0 Drake 100 2G7V7zsVDxg1yRsu7Ew9RJ In My Feelings \n", "1 XXXTENTACION 97 3ee8Jmje8o58CHK66QrVC2 SAD! \n", "2 Tyga 96 5IaHrVsrferBYDm0bDyABy Taste (feat. Offset) \n", "3 Cardi B 97 58q2HKrzhC3ozto2nDdN4z I Like It \n", "4 XXXTENTACION 95 0JP9xo3adEtGSdUEISiszL Moonlight \n", "\n", " acousticness danceability duration_ms energy instrumentalness key \\\n", "0 0.00669 0.738 217933 0.466 0.01020 8 \n", "1 0.25800 0.740 166606 0.613 0.00372 8 \n", "2 0.02360 0.884 232959 0.559 0.00000 0 \n", "3 0.09900 0.816 253390 0.726 0.00000 5 \n", "4 0.55600 0.921 135090 0.537 0.00404 9 \n", "\n", " liveness loudness mode speechiness tempo time_signature valence \n", "0 0.449 -9.433 1 0.1370 181.992 4 0.401 \n", "1 0.123 -4.880 1 0.1450 75.023 4 0.473 \n", "2 0.101 -7.442 1 0.1200 97.994 4 0.342 \n", "3 0.372 -3.998 0 0.1290 136.048 4 0.650 \n", "4 0.102 -5.723 0 0.0804 128.009 4 0.711 " ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# merge both dataframes\n", "# the 'inner' method will make sure that we only keep track IDs present in both datasets\n", "df = pd.merge(df_tracks,df_audio_features,on='track_id',how='inner')\n", "print(\"Shape of the dataset:\", df_audio_features.shape)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Int64Index: 9374 entries, 0 to 9373\n", "Data columns (total 17 columns):\n", "artist_name 9374 non-null object\n", "popularity 9374 non-null int64\n", "track_id 9374 non-null object\n", "track_name 9374 non-null object\n", "acousticness 9374 non-null float64\n", "danceability 9374 non-null float64\n", "duration_ms 9374 non-null int64\n", "energy 9374 non-null float64\n", "instrumentalness 9374 non-null float64\n", "key 9374 non-null int64\n", "liveness 9374 non-null float64\n", "loudness 9374 non-null float64\n", "mode 9374 non-null int64\n", "speechiness 9374 non-null float64\n", "tempo 9374 non-null float64\n", "time_signature 9374 non-null int64\n", "valence 9374 non-null float64\n", "dtypes: float64(9), int64(5), object(3)\n", "memory usage: 1.3+ MB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just in case, checking for any duplicate tracks:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
artist_namepopularitytrack_idtrack_nameacousticnessdanceabilityduration_msenergyinstrumentalnesskeylivenessloudnessmodespeechinesstempotime_signaturevalence
\n", "
" ], "text/plain": [ "Empty DataFrame\n", "Columns: [artist_name, popularity, track_id, track_name, acousticness, danceability, duration_ms, energy, instrumentalness, key, liveness, loudness, mode, speechiness, tempo, time_signature, valence]\n", "Index: []" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df.duplicated(subset=['artist_name','track_name'],keep=False)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Everything seems to be fine so I will save the dataframe as a .csv file." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "df.to_csv('SpotifyAudioFeatures08082018.csv')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 2 }