La historia de la música Popular a través de los datos

Cualquiera de vosotros que haya estado leyendo los artículos que he ido escribiendo aquí se habrá dado cuenta de que la música es una de mis mayores pasiones. Y dentro de esa pasión lo que más me ha interesado siempre ha sido el entender el auge y caída de los géneros musicales (por muy historiador que quede este título). ¿Por qué? Básicamente porque creo que no se pueden entender las tendencias de la música actual sin conocer las tendencias del pasado.

Pero, ¿qué tiene que ver todo esto con los datos? ¿A qué nos vamos a enfrentar en este proyecto? Pues nos vamos a enfrentar literalmente a lo que dice el título: a generar una historia de la música popular a través de los datos. Pero lo vemos a hacer de una forma peculiar. Normalmente lo que os traería en un artículo de estas características es la solución más o menos inmediata de cómo realizar el proceso que estamos viendo y obtener los resultados de una forma ágil y relativamente sencilla. El tema es que para mí, poder obtener esos resultados ha sido una tarea más ardua de lo normal. Esto ha venido ocasionado por varios motivos: menos tiempo para escribir, volumen de proyecto alto, conceptualización más complicada (no olvidemos que se trata de sintetizar la historia de la música popular con datos), etc. Por ello, lejos de daros una solución sencilla y que podáis seguir de la mano voy a plantear este artículo como el taller, como el laboratorio del proyecto: en él veremos todos los errores que he ido cometiendo, las dificultades técnicas o conceptuales que se han ido presentando y, en definitiva, veremos las cloacas de la ciudad que queremos construir. Siempre desde el lado técnico, por supuesto.

Para tenerlo todo lo más organizado posible, voy a enumerar antes de empezar todos los requisitos que vamos a necesitar a lo largo de la aventura:

1. Un clone de mi repositorio en la carpeta que prefieras de tu ordenador:

git clone https://github.com/74minutos/popular_music

2. Una cuenta de desarrollador en spotify, puedes encontrar cómo hacerlo en este enlace.

3. Una carpeta en el root de tu directorio llamada credentials y, dentro de esta, un archivo llamado «spotify_credentials.json», con la siguiente estructura:

{client_id: "inserta aquí tu client_id", client_secret: "inserta aquí tu
 client_secret"}

4. Un virtual env que puedes crear a través de la consola con el siguiente comando:

python -m venv env

5. Instala todas las dependencias del proyecto a través del requirements.txt:

env/bin/pip install -r requirements.txt

6. Una cuenta en BigQuery, donde almacénaremos la información que vamos a extraer de Spotify. Deberemos descargarnos las credenciales de BigQuery como cuenta de servicio, tal y cómo explica este enlace. Las guardaremos también en nuestra carpeta credentials, con el nombre de «google_credentials.json».

7. Una variable de entorno, que generaremos a través del siguiente código en nuestra terminal:

export GOOGLE_APPLICATION_CREDENTIALS="credentials/google_credentials.json"

Primeros pasos: la decadencia de la industria discográfica

Out-of-Business Record Companies - Photos | Steve Hoffman Music Forums

Mi idea inicial era conseguir datos de miles de álbumes por año a través de la API de spotify, desde aproximadamente la década de los cuarenta/cincuenta, fecha en la cual se marca el inicio de la música popular tal y como la conocemos actualmente. Lo que quería conseguir con esto era ver cuántos discos de cada género habían salido cada año, y con esto obtener una cronología bastante acertada de los géneros más populares en cada momento del período estudiado.

Aquí ya nos encontramos la primera limitación: spotify sólo te permite extraer datos para 1.000 elementos por llamada. Esto ya lo tenía claro por previos desarrollos, así que decido que lo mejor será recoger 1.000 álbums por año, una muestra más que aceptable para registrar las tendencias que quiero ver en mi proyecto final. Al hacerlo y empezar a jugar un poco con los datos salta a la vista que estos son del todo ineficientes para nuestro experimento. ¿Por qué? Porque en las últimas décadas el valor y el volumen de los discos ha decrecido muchísimo si lo comparamos con décadas de mayor esplendor, como pueden ser los sesenta/setenta.

¿Qué ocurre en este punto? Pues que los valores que intentamos evaluar no son equiparables. Los géneros que surgen o tienen preponderancia en las décadas de mayor tirada tendrían una sobrerrepresentación con este método, así como aquellos géneros que en las últimas décadas son más dados a seguir emitiendo discos frente a otros que tienen un estilo de producción más directa (principalmente géneros como electrónica, trap o reggaeton, por ejemplo).

Siguiendo la senda: singles

Why Am I Single? 100% Honest Quiz for Girls & Guys

Teniendo en cuenta la problemática anterior, decido que la mejor opción para obtener mi objetivo es centrarme exclusivamente en la extracción de metadatos de canciones. Todo el desarrollo de este módulo lo podéis encontrar en mi repositorio, pero por enfocarme exclusivamente en este proceso, lo que he utilizado es el módulo de search que facilita la API de spotify, con los siguientes valores para que me devolviera lo que necesita en este punto:

tracks = []
    for year in range(1940, 2021):
        for i in range(0,1000, 50):
            track_results = spotify_api.search(q='year:{}'.format(year), 
type='track', limit=50, offset=i)
            for i, t in enumerate(track_results['tracks']['items']):
                track = make_track(
                    popularity =t['popularity'],
                    id = t['id'],
                    track_name = t['name'],
                    artist_name = t['artists'][0]['name'],
                    artist_id = t['artists'][0]['id'],
                    year = year)
                tracks.append(track)

Por supuesto, esto no funciona de manera independiente (mirad el resto en GitHub), pero así es más fácil de entender lo que hacemos ahora mismo: pedimos a spotify que nos devuelva 1.000 canciones por año desde 1940. Con la información que obtenemos generamos un diccionario con los metadatos de: nombre de artista, nombre de canción, id de canción, id de artista, popularidad y año.

Cuando obtenemos los datos de esto y podemos analizarlos de forma algo más profunda nos volvemos a topar con un nuevo problema: los géneros no están asociados a la canción. Para obtener los géneros de las mismas lo que tenemos que hacer es pedirlos por artistas y más tarde asociar este género (o géneros) a la canción en cuestión. En este sentido, vemos que la investigación se ve algo sesgada ya que, aunque es cierto que los artistas no suelen cambiar de estilo de forma drástica a lo largo de su trayectoria, esta técnica podría afectar a la forma de entender ciertos estilos. En cualquier caso, como podemos entender que es algo que afecta de forma bastante superflua, decidimos continuar con el proceso.

¿Alguien había dicho fragmentación?

Seeing Sounds: Kandinsky + Schoenberg - Artsy

Quizá en Kandinsky veo algo más concreto que lo que obtenía cuando quería realizar una gráfica de evolución de todos los géneros obtenidos en el último paso. En la última versión que he trabajado nos encontramos con 3.520 géneros distintos, algo que facilita muchísimo la visualización de las tendencias:

Para poder manejar esto de la manera más flexible y dinámica posible, decido subir toda esta información a BigQuery (módulo upload_to_bigquery). ¿Por qué BigQuery? Básicamente porque necesito hacer una agrupación de los géneros más representativos a través de coincidencias en el string de género que hemos obtenido más arriba, y para esta tarea no hay nada mejor que SQL. La ventaja de hacerlo en BigQuery es que tiene una estupenda integración con DataStudio, la herramienta de visualización de datos de Google, que nos permitirá pintar nuestros datos de forma muy ágil.

Pero nos habíamos quedado en la agrupación de géneros. Déjadme explicarlo mejor. Lo que quiero hacer, visto que los subgéneros son una cosa imposible de manejar, es decir que, por ejemplo, toda canción que lleve «rock» en su género vamos a decir que es Rock. Para tener un punto de vista neutral sobre estos «metagéneros» he extraído la mayoría de aquí. Lo sé, es una simplificación y vamos a dejarnos mucha música que no entra de los estilos más generales, pero debo hacerlo para poder hacer el proyecto algo entendible de un vistazo. Además, este es el camino que yo he tomado, pero lo que espero de este artículo es que aprendáis de mis errores y podáis tomar otro con más interés para vosotros.

Dentro de BigQuery he generado la siguiente consulta que me permite hacer una tabla con la agrupación de géneros que yo quiero en este momento:

create table `your_project.your_dataset.your_table` as
    SELECT DISTINCT 
        popularity,
        id,
        track_name,
        artist_name,
        year,
        case 
            when genre like '%rock%' or genre like'%Rock%' then 'Rock'
            when genre like '%pop%' or genre like '%Pop%' then 'Pop'
            when genre like '%metal%' or genre like '%Metal%' then 'Metal'
            when genre like '%blues%' or genre like '%Blues' then 'Blues'
            when genre like '%country' or genre like '%Country%' then 'Country'
            when genre like '%tronic%' or genre like '%dance%' or genre like '%edm%' or genre like '%house%' or genre like '%electro%' or genre like '%techno%' then 'Electronic'
            when genre like '%folk%' or genre like '%songwriter%' then 'Folk'
            when genre like '%funk%' then 'Funk'
            when genre like '%jazz%' then 'Jazz'
            when genre like '%latin%' or genre like 'son' or genre like 'mambo' or genre like '%reggaeton%' or genre like 'merengue' or genre like 'bachata' or genre like 'salsa' or genre like 'cumbia' or genre like 'bolero' or genre like '%rumba%' then 'Latin'
            when genre like '%hip hop%' or genre like '%rap%' then 'Hip Hop'
            when genre like '%punk%' then 'Punk'
            when genre like '%soul%' or genre like '%r&b%' then 'Soul/R&B'
        else 
            'other'
        end as genre
    FROM `your_project.your_dataset.your_table_without_grouping_genres`
    where genre is not null

Por supuesto, cambia todos los nombres de proyecto, dataset y tablas con los tuyos para que funcione la query.

¿Esto que nos permite? Nos permite tener de manera mucho más ordenada todos los estilos de las canciones que hemos extraído como nuestro conjunto de datos. Más tarde veremos cómo cambia la visualización con respecto a lo que habíamos obtenido con la híper fragmentación anterior.

Debo decir aquí que sólo al empezar a trabajar de forma más categórica con SQL en este dataset fue cuando pude descubrir algunos errores en mi llamada a Spotify que me estaban haciendo recoger datos de forma errónea (muchas de las entradas estaban repetidas). Esto es así y lo quiero recalcar porque si bien es cierto que python es la herramienta a la que más provecho podemos sacar, SQL nos permite realizar trabajos que serían muchísimo más tediosos y complejos con python, en cuestión de unas pocas líneas (como las que habéis visto). El hecho de realizar este análisis sobre nuestro conjunto de datos siempre nos asegurará un doble check fundamental para entender que nuestro trabajo está correctamente realizado.

Anacronismo vs Popularidad

On Empire and Anachronism – Imperial & Global Forum

Mi idea para ordenar y dar el valor que le correspondía a las canciones era utilizar el parámetro «popularity». MI gozo en un pozo. Consultando la documentación de la API de Spotify para ver a qué se refería exactamente este valor, me encuentro con lo siguiente:

The popularity of a track is a value between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.

Generally speaking, songs that are being played a lot now will have a higher popularity than songs that were played a lot in the past. Duplicate tracks (e.g. the same track from a single and an album) are rated independently. Artist and album popularity is derived mathematically from track popularity.

En resumen, la popularidad de la canción depende principalmente de las escuchas que ha tenido en los últimos días. ¡Maravilloso para las canciones de los cuarenta! Por supuesto, esto lo convertía en un parámetro totalmente inútil para mis propósitos, ya que se verían sobrerrepresentados géneros que ahora mismo sean los de mayor éxito, mientras otros (el jazz, el blues…) se quedarían en el olvido por no tener las suficientes escuchas recientes.

En cualquier caso, aunque era un parámetro que no iba a utilizar como medida de las cosas, sí que lo encuentro como algo que podemos utilizar en la visualización, al menos para entender las tendencias más actuales. Lo que acabé utilizando como medida fue un simple contador de canciones únicas por género. Este hecho lo pude realizar gracias a la denormalización del conjunto de datos en base a género, lo que suponía tener una canción única por cada estilo musical. Así, por ejemplo, con Enter Sandman la tendríamos una vez en Rock y otra en Metal.

Visualización y cierre

Parece que ya hemos superado todos los grandes obstáculos del camino, tenemos la meta cerca y estamos deseando cruzarla sin mirar atrás. Sólo nos queda poder visualizarlo de la forma que nosotros queremos. De todas las que he estado probando, sin duda la que me parece más acertada para mis propósitos es la siguiente.

Estuve probando gráficas de área, gráficas de línea, etc. pero al final lo que me interesaba realmente era poder observar lo que vemos aquí: cómo se mueven los géneros a los largo del tiempo. Podemos ver por ejemplo la época del esplendor del jazz, que muy rápidamente se convierte en un estilo minoritario en favor esencialmente del rock, que crece desorbitadamente en la década de los 60 y se convierte en el estilo mayoritario hasta prácticamente los 2000.

Como creo que ya se ha visto anteriormente, mi idea inicial era realizar todo esto con Tableau, que tiene opciones más avanzadas en algunos aspectos que Datastudio. En hecho de finalmente procesar todo a través de BigQuery hacía infinitamente más sencillo realizar la visualización a través de DataStudio, lo cual es lo que he decidido hacer finalmente. Lo podéis consultar aquí. Sin embargo, en este sentido, debo decir que la visualización se ha quedado en un proceso abierto. Estoy seguro de que seguiré trabajando este dashboard durante mucho tiempo, ya que lo quiero hacer básicamente mi manual de referencia al que acudir para entender ciertas tendencias que de esta forma son mucho más sencillas de entender.

En cualquier caso, el resultado final no era el objetivo de este artículo sino el ver las vicisitudes a las que te puedes enfrentar a la hora de realizar un proyecto de este tipo, y cómo ir resolviéndolas a lo largo del camino. Espero que te haya sido útil y sobre todo, espero que hayas aprendido algo.

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s