sung


Namesung JSON
Version 0.0.8 PyPI version JSON
download
home_pagehttps://github.com/thorwhalen/sung
SummaryMusic data access
upload_time2024-11-16 18:55:19
maintainerNone
docs_urlNone
authorThor Whalen
requires_pythonNone
licensemit
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # sung

Music data access. Mainly sources from spotify and wikipedia.


# Install

To install:	```pip install sung```

For most tools, you'll also need a spotify

```
export SPOTIFY_API_CLIENT_ID="your_api_client_id"
export SPOTIFY_API_CLIENT_SECRET="your_api_client_secrete"
export SPOTIPY_REDIRECT_URI="http://localhost:8000/callback"
export SPOTIPY_CLIENT_ID="$SPOTIFY_API_CLIENT_ID"
export SPOTIPY_CLIENT_SECRET="$SPOTIFY_API_CLIENT_SECRET"
```

## Spotify API credentials?

To obtain Spotify API credentials, follow these steps:
	1.	Create a Spotify Developer Account:
	•	Visit the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/).
	•	Log in with your Spotify account or create a new one.
	2.	Register a New Application:
	•	Click on “Create an App.”
	•	Provide an App Name and App Description.
	•	Agree to the Developer Terms of Service.
	•	Click “Create.”
	3.	Retrieve Client ID and Client Secret:
	•	After creating the app, you’ll be directed to the app’s dashboard.
	•	Here, you’ll find your Client ID and Client Secret.
	•	Keep these credentials secure; they are essential for API authentication.
	4.	Set Redirect URIs (if applicable):
	•	In your app settings, click “Edit Settings.”
	•	Under “Redirect URIs,” add the URIs where Spotify should redirect after authentication.
	•	This is crucial for certain authorization flows.

For detailed information on authorization flows and using your credentials, refer to 
[Spotify’s Authorization Guide](https://developer.spotify.com/documentation/web-api/concepts/authorization).

Ensure you handle your Client Secret securely and adhere to 
[Spotify’s Developer Terms of Service](https://developer.spotify.com/terms/).

# Using the sung.base Module to Search Tracks and Create a Playlist

In this example, we’ll:
* Search for tracks using `Tracks.search`.
* See the search results from the dict-like `tracks` instance
* Display the search results in a pandas DataFrame.
* Create a playlist called "my_test_playlist" with the selected tracks.
* Get the URL of the newly created playlist.
* Delete a playlist
* Instantiate a `Playlist` object using a URL.
* Look at audio features aof this playlist



Import the necessary classes from the sung.base module


```python
from sung.base import Tracks, Playlist
```

Search for tracks with the query 'Love', limiting the results to 7
This will return a Tracks object containing the search results


```python
tracks = Tracks.search(query='Love', limit=7)
```

```
list(tracks)
```


    ['1vrd6UOGamcKNGnSHJQlSt',
     '3CeCwYWvdfXbZLXFhBrbnf',
     '1dGr1c8CrMLDpV6mPbImSI',
     '0u2P5u6lvoDfwTYjAADbn4',
     '6nGeLlakfzlBcFdZXteDq7',
     '6dBUzqjtbnIa1TwYbyw5CM',
     '7hR22TOX3RorxJPcsz5Wbo']


You can also make a `tracks` object by passing a list of track IDs or urls


```python
track_ids = [
    '1vrd6UOGamcKNGnSHJQlSt',
    '3CeCwYWvdfXbZLXFhBrbnf',
    '1dGr1c8CrMLDpV6mPbImSI',
    '0u2P5u6lvoDfwTYjAADbn4',
    'https://open.spotify.com/track/6nGeLlakfzlBcFdZXteDq7',  # url
    'https://open.spotify.com/track/6dBUzqjtbnIa1TwYbyw5CM',   # url
    'spotify:track:7hR22TOX3RorxJPcsz5Wbo',  # uri
]

tracks = Tracks(track_ids)
```

`tracks` is a `Mapping` (that means "dict-like"), so you can do what you do with dicts...

Like listing the tracks' keys (IDs)


```python
list(tracks)
```


    ['1vrd6UOGamcKNGnSHJQlSt',
     '3CeCwYWvdfXbZLXFhBrbnf',
     '1dGr1c8CrMLDpV6mPbImSI',
     '0u2P5u6lvoDfwTYjAADbn4',
     '6nGeLlakfzlBcFdZXteDq7',
     '6dBUzqjtbnIa1TwYbyw5CM',
     '7hR22TOX3RorxJPcsz5Wbo']



Like Accessing the value of a track for a given key. 
The value is a bunch of metadata about the track.


```python
track_metadata = tracks['1dGr1c8CrMLDpV6mPbImSI']  # get metadata of track via it's id
assert isinstance(track_metadata, dict)
sorted(track_metadata)
```



    ['album',
     'artists',
     'available_markets',
     'disc_number',
     'duration_ms',
     'explicit',
     'external_ids',
     'external_urls',
     'href',
     'id',
     'is_local',
     'name',
     'popularity',
     'preview_url',
     'track_number',
     'type',
     'uri']


But we also have extras over normal dicts. 

We can get metadata of a track via it's index:


```python
track_metadata = tracks[2]  # get metadata of track via it's id
```

We can get a sublist of track metadatas from a list of ids.

```python
list_of_track_metadatas = tracks[['6dBUzqjtbnIa1TwYbyw5CM', '1vrd6UOGamcKNGnSHJQlSt']]  # get metadata of tracks via a list of ids
```

We can also get a sublist using slicing.

```python
list_of_track_metadatas = tracks[2:4]  # get metadata of tracks via a slice of ids
```


## Display the search results in a pandas DataFrame

The dataframe method converts the track metadata into a DataFrame for easy viewing.

(Note, you can also use the tracks.dataframe(keys, front_columns=...) to retrieve a data table with more control.)


If you have `pandas` installed, you can get the meta data as a table (dataframe).

```python
tracks.data
```


<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>duration_ms</th>
      <th>popularity</th>
      <th>explicit</th>
      <th>id</th>
      <th>album</th>
      <th>artists</th>
      <th>available_markets</th>
      <th>disc_number</th>
      <th>external_ids</th>
      <th>external_urls</th>
      <th>href</th>
      <th>is_local</th>
      <th>preview_url</th>
      <th>track_number</th>
      <th>type</th>
      <th>uri</th>
    </tr>
    <tr>
      <th>id</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1vrd6UOGamcKNGnSHJQlSt</th>
      <td>Love Story</td>
      <td>235266</td>
      <td>62</td>
      <td>False</td>
      <td>1vrd6UOGamcKNGnSHJQlSt</td>
      <td>{'album_type': 'album', 'artists': [{'external...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[CA, US]</td>
      <td>1</td>
      <td>{'isrc': 'USCJY0803275'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/1v...</td>
      <td>https://api.spotify.com/v1/tracks/1vrd6UOGamcK...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/7bc39c6033766fc8...</td>
      <td>3</td>
      <td>track</td>
      <td>spotify:track:1vrd6UOGamcKNGnSHJQlSt</td>
    </tr>
    <tr>
      <th>3CeCwYWvdfXbZLXFhBrbnf</th>
      <td>Love Story (Taylor’s Version)</td>
      <td>235766</td>
      <td>76</td>
      <td>False</td>
      <td>3CeCwYWvdfXbZLXFhBrbnf</td>
      <td>{'album_type': 'single', 'artists': [{'externa...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'USUG12100342'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/3C...</td>
      <td>https://api.spotify.com/v1/tracks/3CeCwYWvdfXb...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/b2c1ed4794591a62...</td>
      <td>1</td>
      <td>track</td>
      <td>spotify:track:3CeCwYWvdfXbZLXFhBrbnf</td>
    </tr>
    <tr>
      <th>1dGr1c8CrMLDpV6mPbImSI</th>
      <td>Lover</td>
      <td>221306</td>
      <td>84</td>
      <td>False</td>
      <td>1dGr1c8CrMLDpV6mPbImSI</td>
      <td>{'album_type': 'album', 'artists': [{'external...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'USUG11901473'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/1d...</td>
      <td>https://api.spotify.com/v1/tracks/1dGr1c8CrMLD...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/aad996e106de5278...</td>
      <td>3</td>
      <td>track</td>
      <td>spotify:track:1dGr1c8CrMLDpV6mPbImSI</td>
    </tr>
    <tr>
      <th>0u2P5u6lvoDfwTYjAADbn4</th>
      <td>lovely (with Khalid)</td>
      <td>200185</td>
      <td>86</td>
      <td>False</td>
      <td>0u2P5u6lvoDfwTYjAADbn4</td>
      <td>{'album_type': 'single', 'artists': [{'externa...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'USUM71804190'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/0u...</td>
      <td>https://api.spotify.com/v1/tracks/0u2P5u6lvoDf...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/18b3cbbad11e488c...</td>
      <td>1</td>
      <td>track</td>
      <td>spotify:track:0u2P5u6lvoDfwTYjAADbn4</td>
    </tr>
    <tr>
      <th>6nGeLlakfzlBcFdZXteDq7</th>
      <td>Love Story</td>
      <td>316280</td>
      <td>74</td>
      <td>False</td>
      <td>6nGeLlakfzlBcFdZXteDq7</td>
      <td>{'album_type': 'album', 'artists': [{'external...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'FRUM71400048'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/6n...</td>
      <td>https://api.spotify.com/v1/tracks/6nGeLlakfzlB...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/677f771b1fc30024...</td>
      <td>3</td>
      <td>track</td>
      <td>spotify:track:6nGeLlakfzlBcFdZXteDq7</td>
    </tr>
    <tr>
      <th>6dBUzqjtbnIa1TwYbyw5CM</th>
      <td>Lovers Rock</td>
      <td>213920</td>
      <td>85</td>
      <td>False</td>
      <td>6dBUzqjtbnIa1TwYbyw5CM</td>
      <td>{'album_type': 'album', 'artists': [{'external...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'USHM21438143'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/6d...</td>
      <td>https://api.spotify.com/v1/tracks/6dBUzqjtbnIa...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/922a42db5aa8f8d3...</td>
      <td>9</td>
      <td>track</td>
      <td>spotify:track:6dBUzqjtbnIa1TwYbyw5CM</td>
    </tr>
    <tr>
      <th>7hR22TOX3RorxJPcsz5Wbo</th>
      <td>Love Somebody</td>
      <td>204828</td>
      <td>86</td>
      <td>False</td>
      <td>7hR22TOX3RorxJPcsz5Wbo</td>
      <td>{'album_type': 'single', 'artists': [{'externa...</td>
      <td>[{'external_urls': {'spotify': 'https://open.s...</td>
      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>
      <td>1</td>
      <td>{'isrc': 'USUG12406387'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/7h...</td>
      <td>https://api.spotify.com/v1/tracks/7hR22TOX3Ror...</td>
      <td>False</td>
      <td>https://p.scdn.co/mp3-preview/00b94e332ed40625...</td>
      <td>1</td>
      <td>track</td>
      <td>spotify:track:7hR22TOX3RorxJPcsz5Wbo</td>
    </tr>
  </tbody>
</table>
</div>



## Make a playlist

Create a new playlist named 'my_test_playlist' with the selected tracks
The create_from_track_list class method creates a new playlist with the given tracks


```python
playlist = Playlist.create_from_track_list(
    track_list=selected_track_ids,
    playlist_name='my_test_playlist'
)
print(f"\nPlaylist '{playlist.playlist_id}' created successfully.")

```

    
    Playlist '7BZcFvIWUnVzvZ5wpVt9cD' created successfully.


Get the playlist URL of the newly created playlist (go check it out!)


```python
playlist.playlist_url
```


    'https://open.spotify.com/playlist/7BZcFvIWUnVzvZ5wpVt9cD'



## Delete a playlist

We purposely tried to make deleting a playlist not as easy as the other actions. 
So we didn't attach a delete method to the playlist instance, but put this in a 
separate function you have to import. 
Also, we made that function verbose, and asking for confirmation by default. 
(But there's arguments to control that, so you can use `functools.partial` to 
make your own cowboy (not speaking and not asking for permission) version).


```python
from sung import delete_playlist

delete_playlist(playlist.playlist_id)
```

Instantiate a Playlist object using a URL.
This allows you to interact with the playlist, such as accessing its tracks.


```python
top50_global_url = 'https://open.spotify.com/playlist/37i9dQZEVXbMDoHDwVN2tF?si=d6e0c7bc8f59473b'
top50_playlist = Playlist(top50_global_url)
df = top50_playlist.data
df['first_artist'] = df['artists'].apply(lambda x: x[0]['name'])
df['name_and_first_artist'] = df['name'] + ' - ' + df['first_artist']
top_5_tracks = top50_playlist.data.iloc[:5].name_and_first_artist
top_5_tracks
```


    id
    2plbrEY59IikOBgBGLjaoe          Die With A Smile - Lady Gaga
    5vNRhkKd0yEAg8suGBpjeY                           APT. - ROSÉ
    6dOtVTDdiauQNBQEDOtlAB    BIRDS OF A FEATHER - Billie Eilish
    7ne4VBA60CxGM75vw0EYad        That’s So True - Gracie Abrams
    7tI8dRuH2Yc6RuoTjxo4dU                           Who - Jimin
    Name: name_and_first_artist, dtype: object


## Audio features


```python
import pandas as pd

print(f"{top50_playlist.audio_features_df.shape=}")
top50_playlist.audio_features_df.iloc[0]

```

    top50_playlist.audio_features_df.shape=(50, 17)





    danceability                                                    0.521
    energy                                                          0.592
    key                                                                 6
    loudness                                                       -7.777
    mode                                                                0
    speechiness                                                    0.0304
    acousticness                                                    0.308
    instrumentalness                                                  0.0
    liveness                                                        0.122
    valence                                                         0.535
    tempo                                                         157.969
    type                                                   audio_features
    uri                              spotify:track:2plbrEY59IikOBgBGLjaoe
    track_href          https://api.spotify.com/v1/tracks/2plbrEY59Iik...
    analysis_url        https://api.spotify.com/v1/audio-analysis/2plb...
    duration_ms                                                    251668
    time_signature                                                      3
    Name: 2plbrEY59IikOBgBGLjaoe, dtype: object




```python
import seaborn as sns
from matplotlib import pyplot as plt

df = pd.merge(top50_playlist.data, top50_playlist.audio_features_df, left_index=True, right_index=True)
# scatter plot with danceability and energy, colored by popularity, with size as loudness
sns.scatterplot(data=df, x='danceability', y='energy', hue='popularity', size='loudness')

# Move the legend outside the plot
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left');
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/sung_demo_files/sung_demo_31_0.png)
    



```python
import seaborn as sns

sns.pairplot(top50_playlist.audio_features_df[['danceability', 'energy', 'loudness', 'speechiness', 'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo']])
```




    <seaborn.axisgrid.PairGrid at 0x10ac069b0>




    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/sung_demo_files/sung_demo_32_1.png)
    


## Audio analysis


```python
audio_analysis = top50_playlist.audio_analysis(next(iter(top50_playlist)))
```


```python
type(audio_analysis)
```




    dict




```python
list(audio_analysis)
```




    ['meta', 'track', 'bars', 'beats', 'sections', 'segments', 'tatums']




```python
audio_analysis['meta']
```




    {'analyzer_version': '4.0.0',
     'platform': 'Linux',
     'detailed_status': 'OK',
     'status_code': 0,
     'timestamp': 1723785476,
     'analysis_time': 5.78793,
     'input_process': 'libvorbisfile L+R 44100->22050'}




```python
audio_analysis['track']
```


    {'num_samples': 5549270,
     'duration': 251.66757,
     'sample_md5': '',
     'offset_seconds': 0,
     'window_seconds': 0,
     'analysis_sample_rate': 22050,
     'analysis_channels': 1,
     'end_of_fade_in': 0.2034,
     'start_of_fade_out': 241.98096,
     'loudness': -7.863,
     'tempo': 158.005,
     'tempo_confidence': 0.501,
     'time_signature': 3,
     'time_signature_confidence': 1.0,
     'key': 6,
     'key_confidence': 0.253,
     'mode': 0,
     'mode_confidence': 0.452,
     'codestring': 'eJxVmgcC...twbhuw==',
     'code_version': 3.15,
     'echoprintstring': '...',
     'echoprint_version': 4.12,
     'synchstring': 'eJxVWYmR6zoMa8UlSDx09N...EsF7ZvNGhvn5DzGSYaU=',
     'synch_version': 1.0,
     'rhythmstring': 'eJxdnAmSWzkSQ6..._8hOM4=',
     'rhythm_version': 1.0}




```python
from lkj import truncate_dict_values

print(f"{len(audio_analysis['bars'])=})")
truncate_dict_values(audio_analysis['bars'])
```

    len(audio_analysis['bars'])=211)





    [{'start': 1.36936, 'duration': 1.1373, 'confidence': 0.506},
     {'start': 2.50666, 'duration': 1.14286, 'confidence': 0.037}]




```python
print(f"{len(audio_analysis['beats'])=})")
truncate_dict_values(audio_analysis['beats'])
```

    len(audio_analysis['beats'])=639)





    [{'start': 0.598, 'duration': 0.39454, 'confidence': 0.786},
     {'start': 0.99254, 'duration': 0.37682, 'confidence': 0.461}]




```python
print(f"{len(audio_analysis['sections'])=})")
truncate_dict_values(audio_analysis['sections'])
```

    len(audio_analysis['sections'])=10)




    [{'start': 0.0,
      'duration': 9.72348,
      'confidence': 1.0,
      'loudness': -22.269,
      'tempo': 158.348,
      'tempo_confidence': 0.353,
      'key': 1,
      'key_confidence': 0.03,
      'mode': 0,
      'mode_confidence': 0.567,
      'time_signature': 3,
      'time_signature_confidence': 1.0},
     {'start': 9.72348,
      'duration': 29.24311,
      'confidence': 0.606,
      'loudness': -11.712,
      'tempo': 158.114,
      'tempo_confidence': 0.364,
      'key': 9,
      'key_confidence': 0.217,
      'mode': 1,
      'mode_confidence': 0.472,
      'time_signature': 3,
      'time_signature_confidence': 1.0}]




```python
print(f"{len(audio_analysis['segments'])=})")
truncate_dict_values(audio_analysis['segments'])
```

    len(audio_analysis['segments'])=780)





    [{'start': 0.0,
      'duration': 0.2034,
      'confidence': 0.0,
      'loudness_start': -60.0,
      'loudness_max_time': 0.0,
      'loudness_max': -60.0,
      'loudness_end': 0.0,
      'pitches': [1.0, 1.0],
      'timbre': [0.0, 171.13]},
     {'start': 0.2034,
      'duration': 0.41234,
      'confidence': 1.0,
      'loudness_start': -60.0,
      'loudness_max_time': 0.05445,
      'loudness_max': -22.196,
      'loudness_end': 0.0,
      'pitches': [0.082, 0.554],
      'timbre': [33.758, 53.096]}]




```python
print(f"{len(audio_analysis['tatums'])=})")
truncate_dict_values(audio_analysis['tatums'])
```

    len(audio_analysis['tatums'])=1278)





    [{'start': 0.598, 'duration': 0.19727, 'confidence': 0.786},
     {'start': 0.79527, 'duration': 0.19727, 'confidence': 0.786}]




```python
from lkj import truncate_dict_values

truncate_dict_values(audio_analysis, max_list_size=2)
```


    {'meta': {'analyzer_version': '4.0.0',
      'platform': 'Linux',
      'detailed_status': 'OK',
      'status_code': 0,
      'timestamp': 1476616359,
      'analysis_time': 109.6869,
      'input_process': 'libvorbisfile L+R 44100->22050'},
     'track': {'num_samples': 15594936,
      'duration': 707.25336,
      'sample_md5': '',
      'offset_seconds': 0,
      'window_seconds': 0,
      'analysis_sample_rate': 22050,
      'analysis_channels': 1,
      'end_of_fade_in': 2.82703,
      'start_of_fade_out': 693.6381,
      'loudness': -10.355,
      'tempo': 106.396,
      'tempo_confidence': 0.595,
      'time_signature': 4,
      'time_signature_confidence': 0.904,
      'key': 5,
      'key_confidence': 0.049,
      'mode': 0,
      'mode_confidence': 0.228,
      'codestring': 'eJw1nQmS5LqOBK9SRxB38v4X63BHtv2...y2bmBs1qBYvtiECKLDlx_oH4Y3DGg==',
      'code_version': 3.15,
      'echoprintstring': 'eJzcnQ2u7DhzZLckUaRILkf82_8S5oT...av23MzLxruBTa5AgsAdSL_-A1nrtTE=',
      'echoprint_version': 4.12,
      'synchstring': 'eJx9mAuS5DgIRK_iI1h_6_4XW_IlclV...OPN79PfjNMgH2A-QVgPFZR_AHMBU_o=',
      'synch_version': 1.0,
      'rhythmstring': 'eJyNnVmSJEmOQ68SR9B9uf_FxogHqme...EXgaMRt5h7-gy4yclWmWjb8_wC55QRT',
      'rhythm_version': 1.0},
     'bars': [{'start': 2.64511, 'duration': 2.23768, 'confidence': 0.825},
      {'start': 4.88279, 'duration': 2.16451, 'confidence': 0.352}],
     'beats': [{'start': 0.9181, 'duration': 0.58698, 'confidence': 0.683},
      {'start': 1.50508, 'duration': 0.57369, 'confidence': 0.572}],
     'sections': [{'start': 0.0,
       'duration': 11.51788,
       'confidence': 1.0,
       'loudness': -20.409,
       'tempo': 108.121,
       'tempo_confidence': 0.728,
       'key': 6,
       'key_confidence': 0.162,
       'mode': 1,
       'mode_confidence': 0.478,
       'time_signature': 4,
       'time_signature_confidence': 0.1},
      {'start': 11.51788,
       'duration': 30.61314,
       'confidence': 0.731,
       'loudness': -12.171,
       'tempo': 107.882,
       'tempo_confidence': 0.499,
       'key': 10,
       'key_confidence': 0.429,
       'mode': 0,
       'mode_confidence': 0.387,
       'time_signature': 4,
       'time_signature_confidence': 0.467}],
     'segments': [{'start': 0.0,
       'duration': 0.60957,
       'confidence': 0.0,
       'loudness_start': -60.0,
       'loudness_max_time': 0.5863,
       'loudness_max': -56.103,
       'loudness_end': 0.0,
       'pitches': [0.8, 0.511],
       'timbre': [0.116, 169.016]},
      {'start': 0.60957,
       'duration': 0.60376,
       'confidence': 1.0,
       'loudness_start': -55.895,
       'loudness_max_time': 0.03504,
       'loudness_max': -36.652,
       'loudness_end': 0.0,
       'pitches': [0.434, 0.38],
       'timbre': [13.111, 157.189]}],
     'tatums': [{'start': 0.9181, 'duration': 0.29349, 'confidence': 0.683},
      {'start': 1.21159, 'duration': 0.29349, 'confidence': 0.683}]}




# Analyze a playlist


```python
from sung import TracksAnalysis, ensure_playlist_id

```

## Initialize the Class with a Playlist ID


```python
# Let's analyze my daughter's playlist...

playlist = "https://open.spotify.com/playlist/4nEeS47ineUShHK2iAVeO0?si=be16c62b664f43f3"

ta = TracksAnalysis(playlist)
```

Note that, alternatively, if you already have a dataframe, you can just give `TracksAnalysis` that.
Note that it must have been prepared by `TracksAnalysis`, or at least satisfy the dataframe conditions on the columns. 


```python
# import pandas as pd
# df = pd.read_excel("~/Dropbox/_odata/ai_contexts/misc/music/encore_playlist.xlsx")
# ta = TracksAnalysis(df)
```

## Access the Processed Dataframe


```python
ta.df.head()

```



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name</th>
      <th>first_artist</th>
      <th>duration_ms</th>
      <th>popularity</th>
      <th>explicit</th>
      <th>album_release_date</th>
      <th>album_release_year</th>
      <th>added_at_date</th>
      <th>url</th>
      <th>first_letter</th>
      <th>...</th>
      <th>disc_number</th>
      <th>external_ids</th>
      <th>external_urls</th>
      <th>href</th>
      <th>is_local</th>
      <th>track_number</th>
      <th>type</th>
      <th>uri</th>
      <th>preview_url</th>
      <th>added_at_datetime</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>181</th>
      <td>Love The Way You Lie</td>
      <td>Eminem</td>
      <td>263373</td>
      <td>47</td>
      <td>False</td>
      <td>2010-06-18</td>
      <td>2010</td>
      <td>2024-11-06</td>
      <td>https://open.spotify.com/track/4k5Rb51qsUSMFg6...</td>
      <td>L</td>
      <td>...</td>
      <td>1</td>
      <td>{'isrc': 'USUM71015443'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/4k...</td>
      <td>https://api.spotify.com/v1/tracks/4k5Rb51qsUSM...</td>
      <td>False</td>
      <td>15</td>
      <td>track</td>
      <td>spotify:track:4k5Rb51qsUSMFg6oFdVC48</td>
      <td>NaN</td>
      <td>2024-11-06T16:01:38Z</td>
    </tr>
    <tr>
      <th>180</th>
      <td>Without Me</td>
      <td>Eminem</td>
      <td>290120</td>
      <td>46</td>
      <td>False</td>
      <td>2002-05-26</td>
      <td>2002</td>
      <td>2024-11-03</td>
      <td>https://open.spotify.com/track/3Q0kSmKpkffn4aW...</td>
      <td>W</td>
      <td>...</td>
      <td>1</td>
      <td>{'isrc': 'USIR10211127'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/3Q...</td>
      <td>https://api.spotify.com/v1/tracks/3Q0kSmKpkffn...</td>
      <td>False</td>
      <td>10</td>
      <td>track</td>
      <td>spotify:track:3Q0kSmKpkffn4aWkYkWwet</td>
      <td>NaN</td>
      <td>2024-11-03T11:27:58Z</td>
    </tr>
    <tr>
      <th>179</th>
      <td>Lose Yourself</td>
      <td>Eminem</td>
      <td>320573</td>
      <td>50</td>
      <td>False</td>
      <td>2014-11-24</td>
      <td>2014</td>
      <td>2024-11-03</td>
      <td>https://open.spotify.com/track/2jvHb9SHJDi8Ugk...</td>
      <td>L</td>
      <td>...</td>
      <td>2</td>
      <td>{'isrc': 'USIR10211570'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/2j...</td>
      <td>https://api.spotify.com/v1/tracks/2jvHb9SHJDi8...</td>
      <td>False</td>
      <td>3</td>
      <td>track</td>
      <td>spotify:track:2jvHb9SHJDi8Ugky7tUzUb</td>
      <td>NaN</td>
      <td>2024-11-03T11:27:34Z</td>
    </tr>
    <tr>
      <th>178</th>
      <td>The Real Slim Shady</td>
      <td>Eminem</td>
      <td>283693</td>
      <td>54</td>
      <td>False</td>
      <td>2005-12-06</td>
      <td>2005</td>
      <td>2024-11-03</td>
      <td>https://open.spotify.com/track/2WXUcFnJPPATncU...</td>
      <td>T</td>
      <td>...</td>
      <td>1</td>
      <td>{'isrc': 'USIR10000449'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/2W...</td>
      <td>https://api.spotify.com/v1/tracks/2WXUcFnJPPAT...</td>
      <td>False</td>
      <td>9</td>
      <td>track</td>
      <td>spotify:track:2WXUcFnJPPATncUkPYC54v</td>
      <td>NaN</td>
      <td>2024-11-03T11:27:15Z</td>
    </tr>
    <tr>
      <th>177</th>
      <td>Houdini</td>
      <td>Eminem</td>
      <td>227239</td>
      <td>57</td>
      <td>False</td>
      <td>2024-05-30</td>
      <td>2024</td>
      <td>2024-11-03</td>
      <td>https://open.spotify.com/track/6vw2M02LT3otGUo...</td>
      <td>H</td>
      <td>...</td>
      <td>1</td>
      <td>{'isrc': 'USUG12403399'}</td>
      <td>{'spotify': 'https://open.spotify.com/track/6v...</td>
      <td>https://api.spotify.com/v1/tracks/6vw2M02LT3ot...</td>
      <td>False</td>
      <td>1</td>
      <td>track</td>
      <td>spotify:track:6vw2M02LT3otGUoK4ZqHwx</td>
      <td>NaN</td>
      <td>2024-11-03T11:21:18Z</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 25 columns</p>
</div>



## Perform Analyses


```python
print(f"Number of songs: {ta.number_of_songs}")
print(f"Number of unique names: {ta.number_of_unique_names}")
```

    Number of songs: 182
    Number of unique names: 178


### Print Duplicates


```python
ta.print_duplicates()
```

    
    ### Duplicates
    |                              |   count |
    |:-----------------------------|--------:|
    | Houdini                      |       2 |
    | Anything You Can Do          |       2 |
    | Somebody That I Used to Know |       2 |
    | The Bare Necessities         |       2 |


### Print Most Popular Songs


```python
ta.print_most_popular_songs(n=20)
```

    | name                                            | first_artist      |   popularity |
    |:------------------------------------------------|:------------------|-------------:|
    | Espresso                                        | Sabrina Carpenter |           90 |
    | exes                                            | Tate McRae        |           83 |
    | Sweet Dreams (Are Made of This) - 2005 Remaster | Eurythmics        |           83 |
    | Zombie                                          | The Cranberries   |           82 |
    | Here Comes The Sun - Remastered 2009            | The Beatles       |           82 |
    | Before You Go                                   | Lewis Capaldi     |           81 |
    | bad guy                                         | Billie Eilish     |           81 |
    | ...Baby One More Time                           | Britney Spears    |           81 |
    | Tainted Love                                    | Soft Cell         |           79 |
    | Wrecking Ball                                   | Miley Cyrus       |           78 |
    | New Rules                                       | Dua Lipa          |           78 |
    | Rolling in the Deep                             | Adele             |           77 |
    | Kings & Queens                                  | Ava Max           |           77 |
    | Easy On Me                                      | Adele             |           77 |
    | Roar                                            | Katy Perry        |           77 |
    | bellyache                                       | Billie Eilish     |           76 |
    | Jolene                                          | Dolly Parton      |           75 |
    | Symphony (feat. Zara Larsson)                   | Clean Bandit      |           75 |
    | Nice For What                                   | Drake             |           74 |
    | bury a friend                                   | Billie Eilish     |           74 |


### Print Top Artists


```python
ta.print_top_artists(n=25)
```

    | first_artist       |   count |
    |:-------------------|--------:|
    | Dua Lipa           |       6 |
    | Eminem             |       5 |
    | Jacob Collier      |       4 |
    | Norris Nuts        |       4 |
    | The Beatles        |       4 |
    | Hugh Jackman       |       4 |
    | Music Together     |       3 |
    | Leonard Bernstein  |       3 |
    | Julie Andrews      |       3 |
    | Walk off the Earth |       3 |
    | John Williams      |       3 |
    | Billie Eilish      |       3 |
    | Anna Kendrick      |       3 |
    | Zac Efron          |       2 |
    | Clean Bandit       |       2 |
    | Adele              |       2 |
    | Shakira            |       2 |
    | Stromae            |       2 |
    | Michael Jackson    |       2 |
    | Lin-Manuel Miranda |       2 |
    | Caravan Palace     |       2 |
    | Queen              |       2 |
    | Ynairaly Simo      |       2 |
    | Édith Piaf         |       2 |
    | Dolly Parton       |       1 |


### Plot Number of Songs per Release Year


```python
ta.plot_songs_per_year()
```

    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 44053 (\N{HANGUL SYLLABLE GANG}) missing from font(s) DejaVu Sans.
      fig.canvas.print_figure(bytes_io, **kw)
    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 45224 (\N{HANGUL SYLLABLE NAM}) missing from font(s) DejaVu Sans.
      fig.canvas.print_figure(bytes_io, **kw)
    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 49828 (\N{HANGUL SYLLABLE SEU}) missing from font(s) DejaVu Sans.
      fig.canvas.print_figure(bytes_io, **kw)
    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 53440 (\N{HANGUL SYLLABLE TA}) missing from font(s) DejaVu Sans.
      fig.canvas.print_figure(bytes_io, **kw)
    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 51068 (\N{HANGUL SYLLABLE IL}) missing from font(s) DejaVu Sans.
      fig.canvas.print_figure(bytes_io, **kw)



    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_20_1.png)
    


### Plot Added Date vs. Release Date


```python
ta.plot_added_vs_release_dates()
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_22_0.png)
    



```python
ta.plot_added_vs_release_kde()
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_23_0.png)
    



```python
ta.plot_added_vs_release_kde_boundary()
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_24_0.png)
    


### Plot First Letter Distribution


```python
ta.plot_first_letter_distribution(sort_by='lexicographical')
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_26_0.png)
    



```python
ta.plot_first_letter_distribution(sort_by='count')
```


    
![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_27_0.png)
    


### Print Top Tracks by Starting Letter


```python
ta.print_top_names_by_letter(n=5)
```

    L (5 tracks):
      - (74) Levitating
      - (73) Livin' la Vida Loca
      - (63) Lucy In The Sky With Diamonds - Remastered 2009
      - (58) La Vie en rose
      - (50) Lose Yourself
    W (5 tracks):
      - (78) Wrecking Ball
      - (71) We Don't Talk About Bruno
      - (69) Wellerman - Sea Shanty
      - (69) We Will Rock You - Remastered 2011
      - (64) Wuthering Heights
    T (5 tracks):
      - (79) Tainted Love
      - (74) Training Season
      - (70) The Other Side
      - (70) The Greatest Show
      - (70) This Is Me
    H (5 tracks):
      - (82) Here Comes The Sun - Remastered 2009
      - (74) Happy Together
      - (57) Houdini
      - (57) Houdini
      - (57) Holocaust
    S (5 tracks):
      - (83) Sweet Dreams (Are Made of This) - 2005 Remaster
      - (75) Symphony (feat. Zara Larsson)
      - (74) Somebody That I Used To Know
      - (74) Señorita
      - (71) Super Trouper
    N (4 tracks):
      - (78) New Rules
      - (74) Nice For What
      - (63) Night Falls
      - (44) Non, je ne regrette rien
    R (5 tracks):
      - (77) Rolling in the Deep
      - (77) Roar
      - (70) Rewrite The Stars
      - (59) Ring My Bell
      - (48) Running Out Of Time
    E (4 tracks):
      - (90) Espresso
      - (83) exes
      - (77) Easy On Me
      - (53) Eating the Cats (Donald Trump Remix)
    A (5 tracks):
      - (73) Ain't Nobody (Loves Me Better) (feat. Jasmine Thompson)
      - (72) A Million Dreams
      - (53) A Spoonful of Sugar - From "Mary Poppins" / Soundtrack Version
      - (0) Anything You Can Do
      - (29) Away We Go
    1 (1 tracks):
      - (19) 10:35
    I (5 tracks):
      - (68) I Like To Move It
      - (66) Illusion
      - (65) I'll Be There for You - Theme From "Friends"
      - (47) It's Oh So Quiet
      - (40) Indiana Jones Theme
    C (5 tracks):
      - (69) Chandelier
      - (67) Come Alive
      - (62) Crab Rave
      - (53) Coconut
      - (46) Cups - Movie Version
    V (1 tracks):
      - (25) Viens
    U (1 tracks):
      - (14) Unity
    D (5 tracks):
      - (72) Don't Stop Believin'
      - (66) Dance Monkey
      - (62) Drive My Car - Remastered 2009
      - (53) Do-Re-Mi
      - (41) Don't Rain on My Parade
    M (5 tracks):
      - (74) MIDDLE OF THE NIGHT
      - (56) Material Girl
      - (49) Mellow Yellow
      - (46) Monster
      - (36) My Baby Just Cares For Me
    B (5 tracks):
      - (81) Before You Go
      - (81) bad guy
      - (76) bellyache
      - (74) bury a friend
      - (67) Bad - 2012 Remaster
    F (4 tracks):
      - (70) From Now On
      - (65) Friend Like Me
      - (63) Fat Bottomed Girls - Remastered 2011
      - (58) Fever
    G (5 tracks):
      - (74) Ghostbusters
      - (73) Get Into It (Yuh)
      - (72) Gangnam Style (강남스타일)
      - (62) Get Back Up Again
      - (59) Greased Lightnin' - From “Grease”
    P (3 tracks):
      - (64) Peaches
      - (30) Pink Panther Theme - Remix Version
      - (0) Papaoutai
    Y (3 tracks):
      - (65) You Can't Always Get What You Want
      - (49) You Can't Stop The Beat
      - (31) You're No Good - From 'Minions: The Rise of Gru' Soundtrack
    Z (1 tracks):
      - (82) Zombie
    K (3 tracks):
      - (77) Kings & Queens
      - (58) Karma Chameleon
      - (0) Kung Fu Fighting (From "Kung Fu Panda 3")
    O (5 tracks):
      - (64) Oye Como Va
      - (43) One Of A Kind
      - (41) On My Way
      - (40) One More Song
      - (0) Omg - Radio Edit
    J (3 tracks):
      - (75) Jolene
      - (43) Je Me Suis Fait Tout Petit
      - (33) Jolie coquine
    5 (1 tracks):
      - (30) 5:55
    . (1 tracks):
      - (81) ...Baby One More Time
    " (1 tracks):
      - (3) "Ellens Gesang III", D839: Ave Maria



```python
# To print all of them, just make n really big
ta.print_top_names_by_letter(n=10_000)
```

    L (12 tracks):
      - (74) Levitating
      - (73) Livin' la Vida Loca
      - (63) Lucy In The Sky With Diamonds - Remastered 2009
      - (58) La Vie en rose
      - (50) Lose Yourself
      - (47) Love The Way You Lie
      - (47) Le café
      - (44) Les cités d'or
      - (39) Little Boxes
      - (35) Lost and Found
      - (34) Lemon Boy - Acappella Version
      - (33) Laisse aller
    W (17 tracks):
      - (78) Wrecking Ball
      - (71) We Don't Talk About Bruno
      - (69) We Will Rock You - Remastered 2011
      - (69) Wellerman - Sea Shanty
      - (64) Wuthering Heights
      - (64) Who Let The Dogs Out
      - (48) What Time Is It
      - (46) Without Me
      - (43) West Side Story: Act I: America
      - (35) West Side Story: Act I: Something's Coming
      - (34) West Side Story: Act II: I Feel Pretty
      - (32) We the #Legends
      - (30) We Play All Night Long
      - (22) Winter Ducks Play on Water
      - (6) Waka Waka (This Time for Africa) [The Official 2010 FIFA World Cup (TM) Song] (feat. Freshlyground)
      - (0) Windy (Re-Recorded)
      - (0) Wimoweh (Mbube)
    T (16 tracks):
      - (79) Tainted Love
      - (74) Training Season
      - (70) The Other Side
      - (70) The Greatest Show
      - (70) This Is Me
      - (68) Truth Hurts
      - (67) Try Everything
      - (66) The Family Madrigal
      - (57) True Colors - Film Version
      - (56) The Magic Key
      - (54) The Real Slim Shady
      - (48) Time Alone With You (feat. Daniel Caesar)
      - (37) The Bare Necessities
      - (39) The Lonely Goatherd
      - (37) The Bare Necessities
      - (0) The Imperial March (Darth Vader's Theme)
    H (8 tracks):
      - (82) Here Comes The Sun - Remastered 2009
      - (74) Happy Together
      - (57) Houdini
      - (57) Houdini
      - (57) Holocaust
      - (31) Here Comes The Sun (feat. dodie)
      - (26) Hello
      - (0) Hello Song
    S (21 tracks):
      - (83) Sweet Dreams (Are Made of This) - 2005 Remaster
      - (75) Symphony (feat. Zara Larsson)
      - (74) Señorita
      - (74) Somebody That I Used To Know
      - (71) Super Trouper
      - (70) Solo (feat. Demi Lovato)
      - (68) Scatman (ski-ba-bop-ba-dop-bop)
      - (68) Somewhere Over The Rainbow_What A Wonderful World
      - (68) Surface Pressure
      - (65) Single Ladies (Put a Ring on It)
      - (46) Somebody That I Used to Know
      - (46) Somebody That I Used to Know
      - (36) Scarborough Fair / Canticle - Extended Version
      - (36) Strawberry Fields Forever - Remastered 2009
      - (30) Shape of You
      - (26) Stay Shrimpy
      - (24) Superman March - Alternate Version
      - (24) Sing, Sing, Sing
      - (18) Senza un perchè
      - (0) Suite No.3 In D Major, BWV 1068: 2. Air
      - (0) She Sells Sea Shells
    N (4 tracks):
      - (78) New Rules
      - (74) Nice For What
      - (63) Night Falls
      - (44) Non, je ne regrette rien
    R (8 tracks):
      - (77) Rolling in the Deep
      - (77) Roar
      - (70) Rewrite The Stars
      - (59) Ring My Bell
      - (48) Running Out Of Time
      - (47) Running with the Wolves - WolfWalkers Version
      - (23) Running Outta Love (feat. Tori Kelly)
      - (0) Ridin' in the Car
    E (4 tracks):
      - (90) Espresso
      - (83) exes
      - (77) Easy On Me
      - (53) Eating the Cats (Donald Trump Remix)
    A (8 tracks):
      - (73) Ain't Nobody (Loves Me Better) (feat. Jasmine Thompson)
      - (72) A Million Dreams
      - (53) A Spoonful of Sugar - From "Mary Poppins" / Soundtrack Version
      - (0) Anything You Can Do
      - (29) Away We Go
      - (28) All Norris Nuts Songs About Themselves
      - (2) Alors On Danse - Radio Edit
      - (0) Anything You Can Do
    1 (1 tracks):
      - (19) 10:35
    I (9 tracks):
      - (68) I Like To Move It
      - (66) Illusion
      - (65) I'll Be There for You - Theme From "Friends"
      - (47) It's Oh So Quiet
      - (40) Indiana Jones Theme
      - (35) I Wan'na Be Like You (2016)
      - (34) In My Bones (feat. Kimbra & Tank and The Bangas)
      - (11) I Got You - 1964 Smash Version
      - (0) It's Only A Paper Moon
    C (8 tracks):
      - (69) Chandelier
      - (67) Come Alive
      - (62) Crab Rave
      - (53) Coconut
      - (46) Cups - Movie Version
      - (36) C'est de l'eau
      - (22) Chill Jazz
      - (0) Coco Made Me Do It
    V (1 tracks):
      - (25) Viens
    U (1 tracks):
      - (14) Unity
    D (13 tracks):
      - (72) Don't Stop Believin'
      - (66) Dance Monkey
      - (62) Drive My Car - Remastered 2009
      - (53) Do-Re-Mi
      - (41) Don't Rain on My Parade
      - (38) Drop It Like It's Hot - Radio Edit
      - (37) Do The Bartman
      - (35) Dramophone
      - (25) Drive My Car
      - (11) Djevojka Sa Čardaš Nogama
      - (4) Do Your Ears Hang Low?
      - (1) Dragostea Din Tei
      - (0) Duel Of The Fates
    M (9 tracks):
      - (74) MIDDLE OF THE NIGHT
      - (56) Material Girl
      - (49) Mellow Yellow
      - (46) Monster
      - (36) My Baby Just Cares For Me
      - (30) My Own Drum (Remix) [with Missy Elliott]
      - (27) Malambo No. 1
      - (10) Mah Na Mah Na
      - (2) Mozart: Horn Concerto No. 4 in E-Flat Major, K. 495: III. Rondo (Allegro vivace)
    B (9 tracks):
      - (81) Before You Go
      - (81) bad guy
      - (76) bellyache
      - (74) bury a friend
      - (67) Bad - 2012 Remaster
      - (60) Blood on the Dance Floor
      - (46) Blue (Da Ba Dee)
      - (40) Bizet: Carmen, WD 31, Act 1: Habanera. "L'amour est un oiseau rebelle" (Carmen, Chœur)
      - (39) Baby Mine
    F (4 tracks):
      - (70) From Now On
      - (65) Friend Like Me
      - (63) Fat Bottomed Girls - Remastered 2011
      - (58) Fever
    G (7 tracks):
      - (74) Ghostbusters
      - (73) Get Into It (Yuh)
      - (72) Gangnam Style (강남스타일)
      - (62) Get Back Up Again
      - (59) Greased Lightnin' - From “Grease”
      - (40) Grand Finale
      - (32) Ghost in the Keys
    P (3 tracks):
      - (64) Peaches
      - (30) Pink Panther Theme - Remix Version
      - (0) Papaoutai
    Y (3 tracks):
      - (65) You Can't Always Get What You Want
      - (49) You Can't Stop The Beat
      - (31) You're No Good - From 'Minions: The Rise of Gru' Soundtrack
    Z (1 tracks):
      - (82) Zombie
    K (3 tracks):
      - (77) Kings & Queens
      - (58) Karma Chameleon
      - (0) Kung Fu Fighting (From "Kung Fu Panda 3")
    O (6 tracks):
      - (64) Oye Como Va
      - (43) One Of A Kind
      - (41) On My Way
      - (40) One More Song
      - (0) Omg - Radio Edit
      - (0) ooh la la (feat. Greg Nice & DJ Premier)
    J (3 tracks):
      - (75) Jolene
      - (43) Je Me Suis Fait Tout Petit
      - (33) Jolie coquine
    5 (1 tracks):
      - (30) 5:55
    . (1 tracks):
      - (81) ...Baby One More Time
    " (1 tracks):
      - (3) "Ellens Gesang III", D839: Ave Maria


### The dates table

Just a table with the added_at and album_release dates, along with other metadata, for convenience


```python
ta.dates
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>album_release_date</th>
      <th>added_at_date</th>
      <th>name</th>
      <th>first_artist</th>
      <th>name_and_artist</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>181</th>
      <td>2010-06-18</td>
      <td>2024-11-06</td>
      <td>Love The Way You Lie</td>
      <td>Eminem</td>
      <td>Love The Way You Lie -- Eminem</td>
    </tr>
    <tr>
      <th>180</th>
      <td>2002-05-26</td>
      <td>2024-11-03</td>
      <td>Without Me</td>
      <td>Eminem</td>
      <td>Without Me -- Eminem</td>
    </tr>
    <tr>
      <th>179</th>
      <td>2014-11-24</td>
      <td>2024-11-03</td>
      <td>Lose Yourself</td>
      <td>Eminem</td>
      <td>Lose Yourself -- Eminem</td>
    </tr>
    <tr>
      <th>178</th>
      <td>2005-12-06</td>
      <td>2024-11-03</td>
      <td>The Real Slim Shady</td>
      <td>Eminem</td>
      <td>The Real Slim Shady -- Eminem</td>
    </tr>
    <tr>
      <th>177</th>
      <td>2024-05-30</td>
      <td>2024-11-03</td>
      <td>Houdini</td>
      <td>Eminem</td>
      <td>Houdini -- Eminem</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2011-01-01</td>
      <td>2016-09-07</td>
      <td>Mah Na Mah Na</td>
      <td>Mahna Mahna and The Two Snowths</td>
      <td>Mah Na Mah Na -- Mahna Mahna and The Two Snowths</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2012-10-29</td>
      <td>2016-09-07</td>
      <td>Sing, Sing, Sing</td>
      <td>The Andrews Sisters</td>
      <td>Sing, Sing, Sing -- The Andrews Sisters</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2007-01-01</td>
      <td>2016-09-07</td>
      <td>My Baby Just Cares For Me</td>
      <td>Nina Simone</td>
      <td>My Baby Just Cares For Me -- Nina Simone</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2015-01-28</td>
      <td>2016-08-14</td>
      <td>Wimoweh (Mbube)</td>
      <td>Yma Sumac</td>
      <td>Wimoweh (Mbube) -- Yma Sumac</td>
    </tr>
    <tr>
      <th>0</th>
      <td>1997-01-01</td>
      <td>2016-08-14</td>
      <td>The Imperial March (Darth Vader's Theme)</td>
      <td>John Williams</td>
      <td>The Imperial March (Darth Vader's Theme) -- Jo...</td>
    </tr>
  </tbody>
</table>
<p>182 rows × 5 columns</p>
</div>




```python
ta.tracks_grouped_by_year
```



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>name_and_artist</th>
      <th>number_of_songs</th>
    </tr>
    <tr>
      <th>album_release_year</th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1954</th>
      <td>[Malambo No. 1 -- Moises Vivanco]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1961</th>
      <td>[West Side Story: Act II: I Feel Pretty -- Leo...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1965</th>
      <td>[The Lonely Goatherd -- Julie Andrews, Do-Re-M...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1967</th>
      <td>[Lucy In The Sky With Diamonds - Remastered 20...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1968</th>
      <td>[Scarborough Fair / Canticle - Extended Versio...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1969</th>
      <td>[You Can't Always Get What You Want -- The Rol...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1970</th>
      <td>[Oye Como Va -- Santana]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1971</th>
      <td>[Coconut -- Harry Nilsson]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1973</th>
      <td>[Strawberry Fields Forever - Remastered 2009 -...</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1974</th>
      <td>[Jolene -- Dolly Parton]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1977</th>
      <td>[We Will Rock You - Remastered 2011 -- Queen]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1978</th>
      <td>[Greased Lightnin' - From “Grease” -- John Tra...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1980</th>
      <td>[Super Trouper -- ABBA]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1981</th>
      <td>[Tainted Love -- Soft Cell]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1983</th>
      <td>[Les cités d'or -- Le Groupe Apollo, Sweet Dre...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1984</th>
      <td>[Material Girl -- Madonna]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1988</th>
      <td>[Drive My Car -- Bobby McFerrin]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1989</th>
      <td>[Je Me Suis Fait Tout Petit -- Georges Brassen...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1990</th>
      <td>[Do The Bartman -- The Simpsons]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1991</th>
      <td>[Mozart: Horn Concerto No. 4 in E-Flat Major, ...</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1993</th>
      <td>[Somewhere Over The Rainbow_What A Wonderful W...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>1994</th>
      <td>[Zombie -- The Cranberries]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1995</th>
      <td>[Scatman (ski-ba-bop-ba-dop-bop) -- Scatman Jo...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1996</th>
      <td>[It's Only A Paper Moon -- Ella Fitzgerald]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>1997</th>
      <td>[Blood on the Dance Floor -- Michael Jackson, ...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1999</th>
      <td>[Livin' la Vida Loca -- Ricky Martin, Anything...</td>
      <td>4</td>
    </tr>
    <tr>
      <th>2000</th>
      <td>[Indiana Jones Theme -- John Williams, Who Let...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>2001</th>
      <td>[Don't Stop Believin' -- Journey]</td>
      <td>1</td>
    </tr>
    <tr>
      <th>2002</th>
      <td>[Without Me -- Eminem, Dragostea Din Tei -- O-...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>2004</th>
      <td>[Drop It Like It's Hot - Radio Edit -- Snoop D...</td>
      <td>2</td>
    </tr>
    <tr>
      <th>2005</th>
      <td>[The Real Slim Shady -- Eminem, Winter Ducks P...</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2006</th>
      <td>[Pink Panther Theme - Remix Version -- Henry M...</td>
      <td>1</td>
    </tr>
    <tr>
      <th>2007</th>
      <td>[What Time Is It -- Zac Efron, You Can't Stop ...</td>
      <td>8</td>
    </tr>
    <tr>
      <th>2008</th>
      <td>[C'est de l'eau -- Les Enfantastiques, I Like ...</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2010</th>
      <td>[Love The Way You Lie -- Eminem, Waka Waka (Th...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>2011</th>
      <td>[Rolling in the Deep -- Adele, Lost and Found ...</td>
      <td>4</td>
    </tr>
    <tr>
      <th>2012</th>
      <td>[Gangnam Style (강남스타일) -- PSY, Somebody That I...</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2013</th>
      <td>[Roar -- Katy Perry, Wrecking Ball -- Miley Cy...</td>
      <td>5</td>
    </tr>
    <tr>
      <th>2014</th>
      <td>[Lose Yourself -- Eminem, I Got You - 1964 Sma...</td>
      <td>4</td>
    </tr>
    <tr>
      <th>2015</th>
      <td>[Cups - Movie Version -- Anna Kendrick, Unity ...</td>
      <td>4</td>
    </tr>
    <tr>
      <th>2016</th>
      <td>[Chill Jazz -- Simon Leonard Thorpe, Ghostbust...</td>
      <td>10</td>
    </tr>
    <tr>
      <th>2017</th>
      <td>[New Rules -- Dua Lipa, The Other Side -- Hugh...</td>
      <td>14</td>
    </tr>
    <tr>
      <th>2018</th>
      <td>[Solo (feat. Demi Lovato) -- Clean Bandit, We ...</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2019</th>
      <td>[We Play All Night Long -- Norris Nuts, Viens ...</td>
      <td>14</td>
    </tr>
    <tr>
      <th>2020</th>
      <td>[All Norris Nuts Songs About Themselves -- Nor...</td>
      <td>10</td>
    </tr>
    <tr>
      <th>2021</th>
      <td>[Stay Shrimpy -- Norris Nuts, Monster -- YOASO...</td>
      <td>14</td>
    </tr>
    <tr>
      <th>2022</th>
      <td>[Don't Rain on My Parade -- Lea Michele, Laiss...</td>
      <td>3</td>
    </tr>
    <tr>
      <th>2023</th>
      <td>[10:35 -- Tiësto, exes -- Tate McRae, Houdini ...</td>
      <td>5</td>
    </tr>
    <tr>
      <th>2024</th>
      <td>[Houdini -- Eminem, Eating the Cats (Donald Tr...</td>
      <td>5</td>
    </tr>
  </tbody>
</table>
</div>


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/thorwhalen/sung",
    "name": "sung",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": "Thor Whalen",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/e7/d6/f3e2a42a0d6695aef9a56fbd440968ef2520a0275085a531039e2e57ab4d/sung-0.0.8.tar.gz",
    "platform": "any",
    "description": "# sung\n\nMusic data access. Mainly sources from spotify and wikipedia.\n\n\n# Install\n\nTo install:\t```pip install sung```\n\nFor most tools, you'll also need a spotify\n\n```\nexport SPOTIFY_API_CLIENT_ID=\"your_api_client_id\"\nexport SPOTIFY_API_CLIENT_SECRET=\"your_api_client_secrete\"\nexport SPOTIPY_REDIRECT_URI=\"http://localhost:8000/callback\"\nexport SPOTIPY_CLIENT_ID=\"$SPOTIFY_API_CLIENT_ID\"\nexport SPOTIPY_CLIENT_SECRET=\"$SPOTIFY_API_CLIENT_SECRET\"\n```\n\n## Spotify API credentials?\n\nTo obtain Spotify API credentials, follow these steps:\n\t1.\tCreate a Spotify Developer Account:\n\t\u2022\tVisit the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/).\n\t\u2022\tLog in with your Spotify account or create a new one.\n\t2.\tRegister a New Application:\n\t\u2022\tClick on \u201cCreate an App.\u201d\n\t\u2022\tProvide an App Name and App Description.\n\t\u2022\tAgree to the Developer Terms of Service.\n\t\u2022\tClick \u201cCreate.\u201d\n\t3.\tRetrieve Client ID and Client Secret:\n\t\u2022\tAfter creating the app, you\u2019ll be directed to the app\u2019s dashboard.\n\t\u2022\tHere, you\u2019ll find your Client ID and Client Secret.\n\t\u2022\tKeep these credentials secure; they are essential for API authentication.\n\t4.\tSet Redirect URIs (if applicable):\n\t\u2022\tIn your app settings, click \u201cEdit Settings.\u201d\n\t\u2022\tUnder \u201cRedirect URIs,\u201d add the URIs where Spotify should redirect after authentication.\n\t\u2022\tThis is crucial for certain authorization flows.\n\nFor detailed information on authorization flows and using your credentials, refer to \n[Spotify\u2019s Authorization Guide](https://developer.spotify.com/documentation/web-api/concepts/authorization).\n\nEnsure you handle your Client Secret securely and adhere to \n[Spotify\u2019s Developer Terms of Service](https://developer.spotify.com/terms/).\n\n# Using the sung.base Module to Search Tracks and Create a Playlist\n\nIn this example, we\u2019ll:\n* Search for tracks using `Tracks.search`.\n* See the search results from the dict-like `tracks` instance\n* Display the search results in a pandas DataFrame.\n* Create a playlist called \"my_test_playlist\" with the selected tracks.\n* Get the URL of the newly created playlist.\n* Delete a playlist\n* Instantiate a `Playlist` object using a URL.\n* Look at audio features aof this playlist\n\n\n\nImport the necessary classes from the sung.base module\n\n\n```python\nfrom sung.base import Tracks, Playlist\n```\n\nSearch for tracks with the query 'Love', limiting the results to 7\nThis will return a Tracks object containing the search results\n\n\n```python\ntracks = Tracks.search(query='Love', limit=7)\n```\n\n```\nlist(tracks)\n```\n\n\n    ['1vrd6UOGamcKNGnSHJQlSt',\n     '3CeCwYWvdfXbZLXFhBrbnf',\n     '1dGr1c8CrMLDpV6mPbImSI',\n     '0u2P5u6lvoDfwTYjAADbn4',\n     '6nGeLlakfzlBcFdZXteDq7',\n     '6dBUzqjtbnIa1TwYbyw5CM',\n     '7hR22TOX3RorxJPcsz5Wbo']\n\n\nYou can also make a `tracks` object by passing a list of track IDs or urls\n\n\n```python\ntrack_ids = [\n    '1vrd6UOGamcKNGnSHJQlSt',\n    '3CeCwYWvdfXbZLXFhBrbnf',\n    '1dGr1c8CrMLDpV6mPbImSI',\n    '0u2P5u6lvoDfwTYjAADbn4',\n    'https://open.spotify.com/track/6nGeLlakfzlBcFdZXteDq7',  # url\n    'https://open.spotify.com/track/6dBUzqjtbnIa1TwYbyw5CM',   # url\n    'spotify:track:7hR22TOX3RorxJPcsz5Wbo',  # uri\n]\n\ntracks = Tracks(track_ids)\n```\n\n`tracks` is a `Mapping` (that means \"dict-like\"), so you can do what you do with dicts...\n\nLike listing the tracks' keys (IDs)\n\n\n```python\nlist(tracks)\n```\n\n\n    ['1vrd6UOGamcKNGnSHJQlSt',\n     '3CeCwYWvdfXbZLXFhBrbnf',\n     '1dGr1c8CrMLDpV6mPbImSI',\n     '0u2P5u6lvoDfwTYjAADbn4',\n     '6nGeLlakfzlBcFdZXteDq7',\n     '6dBUzqjtbnIa1TwYbyw5CM',\n     '7hR22TOX3RorxJPcsz5Wbo']\n\n\n\nLike Accessing the value of a track for a given key. \nThe value is a bunch of metadata about the track.\n\n\n```python\ntrack_metadata = tracks['1dGr1c8CrMLDpV6mPbImSI']  # get metadata of track via it's id\nassert isinstance(track_metadata, dict)\nsorted(track_metadata)\n```\n\n\n\n    ['album',\n     'artists',\n     'available_markets',\n     'disc_number',\n     'duration_ms',\n     'explicit',\n     'external_ids',\n     'external_urls',\n     'href',\n     'id',\n     'is_local',\n     'name',\n     'popularity',\n     'preview_url',\n     'track_number',\n     'type',\n     'uri']\n\n\nBut we also have extras over normal dicts. \n\nWe can get metadata of a track via it's index:\n\n\n```python\ntrack_metadata = tracks[2]  # get metadata of track via it's id\n```\n\nWe can get a sublist of track metadatas from a list of ids.\n\n```python\nlist_of_track_metadatas = tracks[['6dBUzqjtbnIa1TwYbyw5CM', '1vrd6UOGamcKNGnSHJQlSt']]  # get metadata of tracks via a list of ids\n```\n\nWe can also get a sublist using slicing.\n\n```python\nlist_of_track_metadatas = tracks[2:4]  # get metadata of tracks via a slice of ids\n```\n\n\n## Display the search results in a pandas DataFrame\n\nThe dataframe method converts the track metadata into a DataFrame for easy viewing.\n\n(Note, you can also use the tracks.dataframe(keys, front_columns=...) to retrieve a data table with more control.)\n\n\nIf you have `pandas` installed, you can get the meta data as a table (dataframe).\n\n```python\ntracks.data\n```\n\n\n<div>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>name</th>\n      <th>duration_ms</th>\n      <th>popularity</th>\n      <th>explicit</th>\n      <th>id</th>\n      <th>album</th>\n      <th>artists</th>\n      <th>available_markets</th>\n      <th>disc_number</th>\n      <th>external_ids</th>\n      <th>external_urls</th>\n      <th>href</th>\n      <th>is_local</th>\n      <th>preview_url</th>\n      <th>track_number</th>\n      <th>type</th>\n      <th>uri</th>\n    </tr>\n    <tr>\n      <th>id</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>1vrd6UOGamcKNGnSHJQlSt</th>\n      <td>Love Story</td>\n      <td>235266</td>\n      <td>62</td>\n      <td>False</td>\n      <td>1vrd6UOGamcKNGnSHJQlSt</td>\n      <td>{'album_type': 'album', 'artists': [{'external...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[CA, US]</td>\n      <td>1</td>\n      <td>{'isrc': 'USCJY0803275'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/1v...</td>\n      <td>https://api.spotify.com/v1/tracks/1vrd6UOGamcK...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/7bc39c6033766fc8...</td>\n      <td>3</td>\n      <td>track</td>\n      <td>spotify:track:1vrd6UOGamcKNGnSHJQlSt</td>\n    </tr>\n    <tr>\n      <th>3CeCwYWvdfXbZLXFhBrbnf</th>\n      <td>Love Story (Taylor\u2019s Version)</td>\n      <td>235766</td>\n      <td>76</td>\n      <td>False</td>\n      <td>3CeCwYWvdfXbZLXFhBrbnf</td>\n      <td>{'album_type': 'single', 'artists': [{'externa...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUG12100342'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/3C...</td>\n      <td>https://api.spotify.com/v1/tracks/3CeCwYWvdfXb...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/b2c1ed4794591a62...</td>\n      <td>1</td>\n      <td>track</td>\n      <td>spotify:track:3CeCwYWvdfXbZLXFhBrbnf</td>\n    </tr>\n    <tr>\n      <th>1dGr1c8CrMLDpV6mPbImSI</th>\n      <td>Lover</td>\n      <td>221306</td>\n      <td>84</td>\n      <td>False</td>\n      <td>1dGr1c8CrMLDpV6mPbImSI</td>\n      <td>{'album_type': 'album', 'artists': [{'external...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUG11901473'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/1d...</td>\n      <td>https://api.spotify.com/v1/tracks/1dGr1c8CrMLD...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/aad996e106de5278...</td>\n      <td>3</td>\n      <td>track</td>\n      <td>spotify:track:1dGr1c8CrMLDpV6mPbImSI</td>\n    </tr>\n    <tr>\n      <th>0u2P5u6lvoDfwTYjAADbn4</th>\n      <td>lovely (with Khalid)</td>\n      <td>200185</td>\n      <td>86</td>\n      <td>False</td>\n      <td>0u2P5u6lvoDfwTYjAADbn4</td>\n      <td>{'album_type': 'single', 'artists': [{'externa...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUM71804190'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/0u...</td>\n      <td>https://api.spotify.com/v1/tracks/0u2P5u6lvoDf...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/18b3cbbad11e488c...</td>\n      <td>1</td>\n      <td>track</td>\n      <td>spotify:track:0u2P5u6lvoDfwTYjAADbn4</td>\n    </tr>\n    <tr>\n      <th>6nGeLlakfzlBcFdZXteDq7</th>\n      <td>Love Story</td>\n      <td>316280</td>\n      <td>74</td>\n      <td>False</td>\n      <td>6nGeLlakfzlBcFdZXteDq7</td>\n      <td>{'album_type': 'album', 'artists': [{'external...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'FRUM71400048'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/6n...</td>\n      <td>https://api.spotify.com/v1/tracks/6nGeLlakfzlB...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/677f771b1fc30024...</td>\n      <td>3</td>\n      <td>track</td>\n      <td>spotify:track:6nGeLlakfzlBcFdZXteDq7</td>\n    </tr>\n    <tr>\n      <th>6dBUzqjtbnIa1TwYbyw5CM</th>\n      <td>Lovers Rock</td>\n      <td>213920</td>\n      <td>85</td>\n      <td>False</td>\n      <td>6dBUzqjtbnIa1TwYbyw5CM</td>\n      <td>{'album_type': 'album', 'artists': [{'external...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'USHM21438143'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/6d...</td>\n      <td>https://api.spotify.com/v1/tracks/6dBUzqjtbnIa...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/922a42db5aa8f8d3...</td>\n      <td>9</td>\n      <td>track</td>\n      <td>spotify:track:6dBUzqjtbnIa1TwYbyw5CM</td>\n    </tr>\n    <tr>\n      <th>7hR22TOX3RorxJPcsz5Wbo</th>\n      <td>Love Somebody</td>\n      <td>204828</td>\n      <td>86</td>\n      <td>False</td>\n      <td>7hR22TOX3RorxJPcsz5Wbo</td>\n      <td>{'album_type': 'single', 'artists': [{'externa...</td>\n      <td>[{'external_urls': {'spotify': 'https://open.s...</td>\n      <td>[AR, AU, AT, BE, BO, BR, BG, CA, CL, CO, CR, C...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUG12406387'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/7h...</td>\n      <td>https://api.spotify.com/v1/tracks/7hR22TOX3Ror...</td>\n      <td>False</td>\n      <td>https://p.scdn.co/mp3-preview/00b94e332ed40625...</td>\n      <td>1</td>\n      <td>track</td>\n      <td>spotify:track:7hR22TOX3RorxJPcsz5Wbo</td>\n    </tr>\n  </tbody>\n</table>\n</div>\n\n\n\n## Make a playlist\n\nCreate a new playlist named 'my_test_playlist' with the selected tracks\nThe create_from_track_list class method creates a new playlist with the given tracks\n\n\n```python\nplaylist = Playlist.create_from_track_list(\n    track_list=selected_track_ids,\n    playlist_name='my_test_playlist'\n)\nprint(f\"\\nPlaylist '{playlist.playlist_id}' created successfully.\")\n\n```\n\n    \n    Playlist '7BZcFvIWUnVzvZ5wpVt9cD' created successfully.\n\n\nGet the playlist URL of the newly created playlist (go check it out!)\n\n\n```python\nplaylist.playlist_url\n```\n\n\n    'https://open.spotify.com/playlist/7BZcFvIWUnVzvZ5wpVt9cD'\n\n\n\n## Delete a playlist\n\nWe purposely tried to make deleting a playlist not as easy as the other actions. \nSo we didn't attach a delete method to the playlist instance, but put this in a \nseparate function you have to import. \nAlso, we made that function verbose, and asking for confirmation by default. \n(But there's arguments to control that, so you can use `functools.partial` to \nmake your own cowboy (not speaking and not asking for permission) version).\n\n\n```python\nfrom sung import delete_playlist\n\ndelete_playlist(playlist.playlist_id)\n```\n\nInstantiate a Playlist object using a URL.\nThis allows you to interact with the playlist, such as accessing its tracks.\n\n\n```python\ntop50_global_url = 'https://open.spotify.com/playlist/37i9dQZEVXbMDoHDwVN2tF?si=d6e0c7bc8f59473b'\ntop50_playlist = Playlist(top50_global_url)\ndf = top50_playlist.data\ndf['first_artist'] = df['artists'].apply(lambda x: x[0]['name'])\ndf['name_and_first_artist'] = df['name'] + ' - ' + df['first_artist']\ntop_5_tracks = top50_playlist.data.iloc[:5].name_and_first_artist\ntop_5_tracks\n```\n\n\n    id\n    2plbrEY59IikOBgBGLjaoe          Die With A Smile - Lady Gaga\n    5vNRhkKd0yEAg8suGBpjeY                           APT. - ROS\u00c9\n    6dOtVTDdiauQNBQEDOtlAB    BIRDS OF A FEATHER - Billie Eilish\n    7ne4VBA60CxGM75vw0EYad        That\u2019s So True - Gracie Abrams\n    7tI8dRuH2Yc6RuoTjxo4dU                           Who - Jimin\n    Name: name_and_first_artist, dtype: object\n\n\n## Audio features\n\n\n```python\nimport pandas as pd\n\nprint(f\"{top50_playlist.audio_features_df.shape=}\")\ntop50_playlist.audio_features_df.iloc[0]\n\n```\n\n    top50_playlist.audio_features_df.shape=(50, 17)\n\n\n\n\n\n    danceability                                                    0.521\n    energy                                                          0.592\n    key                                                                 6\n    loudness                                                       -7.777\n    mode                                                                0\n    speechiness                                                    0.0304\n    acousticness                                                    0.308\n    instrumentalness                                                  0.0\n    liveness                                                        0.122\n    valence                                                         0.535\n    tempo                                                         157.969\n    type                                                   audio_features\n    uri                              spotify:track:2plbrEY59IikOBgBGLjaoe\n    track_href          https://api.spotify.com/v1/tracks/2plbrEY59Iik...\n    analysis_url        https://api.spotify.com/v1/audio-analysis/2plb...\n    duration_ms                                                    251668\n    time_signature                                                      3\n    Name: 2plbrEY59IikOBgBGLjaoe, dtype: object\n\n\n\n\n```python\nimport seaborn as sns\nfrom matplotlib import pyplot as plt\n\ndf = pd.merge(top50_playlist.data, top50_playlist.audio_features_df, left_index=True, right_index=True)\n# scatter plot with danceability and energy, colored by popularity, with size as loudness\nsns.scatterplot(data=df, x='danceability', y='energy', hue='popularity', size='loudness')\n\n# Move the legend outside the plot\nplt.legend(bbox_to_anchor=(1.05, 1), loc='upper left');\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/sung_demo_files/sung_demo_31_0.png)\n    \n\n\n\n```python\nimport seaborn as sns\n\nsns.pairplot(top50_playlist.audio_features_df[['danceability', 'energy', 'loudness', 'speechiness', 'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo']])\n```\n\n\n\n\n    <seaborn.axisgrid.PairGrid at 0x10ac069b0>\n\n\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/sung_demo_files/sung_demo_32_1.png)\n    \n\n\n## Audio analysis\n\n\n```python\naudio_analysis = top50_playlist.audio_analysis(next(iter(top50_playlist)))\n```\n\n\n```python\ntype(audio_analysis)\n```\n\n\n\n\n    dict\n\n\n\n\n```python\nlist(audio_analysis)\n```\n\n\n\n\n    ['meta', 'track', 'bars', 'beats', 'sections', 'segments', 'tatums']\n\n\n\n\n```python\naudio_analysis['meta']\n```\n\n\n\n\n    {'analyzer_version': '4.0.0',\n     'platform': 'Linux',\n     'detailed_status': 'OK',\n     'status_code': 0,\n     'timestamp': 1723785476,\n     'analysis_time': 5.78793,\n     'input_process': 'libvorbisfile L+R 44100->22050'}\n\n\n\n\n```python\naudio_analysis['track']\n```\n\n\n    {'num_samples': 5549270,\n     'duration': 251.66757,\n     'sample_md5': '',\n     'offset_seconds': 0,\n     'window_seconds': 0,\n     'analysis_sample_rate': 22050,\n     'analysis_channels': 1,\n     'end_of_fade_in': 0.2034,\n     'start_of_fade_out': 241.98096,\n     'loudness': -7.863,\n     'tempo': 158.005,\n     'tempo_confidence': 0.501,\n     'time_signature': 3,\n     'time_signature_confidence': 1.0,\n     'key': 6,\n     'key_confidence': 0.253,\n     'mode': 0,\n     'mode_confidence': 0.452,\n     'codestring': 'eJxVmgcC...twbhuw==',\n     'code_version': 3.15,\n     'echoprintstring': '...',\n     'echoprint_version': 4.12,\n     'synchstring': 'eJxVWYmR6zoMa8UlSDx09N...EsF7ZvNGhvn5DzGSYaU=',\n     'synch_version': 1.0,\n     'rhythmstring': 'eJxdnAmSWzkSQ6..._8hOM4=',\n     'rhythm_version': 1.0}\n\n\n\n\n```python\nfrom lkj import truncate_dict_values\n\nprint(f\"{len(audio_analysis['bars'])=})\")\ntruncate_dict_values(audio_analysis['bars'])\n```\n\n    len(audio_analysis['bars'])=211)\n\n\n\n\n\n    [{'start': 1.36936, 'duration': 1.1373, 'confidence': 0.506},\n     {'start': 2.50666, 'duration': 1.14286, 'confidence': 0.037}]\n\n\n\n\n```python\nprint(f\"{len(audio_analysis['beats'])=})\")\ntruncate_dict_values(audio_analysis['beats'])\n```\n\n    len(audio_analysis['beats'])=639)\n\n\n\n\n\n    [{'start': 0.598, 'duration': 0.39454, 'confidence': 0.786},\n     {'start': 0.99254, 'duration': 0.37682, 'confidence': 0.461}]\n\n\n\n\n```python\nprint(f\"{len(audio_analysis['sections'])=})\")\ntruncate_dict_values(audio_analysis['sections'])\n```\n\n    len(audio_analysis['sections'])=10)\n\n\n\n\n    [{'start': 0.0,\n      'duration': 9.72348,\n      'confidence': 1.0,\n      'loudness': -22.269,\n      'tempo': 158.348,\n      'tempo_confidence': 0.353,\n      'key': 1,\n      'key_confidence': 0.03,\n      'mode': 0,\n      'mode_confidence': 0.567,\n      'time_signature': 3,\n      'time_signature_confidence': 1.0},\n     {'start': 9.72348,\n      'duration': 29.24311,\n      'confidence': 0.606,\n      'loudness': -11.712,\n      'tempo': 158.114,\n      'tempo_confidence': 0.364,\n      'key': 9,\n      'key_confidence': 0.217,\n      'mode': 1,\n      'mode_confidence': 0.472,\n      'time_signature': 3,\n      'time_signature_confidence': 1.0}]\n\n\n\n\n```python\nprint(f\"{len(audio_analysis['segments'])=})\")\ntruncate_dict_values(audio_analysis['segments'])\n```\n\n    len(audio_analysis['segments'])=780)\n\n\n\n\n\n    [{'start': 0.0,\n      'duration': 0.2034,\n      'confidence': 0.0,\n      'loudness_start': -60.0,\n      'loudness_max_time': 0.0,\n      'loudness_max': -60.0,\n      'loudness_end': 0.0,\n      'pitches': [1.0, 1.0],\n      'timbre': [0.0, 171.13]},\n     {'start': 0.2034,\n      'duration': 0.41234,\n      'confidence': 1.0,\n      'loudness_start': -60.0,\n      'loudness_max_time': 0.05445,\n      'loudness_max': -22.196,\n      'loudness_end': 0.0,\n      'pitches': [0.082, 0.554],\n      'timbre': [33.758, 53.096]}]\n\n\n\n\n```python\nprint(f\"{len(audio_analysis['tatums'])=})\")\ntruncate_dict_values(audio_analysis['tatums'])\n```\n\n    len(audio_analysis['tatums'])=1278)\n\n\n\n\n\n    [{'start': 0.598, 'duration': 0.19727, 'confidence': 0.786},\n     {'start': 0.79527, 'duration': 0.19727, 'confidence': 0.786}]\n\n\n\n\n```python\nfrom lkj import truncate_dict_values\n\ntruncate_dict_values(audio_analysis, max_list_size=2)\n```\n\n\n    {'meta': {'analyzer_version': '4.0.0',\n      'platform': 'Linux',\n      'detailed_status': 'OK',\n      'status_code': 0,\n      'timestamp': 1476616359,\n      'analysis_time': 109.6869,\n      'input_process': 'libvorbisfile L+R 44100->22050'},\n     'track': {'num_samples': 15594936,\n      'duration': 707.25336,\n      'sample_md5': '',\n      'offset_seconds': 0,\n      'window_seconds': 0,\n      'analysis_sample_rate': 22050,\n      'analysis_channels': 1,\n      'end_of_fade_in': 2.82703,\n      'start_of_fade_out': 693.6381,\n      'loudness': -10.355,\n      'tempo': 106.396,\n      'tempo_confidence': 0.595,\n      'time_signature': 4,\n      'time_signature_confidence': 0.904,\n      'key': 5,\n      'key_confidence': 0.049,\n      'mode': 0,\n      'mode_confidence': 0.228,\n      'codestring': 'eJw1nQmS5LqOBK9SRxB38v4X63BHtv2...y2bmBs1qBYvtiECKLDlx_oH4Y3DGg==',\n      'code_version': 3.15,\n      'echoprintstring': 'eJzcnQ2u7DhzZLckUaRILkf82_8S5oT...av23MzLxruBTa5AgsAdSL_-A1nrtTE=',\n      'echoprint_version': 4.12,\n      'synchstring': 'eJx9mAuS5DgIRK_iI1h_6_4XW_IlclV...OPN79PfjNMgH2A-QVgPFZR_AHMBU_o=',\n      'synch_version': 1.0,\n      'rhythmstring': 'eJyNnVmSJEmOQ68SR9B9uf_FxogHqme...EXgaMRt5h7-gy4yclWmWjb8_wC55QRT',\n      'rhythm_version': 1.0},\n     'bars': [{'start': 2.64511, 'duration': 2.23768, 'confidence': 0.825},\n      {'start': 4.88279, 'duration': 2.16451, 'confidence': 0.352}],\n     'beats': [{'start': 0.9181, 'duration': 0.58698, 'confidence': 0.683},\n      {'start': 1.50508, 'duration': 0.57369, 'confidence': 0.572}],\n     'sections': [{'start': 0.0,\n       'duration': 11.51788,\n       'confidence': 1.0,\n       'loudness': -20.409,\n       'tempo': 108.121,\n       'tempo_confidence': 0.728,\n       'key': 6,\n       'key_confidence': 0.162,\n       'mode': 1,\n       'mode_confidence': 0.478,\n       'time_signature': 4,\n       'time_signature_confidence': 0.1},\n      {'start': 11.51788,\n       'duration': 30.61314,\n       'confidence': 0.731,\n       'loudness': -12.171,\n       'tempo': 107.882,\n       'tempo_confidence': 0.499,\n       'key': 10,\n       'key_confidence': 0.429,\n       'mode': 0,\n       'mode_confidence': 0.387,\n       'time_signature': 4,\n       'time_signature_confidence': 0.467}],\n     'segments': [{'start': 0.0,\n       'duration': 0.60957,\n       'confidence': 0.0,\n       'loudness_start': -60.0,\n       'loudness_max_time': 0.5863,\n       'loudness_max': -56.103,\n       'loudness_end': 0.0,\n       'pitches': [0.8, 0.511],\n       'timbre': [0.116, 169.016]},\n      {'start': 0.60957,\n       'duration': 0.60376,\n       'confidence': 1.0,\n       'loudness_start': -55.895,\n       'loudness_max_time': 0.03504,\n       'loudness_max': -36.652,\n       'loudness_end': 0.0,\n       'pitches': [0.434, 0.38],\n       'timbre': [13.111, 157.189]}],\n     'tatums': [{'start': 0.9181, 'duration': 0.29349, 'confidence': 0.683},\n      {'start': 1.21159, 'duration': 0.29349, 'confidence': 0.683}]}\n\n\n\n\n# Analyze a playlist\n\n\n```python\nfrom sung import TracksAnalysis, ensure_playlist_id\n\n```\n\n## Initialize the Class with a Playlist ID\n\n\n```python\n# Let's analyze my daughter's playlist...\n\nplaylist = \"https://open.spotify.com/playlist/4nEeS47ineUShHK2iAVeO0?si=be16c62b664f43f3\"\n\nta = TracksAnalysis(playlist)\n```\n\nNote that, alternatively, if you already have a dataframe, you can just give `TracksAnalysis` that.\nNote that it must have been prepared by `TracksAnalysis`, or at least satisfy the dataframe conditions on the columns. \n\n\n```python\n# import pandas as pd\n# df = pd.read_excel(\"~/Dropbox/_odata/ai_contexts/misc/music/encore_playlist.xlsx\")\n# ta = TracksAnalysis(df)\n```\n\n## Access the Processed Dataframe\n\n\n```python\nta.df.head()\n\n```\n\n\n\n<div>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>name</th>\n      <th>first_artist</th>\n      <th>duration_ms</th>\n      <th>popularity</th>\n      <th>explicit</th>\n      <th>album_release_date</th>\n      <th>album_release_year</th>\n      <th>added_at_date</th>\n      <th>url</th>\n      <th>first_letter</th>\n      <th>...</th>\n      <th>disc_number</th>\n      <th>external_ids</th>\n      <th>external_urls</th>\n      <th>href</th>\n      <th>is_local</th>\n      <th>track_number</th>\n      <th>type</th>\n      <th>uri</th>\n      <th>preview_url</th>\n      <th>added_at_datetime</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>181</th>\n      <td>Love The Way You Lie</td>\n      <td>Eminem</td>\n      <td>263373</td>\n      <td>47</td>\n      <td>False</td>\n      <td>2010-06-18</td>\n      <td>2010</td>\n      <td>2024-11-06</td>\n      <td>https://open.spotify.com/track/4k5Rb51qsUSMFg6...</td>\n      <td>L</td>\n      <td>...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUM71015443'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/4k...</td>\n      <td>https://api.spotify.com/v1/tracks/4k5Rb51qsUSM...</td>\n      <td>False</td>\n      <td>15</td>\n      <td>track</td>\n      <td>spotify:track:4k5Rb51qsUSMFg6oFdVC48</td>\n      <td>NaN</td>\n      <td>2024-11-06T16:01:38Z</td>\n    </tr>\n    <tr>\n      <th>180</th>\n      <td>Without Me</td>\n      <td>Eminem</td>\n      <td>290120</td>\n      <td>46</td>\n      <td>False</td>\n      <td>2002-05-26</td>\n      <td>2002</td>\n      <td>2024-11-03</td>\n      <td>https://open.spotify.com/track/3Q0kSmKpkffn4aW...</td>\n      <td>W</td>\n      <td>...</td>\n      <td>1</td>\n      <td>{'isrc': 'USIR10211127'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/3Q...</td>\n      <td>https://api.spotify.com/v1/tracks/3Q0kSmKpkffn...</td>\n      <td>False</td>\n      <td>10</td>\n      <td>track</td>\n      <td>spotify:track:3Q0kSmKpkffn4aWkYkWwet</td>\n      <td>NaN</td>\n      <td>2024-11-03T11:27:58Z</td>\n    </tr>\n    <tr>\n      <th>179</th>\n      <td>Lose Yourself</td>\n      <td>Eminem</td>\n      <td>320573</td>\n      <td>50</td>\n      <td>False</td>\n      <td>2014-11-24</td>\n      <td>2014</td>\n      <td>2024-11-03</td>\n      <td>https://open.spotify.com/track/2jvHb9SHJDi8Ugk...</td>\n      <td>L</td>\n      <td>...</td>\n      <td>2</td>\n      <td>{'isrc': 'USIR10211570'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/2j...</td>\n      <td>https://api.spotify.com/v1/tracks/2jvHb9SHJDi8...</td>\n      <td>False</td>\n      <td>3</td>\n      <td>track</td>\n      <td>spotify:track:2jvHb9SHJDi8Ugky7tUzUb</td>\n      <td>NaN</td>\n      <td>2024-11-03T11:27:34Z</td>\n    </tr>\n    <tr>\n      <th>178</th>\n      <td>The Real Slim Shady</td>\n      <td>Eminem</td>\n      <td>283693</td>\n      <td>54</td>\n      <td>False</td>\n      <td>2005-12-06</td>\n      <td>2005</td>\n      <td>2024-11-03</td>\n      <td>https://open.spotify.com/track/2WXUcFnJPPATncU...</td>\n      <td>T</td>\n      <td>...</td>\n      <td>1</td>\n      <td>{'isrc': 'USIR10000449'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/2W...</td>\n      <td>https://api.spotify.com/v1/tracks/2WXUcFnJPPAT...</td>\n      <td>False</td>\n      <td>9</td>\n      <td>track</td>\n      <td>spotify:track:2WXUcFnJPPATncUkPYC54v</td>\n      <td>NaN</td>\n      <td>2024-11-03T11:27:15Z</td>\n    </tr>\n    <tr>\n      <th>177</th>\n      <td>Houdini</td>\n      <td>Eminem</td>\n      <td>227239</td>\n      <td>57</td>\n      <td>False</td>\n      <td>2024-05-30</td>\n      <td>2024</td>\n      <td>2024-11-03</td>\n      <td>https://open.spotify.com/track/6vw2M02LT3otGUo...</td>\n      <td>H</td>\n      <td>...</td>\n      <td>1</td>\n      <td>{'isrc': 'USUG12403399'}</td>\n      <td>{'spotify': 'https://open.spotify.com/track/6v...</td>\n      <td>https://api.spotify.com/v1/tracks/6vw2M02LT3ot...</td>\n      <td>False</td>\n      <td>1</td>\n      <td>track</td>\n      <td>spotify:track:6vw2M02LT3otGUoK4ZqHwx</td>\n      <td>NaN</td>\n      <td>2024-11-03T11:21:18Z</td>\n    </tr>\n  </tbody>\n</table>\n<p>5 rows \u00d7 25 columns</p>\n</div>\n\n\n\n## Perform Analyses\n\n\n```python\nprint(f\"Number of songs: {ta.number_of_songs}\")\nprint(f\"Number of unique names: {ta.number_of_unique_names}\")\n```\n\n    Number of songs: 182\n    Number of unique names: 178\n\n\n### Print Duplicates\n\n\n```python\nta.print_duplicates()\n```\n\n    \n    ### Duplicates\n    |                              |   count |\n    |:-----------------------------|--------:|\n    | Houdini                      |       2 |\n    | Anything You Can Do          |       2 |\n    | Somebody That I Used to Know |       2 |\n    | The Bare Necessities         |       2 |\n\n\n### Print Most Popular Songs\n\n\n```python\nta.print_most_popular_songs(n=20)\n```\n\n    | name                                            | first_artist      |   popularity |\n    |:------------------------------------------------|:------------------|-------------:|\n    | Espresso                                        | Sabrina Carpenter |           90 |\n    | exes                                            | Tate McRae        |           83 |\n    | Sweet Dreams (Are Made of This) - 2005 Remaster | Eurythmics        |           83 |\n    | Zombie                                          | The Cranberries   |           82 |\n    | Here Comes The Sun - Remastered 2009            | The Beatles       |           82 |\n    | Before You Go                                   | Lewis Capaldi     |           81 |\n    | bad guy                                         | Billie Eilish     |           81 |\n    | ...Baby One More Time                           | Britney Spears    |           81 |\n    | Tainted Love                                    | Soft Cell         |           79 |\n    | Wrecking Ball                                   | Miley Cyrus       |           78 |\n    | New Rules                                       | Dua Lipa          |           78 |\n    | Rolling in the Deep                             | Adele             |           77 |\n    | Kings & Queens                                  | Ava Max           |           77 |\n    | Easy On Me                                      | Adele             |           77 |\n    | Roar                                            | Katy Perry        |           77 |\n    | bellyache                                       | Billie Eilish     |           76 |\n    | Jolene                                          | Dolly Parton      |           75 |\n    | Symphony (feat. Zara Larsson)                   | Clean Bandit      |           75 |\n    | Nice For What                                   | Drake             |           74 |\n    | bury a friend                                   | Billie Eilish     |           74 |\n\n\n### Print Top Artists\n\n\n```python\nta.print_top_artists(n=25)\n```\n\n    | first_artist       |   count |\n    |:-------------------|--------:|\n    | Dua Lipa           |       6 |\n    | Eminem             |       5 |\n    | Jacob Collier      |       4 |\n    | Norris Nuts        |       4 |\n    | The Beatles        |       4 |\n    | Hugh Jackman       |       4 |\n    | Music Together     |       3 |\n    | Leonard Bernstein  |       3 |\n    | Julie Andrews      |       3 |\n    | Walk off the Earth |       3 |\n    | John Williams      |       3 |\n    | Billie Eilish      |       3 |\n    | Anna Kendrick      |       3 |\n    | Zac Efron          |       2 |\n    | Clean Bandit       |       2 |\n    | Adele              |       2 |\n    | Shakira            |       2 |\n    | Stromae            |       2 |\n    | Michael Jackson    |       2 |\n    | Lin-Manuel Miranda |       2 |\n    | Caravan Palace     |       2 |\n    | Queen              |       2 |\n    | Ynairaly Simo      |       2 |\n    | \u00c9dith Piaf         |       2 |\n    | Dolly Parton       |       1 |\n\n\n### Plot Number of Songs per Release Year\n\n\n```python\nta.plot_songs_per_year()\n```\n\n    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 44053 (\\N{HANGUL SYLLABLE GANG}) missing from font(s) DejaVu Sans.\n      fig.canvas.print_figure(bytes_io, **kw)\n    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 45224 (\\N{HANGUL SYLLABLE NAM}) missing from font(s) DejaVu Sans.\n      fig.canvas.print_figure(bytes_io, **kw)\n    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 49828 (\\N{HANGUL SYLLABLE SEU}) missing from font(s) DejaVu Sans.\n      fig.canvas.print_figure(bytes_io, **kw)\n    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 53440 (\\N{HANGUL SYLLABLE TA}) missing from font(s) DejaVu Sans.\n      fig.canvas.print_figure(bytes_io, **kw)\n    /Users/thorwhalen/.pyenv/versions/3.10.13/envs/p10/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 51068 (\\N{HANGUL SYLLABLE IL}) missing from font(s) DejaVu Sans.\n      fig.canvas.print_figure(bytes_io, **kw)\n\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_20_1.png)\n    \n\n\n### Plot Added Date vs. Release Date\n\n\n```python\nta.plot_added_vs_release_dates()\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_22_0.png)\n    \n\n\n\n```python\nta.plot_added_vs_release_kde()\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_23_0.png)\n    \n\n\n\n```python\nta.plot_added_vs_release_kde_boundary()\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_24_0.png)\n    \n\n\n### Plot First Letter Distribution\n\n\n```python\nta.plot_first_letter_distribution(sort_by='lexicographical')\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_26_0.png)\n    \n\n\n\n```python\nta.plot_first_letter_distribution(sort_by='count')\n```\n\n\n    \n![png](https://raw.githubusercontent.com/thorwhalen/sung/main/misc/playlist_analysis_files/playlist_analysis_27_0.png)\n    \n\n\n### Print Top Tracks by Starting Letter\n\n\n```python\nta.print_top_names_by_letter(n=5)\n```\n\n    L (5 tracks):\n      - (74) Levitating\n      - (73) Livin' la Vida Loca\n      - (63) Lucy In The Sky With Diamonds - Remastered 2009\n      - (58) La Vie en rose\n      - (50) Lose Yourself\n    W (5 tracks):\n      - (78) Wrecking Ball\n      - (71) We Don't Talk About Bruno\n      - (69) Wellerman - Sea Shanty\n      - (69) We Will Rock You - Remastered 2011\n      - (64) Wuthering Heights\n    T (5 tracks):\n      - (79) Tainted Love\n      - (74) Training Season\n      - (70) The Other Side\n      - (70) The Greatest Show\n      - (70) This Is Me\n    H (5 tracks):\n      - (82) Here Comes The Sun - Remastered 2009\n      - (74) Happy Together\n      - (57) Houdini\n      - (57) Houdini\n      - (57) Holocaust\n    S (5 tracks):\n      - (83) Sweet Dreams (Are Made of This) - 2005 Remaster\n      - (75) Symphony (feat. Zara Larsson)\n      - (74) Somebody That I Used To Know\n      - (74) Se\u00f1orita\n      - (71) Super Trouper\n    N (4 tracks):\n      - (78) New Rules\n      - (74) Nice For What\n      - (63) Night Falls\n      - (44) Non, je ne regrette rien\n    R (5 tracks):\n      - (77) Rolling in the Deep\n      - (77) Roar\n      - (70) Rewrite The Stars\n      - (59) Ring My Bell\n      - (48) Running Out Of Time\n    E (4 tracks):\n      - (90) Espresso\n      - (83) exes\n      - (77) Easy On Me\n      - (53) Eating the Cats (Donald Trump Remix)\n    A (5 tracks):\n      - (73) Ain't Nobody (Loves Me Better) (feat. Jasmine Thompson)\n      - (72) A Million Dreams\n      - (53) A Spoonful of Sugar - From \"Mary Poppins\" / Soundtrack Version\n      - (0) Anything You Can Do\n      - (29) Away We Go\n    1 (1 tracks):\n      - (19) 10:35\n    I (5 tracks):\n      - (68) I Like To Move It\n      - (66) Illusion\n      - (65) I'll Be There for You - Theme From \"Friends\"\n      - (47) It's Oh So Quiet\n      - (40) Indiana Jones Theme\n    C (5 tracks):\n      - (69) Chandelier\n      - (67) Come Alive\n      - (62) Crab Rave\n      - (53) Coconut\n      - (46) Cups - Movie Version\n    V (1 tracks):\n      - (25) Viens\n    U (1 tracks):\n      - (14) Unity\n    D (5 tracks):\n      - (72) Don't Stop Believin'\n      - (66) Dance Monkey\n      - (62) Drive My Car - Remastered 2009\n      - (53) Do-Re-Mi\n      - (41) Don't Rain on My Parade\n    M (5 tracks):\n      - (74) MIDDLE OF THE NIGHT\n      - (56) Material Girl\n      - (49) Mellow Yellow\n      - (46) Monster\n      - (36) My Baby Just Cares For Me\n    B (5 tracks):\n      - (81) Before You Go\n      - (81) bad guy\n      - (76) bellyache\n      - (74) bury a friend\n      - (67) Bad - 2012 Remaster\n    F (4 tracks):\n      - (70) From Now On\n      - (65) Friend Like Me\n      - (63) Fat Bottomed Girls - Remastered 2011\n      - (58) Fever\n    G (5 tracks):\n      - (74) Ghostbusters\n      - (73) Get Into It (Yuh)\n      - (72) Gangnam Style (\uac15\ub0a8\uc2a4\ud0c0\uc77c)\n      - (62) Get Back Up Again\n      - (59) Greased Lightnin' - From \u201cGrease\u201d\n    P (3 tracks):\n      - (64) Peaches\n      - (30) Pink Panther Theme - Remix Version\n      - (0) Papaoutai\n    Y (3 tracks):\n      - (65) You Can't Always Get What You Want\n      - (49) You Can't Stop The Beat\n      - (31) You're No Good - From 'Minions: The Rise of Gru' Soundtrack\n    Z (1 tracks):\n      - (82) Zombie\n    K (3 tracks):\n      - (77) Kings & Queens\n      - (58) Karma Chameleon\n      - (0) Kung Fu Fighting (From \"Kung Fu Panda 3\")\n    O (5 tracks):\n      - (64) Oye Como Va\n      - (43) One Of A Kind\n      - (41) On My Way\n      - (40) One More Song\n      - (0) Omg - Radio Edit\n    J (3 tracks):\n      - (75) Jolene\n      - (43) Je Me Suis Fait Tout Petit\n      - (33) Jolie coquine\n    5 (1 tracks):\n      - (30) 5:55\n    . (1 tracks):\n      - (81) ...Baby One More Time\n    \" (1 tracks):\n      - (3) \"Ellens Gesang III\", D839: Ave Maria\n\n\n\n```python\n# To print all of them, just make n really big\nta.print_top_names_by_letter(n=10_000)\n```\n\n    L (12 tracks):\n      - (74) Levitating\n      - (73) Livin' la Vida Loca\n      - (63) Lucy In The Sky With Diamonds - Remastered 2009\n      - (58) La Vie en rose\n      - (50) Lose Yourself\n      - (47) Love The Way You Lie\n      - (47) Le caf\u00e9\n      - (44) Les cit\u00e9s d'or\n      - (39) Little Boxes\n      - (35) Lost and Found\n      - (34) Lemon Boy - Acappella Version\n      - (33) Laisse aller\n    W (17 tracks):\n      - (78) Wrecking Ball\n      - (71) We Don't Talk About Bruno\n      - (69) We Will Rock You - Remastered 2011\n      - (69) Wellerman - Sea Shanty\n      - (64) Wuthering Heights\n      - (64) Who Let The Dogs Out\n      - (48) What Time Is It\n      - (46) Without Me\n      - (43) West Side Story: Act I: America\n      - (35) West Side Story: Act I: Something's Coming\n      - (34) West Side Story: Act II: I Feel Pretty\n      - (32) We the #Legends\n      - (30) We Play All Night Long\n      - (22) Winter Ducks Play on Water\n      - (6) Waka Waka (This Time for Africa) [The Official 2010 FIFA World Cup (TM) Song] (feat. Freshlyground)\n      - (0) Windy (Re-Recorded)\n      - (0) Wimoweh (Mbube)\n    T (16 tracks):\n      - (79) Tainted Love\n      - (74) Training Season\n      - (70) The Other Side\n      - (70) The Greatest Show\n      - (70) This Is Me\n      - (68) Truth Hurts\n      - (67) Try Everything\n      - (66) The Family Madrigal\n      - (57) True Colors - Film Version\n      - (56) The Magic Key\n      - (54) The Real Slim Shady\n      - (48) Time Alone With You (feat. Daniel Caesar)\n      - (37) The Bare Necessities\n      - (39) The Lonely Goatherd\n      - (37) The Bare Necessities\n      - (0) The Imperial March (Darth Vader's Theme)\n    H (8 tracks):\n      - (82) Here Comes The Sun - Remastered 2009\n      - (74) Happy Together\n      - (57) Houdini\n      - (57) Houdini\n      - (57) Holocaust\n      - (31) Here Comes The Sun (feat. dodie)\n      - (26) Hello\n      - (0) Hello Song\n    S (21 tracks):\n      - (83) Sweet Dreams (Are Made of This) - 2005 Remaster\n      - (75) Symphony (feat. Zara Larsson)\n      - (74) Se\u00f1orita\n      - (74) Somebody That I Used To Know\n      - (71) Super Trouper\n      - (70) Solo (feat. Demi Lovato)\n      - (68) Scatman (ski-ba-bop-ba-dop-bop)\n      - (68) Somewhere Over The Rainbow_What A Wonderful World\n      - (68) Surface Pressure\n      - (65) Single Ladies (Put a Ring on It)\n      - (46) Somebody That I Used to Know\n      - (46) Somebody That I Used to Know\n      - (36) Scarborough Fair / Canticle - Extended Version\n      - (36) Strawberry Fields Forever - Remastered 2009\n      - (30) Shape of You\n      - (26) Stay Shrimpy\n      - (24) Superman March - Alternate Version\n      - (24) Sing, Sing, Sing\n      - (18) Senza un perch\u00e8\n      - (0) Suite No.3 In D Major, BWV 1068: 2. Air\n      - (0) She Sells Sea Shells\n    N (4 tracks):\n      - (78) New Rules\n      - (74) Nice For What\n      - (63) Night Falls\n      - (44) Non, je ne regrette rien\n    R (8 tracks):\n      - (77) Rolling in the Deep\n      - (77) Roar\n      - (70) Rewrite The Stars\n      - (59) Ring My Bell\n      - (48) Running Out Of Time\n      - (47) Running with the Wolves - WolfWalkers Version\n      - (23) Running Outta Love (feat. Tori Kelly)\n      - (0) Ridin' in the Car\n    E (4 tracks):\n      - (90) Espresso\n      - (83) exes\n      - (77) Easy On Me\n      - (53) Eating the Cats (Donald Trump Remix)\n    A (8 tracks):\n      - (73) Ain't Nobody (Loves Me Better) (feat. Jasmine Thompson)\n      - (72) A Million Dreams\n      - (53) A Spoonful of Sugar - From \"Mary Poppins\" / Soundtrack Version\n      - (0) Anything You Can Do\n      - (29) Away We Go\n      - (28) All Norris Nuts Songs About Themselves\n      - (2) Alors On Danse - Radio Edit\n      - (0) Anything You Can Do\n    1 (1 tracks):\n      - (19) 10:35\n    I (9 tracks):\n      - (68) I Like To Move It\n      - (66) Illusion\n      - (65) I'll Be There for You - Theme From \"Friends\"\n      - (47) It's Oh So Quiet\n      - (40) Indiana Jones Theme\n      - (35) I Wan'na Be Like You (2016)\n      - (34) In My Bones (feat. Kimbra & Tank and The Bangas)\n      - (11) I Got You - 1964 Smash Version\n      - (0) It's Only A Paper Moon\n    C (8 tracks):\n      - (69) Chandelier\n      - (67) Come Alive\n      - (62) Crab Rave\n      - (53) Coconut\n      - (46) Cups - Movie Version\n      - (36) C'est de l'eau\n      - (22) Chill Jazz\n      - (0) Coco Made Me Do It\n    V (1 tracks):\n      - (25) Viens\n    U (1 tracks):\n      - (14) Unity\n    D (13 tracks):\n      - (72) Don't Stop Believin'\n      - (66) Dance Monkey\n      - (62) Drive My Car - Remastered 2009\n      - (53) Do-Re-Mi\n      - (41) Don't Rain on My Parade\n      - (38) Drop It Like It's Hot - Radio Edit\n      - (37) Do The Bartman\n      - (35) Dramophone\n      - (25) Drive My Car\n      - (11) Djevojka Sa \u010carda\u0161 Nogama\n      - (4) Do Your Ears Hang Low?\n      - (1) Dragostea Din Tei\n      - (0) Duel Of The Fates\n    M (9 tracks):\n      - (74) MIDDLE OF THE NIGHT\n      - (56) Material Girl\n      - (49) Mellow Yellow\n      - (46) Monster\n      - (36) My Baby Just Cares For Me\n      - (30) My Own Drum (Remix) [with Missy Elliott]\n      - (27) Malambo No. 1\n      - (10) Mah Na Mah Na\n      - (2) Mozart: Horn Concerto No. 4 in E-Flat Major, K. 495: III. Rondo (Allegro vivace)\n    B (9 tracks):\n      - (81) Before You Go\n      - (81) bad guy\n      - (76) bellyache\n      - (74) bury a friend\n      - (67) Bad - 2012 Remaster\n      - (60) Blood on the Dance Floor\n      - (46) Blue (Da Ba Dee)\n      - (40) Bizet: Carmen, WD 31, Act 1: Habanera. \"L'amour est un oiseau rebelle\" (Carmen, Ch\u0153ur)\n      - (39) Baby Mine\n    F (4 tracks):\n      - (70) From Now On\n      - (65) Friend Like Me\n      - (63) Fat Bottomed Girls - Remastered 2011\n      - (58) Fever\n    G (7 tracks):\n      - (74) Ghostbusters\n      - (73) Get Into It (Yuh)\n      - (72) Gangnam Style (\uac15\ub0a8\uc2a4\ud0c0\uc77c)\n      - (62) Get Back Up Again\n      - (59) Greased Lightnin' - From \u201cGrease\u201d\n      - (40) Grand Finale\n      - (32) Ghost in the Keys\n    P (3 tracks):\n      - (64) Peaches\n      - (30) Pink Panther Theme - Remix Version\n      - (0) Papaoutai\n    Y (3 tracks):\n      - (65) You Can't Always Get What You Want\n      - (49) You Can't Stop The Beat\n      - (31) You're No Good - From 'Minions: The Rise of Gru' Soundtrack\n    Z (1 tracks):\n      - (82) Zombie\n    K (3 tracks):\n      - (77) Kings & Queens\n      - (58) Karma Chameleon\n      - (0) Kung Fu Fighting (From \"Kung Fu Panda 3\")\n    O (6 tracks):\n      - (64) Oye Como Va\n      - (43) One Of A Kind\n      - (41) On My Way\n      - (40) One More Song\n      - (0) Omg - Radio Edit\n      - (0) ooh la la (feat. Greg Nice & DJ Premier)\n    J (3 tracks):\n      - (75) Jolene\n      - (43) Je Me Suis Fait Tout Petit\n      - (33) Jolie coquine\n    5 (1 tracks):\n      - (30) 5:55\n    . (1 tracks):\n      - (81) ...Baby One More Time\n    \" (1 tracks):\n      - (3) \"Ellens Gesang III\", D839: Ave Maria\n\n\n### The dates table\n\nJust a table with the added_at and album_release dates, along with other metadata, for convenience\n\n\n```python\nta.dates\n```\n\n\n\n\n<div>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>album_release_date</th>\n      <th>added_at_date</th>\n      <th>name</th>\n      <th>first_artist</th>\n      <th>name_and_artist</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>181</th>\n      <td>2010-06-18</td>\n      <td>2024-11-06</td>\n      <td>Love The Way You Lie</td>\n      <td>Eminem</td>\n      <td>Love The Way You Lie -- Eminem</td>\n    </tr>\n    <tr>\n      <th>180</th>\n      <td>2002-05-26</td>\n      <td>2024-11-03</td>\n      <td>Without Me</td>\n      <td>Eminem</td>\n      <td>Without Me -- Eminem</td>\n    </tr>\n    <tr>\n      <th>179</th>\n      <td>2014-11-24</td>\n      <td>2024-11-03</td>\n      <td>Lose Yourself</td>\n      <td>Eminem</td>\n      <td>Lose Yourself -- Eminem</td>\n    </tr>\n    <tr>\n      <th>178</th>\n      <td>2005-12-06</td>\n      <td>2024-11-03</td>\n      <td>The Real Slim Shady</td>\n      <td>Eminem</td>\n      <td>The Real Slim Shady -- Eminem</td>\n    </tr>\n    <tr>\n      <th>177</th>\n      <td>2024-05-30</td>\n      <td>2024-11-03</td>\n      <td>Houdini</td>\n      <td>Eminem</td>\n      <td>Houdini -- Eminem</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2011-01-01</td>\n      <td>2016-09-07</td>\n      <td>Mah Na Mah Na</td>\n      <td>Mahna Mahna and The Two Snowths</td>\n      <td>Mah Na Mah Na -- Mahna Mahna and The Two Snowths</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>2012-10-29</td>\n      <td>2016-09-07</td>\n      <td>Sing, Sing, Sing</td>\n      <td>The Andrews Sisters</td>\n      <td>Sing, Sing, Sing -- The Andrews Sisters</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>2007-01-01</td>\n      <td>2016-09-07</td>\n      <td>My Baby Just Cares For Me</td>\n      <td>Nina Simone</td>\n      <td>My Baby Just Cares For Me -- Nina Simone</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2015-01-28</td>\n      <td>2016-08-14</td>\n      <td>Wimoweh (Mbube)</td>\n      <td>Yma Sumac</td>\n      <td>Wimoweh (Mbube) -- Yma Sumac</td>\n    </tr>\n    <tr>\n      <th>0</th>\n      <td>1997-01-01</td>\n      <td>2016-08-14</td>\n      <td>The Imperial March (Darth Vader's Theme)</td>\n      <td>John Williams</td>\n      <td>The Imperial March (Darth Vader's Theme) -- Jo...</td>\n    </tr>\n  </tbody>\n</table>\n<p>182 rows \u00d7 5 columns</p>\n</div>\n\n\n\n\n```python\nta.tracks_grouped_by_year\n```\n\n\n\n<div>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>name_and_artist</th>\n      <th>number_of_songs</th>\n    </tr>\n    <tr>\n      <th>album_release_year</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>1954</th>\n      <td>[Malambo No. 1 -- Moises Vivanco]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1961</th>\n      <td>[West Side Story: Act II: I Feel Pretty -- Leo...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1965</th>\n      <td>[The Lonely Goatherd -- Julie Andrews, Do-Re-M...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1967</th>\n      <td>[Lucy In The Sky With Diamonds - Remastered 20...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1968</th>\n      <td>[Scarborough Fair / Canticle - Extended Versio...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1969</th>\n      <td>[You Can't Always Get What You Want -- The Rol...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1970</th>\n      <td>[Oye Como Va -- Santana]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1971</th>\n      <td>[Coconut -- Harry Nilsson]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1973</th>\n      <td>[Strawberry Fields Forever - Remastered 2009 -...</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1974</th>\n      <td>[Jolene -- Dolly Parton]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1977</th>\n      <td>[We Will Rock You - Remastered 2011 -- Queen]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1978</th>\n      <td>[Greased Lightnin' - From \u201cGrease\u201d -- John Tra...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1980</th>\n      <td>[Super Trouper -- ABBA]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1981</th>\n      <td>[Tainted Love -- Soft Cell]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1983</th>\n      <td>[Les cit\u00e9s d'or -- Le Groupe Apollo, Sweet Dre...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1984</th>\n      <td>[Material Girl -- Madonna]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1988</th>\n      <td>[Drive My Car -- Bobby McFerrin]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1989</th>\n      <td>[Je Me Suis Fait Tout Petit -- Georges Brassen...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1990</th>\n      <td>[Do The Bartman -- The Simpsons]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1991</th>\n      <td>[Mozart: Horn Concerto No. 4 in E-Flat Major, ...</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1993</th>\n      <td>[Somewhere Over The Rainbow_What A Wonderful W...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1994</th>\n      <td>[Zombie -- The Cranberries]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1995</th>\n      <td>[Scatman (ski-ba-bop-ba-dop-bop) -- Scatman Jo...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1996</th>\n      <td>[It's Only A Paper Moon -- Ella Fitzgerald]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1997</th>\n      <td>[Blood on the Dance Floor -- Michael Jackson, ...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1999</th>\n      <td>[Livin' la Vida Loca -- Ricky Martin, Anything...</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>2000</th>\n      <td>[Indiana Jones Theme -- John Williams, Who Let...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>2001</th>\n      <td>[Don't Stop Believin' -- Journey]</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>2002</th>\n      <td>[Without Me -- Eminem, Dragostea Din Tei -- O-...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>2004</th>\n      <td>[Drop It Like It's Hot - Radio Edit -- Snoop D...</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>2005</th>\n      <td>[The Real Slim Shady -- Eminem, Winter Ducks P...</td>\n      <td>6</td>\n    </tr>\n    <tr>\n      <th>2006</th>\n      <td>[Pink Panther Theme - Remix Version -- Henry M...</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>2007</th>\n      <td>[What Time Is It -- Zac Efron, You Can't Stop ...</td>\n      <td>8</td>\n    </tr>\n    <tr>\n      <th>2008</th>\n      <td>[C'est de l'eau -- Les Enfantastiques, I Like ...</td>\n      <td>6</td>\n    </tr>\n    <tr>\n      <th>2010</th>\n      <td>[Love The Way You Lie -- Eminem, Waka Waka (Th...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>2011</th>\n      <td>[Rolling in the Deep -- Adele, Lost and Found ...</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>2012</th>\n      <td>[Gangnam Style (\uac15\ub0a8\uc2a4\ud0c0\uc77c) -- PSY, Somebody That I...</td>\n      <td>6</td>\n    </tr>\n    <tr>\n      <th>2013</th>\n      <td>[Roar -- Katy Perry, Wrecking Ball -- Miley Cy...</td>\n      <td>5</td>\n    </tr>\n    <tr>\n      <th>2014</th>\n      <td>[Lose Yourself -- Eminem, I Got You - 1964 Sma...</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>2015</th>\n      <td>[Cups - Movie Version -- Anna Kendrick, Unity ...</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <th>2016</th>\n      <td>[Chill Jazz -- Simon Leonard Thorpe, Ghostbust...</td>\n      <td>10</td>\n    </tr>\n    <tr>\n      <th>2017</th>\n      <td>[New Rules -- Dua Lipa, The Other Side -- Hugh...</td>\n      <td>14</td>\n    </tr>\n    <tr>\n      <th>2018</th>\n      <td>[Solo (feat. Demi Lovato) -- Clean Bandit, We ...</td>\n      <td>6</td>\n    </tr>\n    <tr>\n      <th>2019</th>\n      <td>[We Play All Night Long -- Norris Nuts, Viens ...</td>\n      <td>14</td>\n    </tr>\n    <tr>\n      <th>2020</th>\n      <td>[All Norris Nuts Songs About Themselves -- Nor...</td>\n      <td>10</td>\n    </tr>\n    <tr>\n      <th>2021</th>\n      <td>[Stay Shrimpy -- Norris Nuts, Monster -- YOASO...</td>\n      <td>14</td>\n    </tr>\n    <tr>\n      <th>2022</th>\n      <td>[Don't Rain on My Parade -- Lea Michele, Laiss...</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>2023</th>\n      <td>[10:35 -- Ti\u00ebsto, exes -- Tate McRae, Houdini ...</td>\n      <td>5</td>\n    </tr>\n    <tr>\n      <th>2024</th>\n      <td>[Houdini -- Eminem, Eating the Cats (Donald Tr...</td>\n      <td>5</td>\n    </tr>\n  </tbody>\n</table>\n</div>\n\n",
    "bugtrack_url": null,
    "license": "mit",
    "summary": "Music data access",
    "version": "0.0.8",
    "project_urls": {
        "Homepage": "https://github.com/thorwhalen/sung"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ef30d30a379e0995b9fb03b88a64f84bfb9c9dcdd22e025e55153c7dd7db5718",
                "md5": "514c10a1264944ee2c8127da0efc3b6e",
                "sha256": "4b4e58daf98d9e69785a82e4b304699d96369501a491d267fb4dc95ab418df83"
            },
            "downloads": -1,
            "filename": "sung-0.0.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "514c10a1264944ee2c8127da0efc3b6e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 46589,
            "upload_time": "2024-11-16T18:55:17",
            "upload_time_iso_8601": "2024-11-16T18:55:17.810166Z",
            "url": "https://files.pythonhosted.org/packages/ef/30/d30a379e0995b9fb03b88a64f84bfb9c9dcdd22e025e55153c7dd7db5718/sung-0.0.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e7d6f3e2a42a0d6695aef9a56fbd440968ef2520a0275085a531039e2e57ab4d",
                "md5": "3804356f173c89d866ee5baba7abcaca",
                "sha256": "fa82ee47bb884af566c4091cb6ba972aa173358a3570dd236b6042d15bf131e2"
            },
            "downloads": -1,
            "filename": "sung-0.0.8.tar.gz",
            "has_sig": false,
            "md5_digest": "3804356f173c89d866ee5baba7abcaca",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 70282,
            "upload_time": "2024-11-16T18:55:19",
            "upload_time_iso_8601": "2024-11-16T18:55:19.736063Z",
            "url": "https://files.pythonhosted.org/packages/e7/d6/f3e2a42a0d6695aef9a56fbd440968ef2520a0275085a531039e2e57ab4d/sung-0.0.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-16 18:55:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "thorwhalen",
    "github_project": "sung",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "sung"
}
        
Elapsed time: 0.64197s