Como resolver disputas familiares con Data Science
Nos anos 90 un par de físicos conseguiron a atención de medio mundo ao anunciaren a descoberta da fusión fría, onde dous núcleos de hidróxeno fúndense para formar un de helio e desbotar a enerxía sobrante a temperaturas de andar, literalmente, por casa.
A importancia da descoberta radicaba en que sería unha fonte de enerxía limpa, abundante e económica.
Hai uns meses, outros científicos da Univerisade de Rochester publicaron os resultados duns experimentos onde aseguraban ter conseguido materiais superconductores a temperatura ambiente. Ao contrario da fusión nuclear, que precisa de condicións proprias do centro das estrelas, certos materiais conducen a electricidade sen apenas resistencia cando se acadan as xélidas temperaturas do espazo exterior.
A superconductividade a temperarura ambiente permitiría, por exemplo, novas técnicas para o almacenamento da electricidade ou reduciría as perdas na súa transmisión (A Axencia Internacional da Enerxía estima que, no mundo, estas representan uns 2100 TWh anuais, o equivalente ao que consumiría Galicia en case un século).
O problema de ámbolas dúas descobertas é que eran mentira. Nature tivo que retirar as publicacións e as universidades despediron aos científicos.
Se a ciencia, onde a razón debería ser capaz de arrinconar ás crenzas e a fe, non é inmune ao fraude ou ao pensamento ilusorio, podemos esperar que un combate de cuñados ou unha rifa entre irmáns discorra en termos racionalistas?
Probabélmente, non, pero haberá que facer un esforzo.
O problema: é mellor a música dos 90 ou dos 80?
O caso que me ocupa é o de dous irmáns que defenden dúas décadas distintas como as mellores da música: Queen, The Police e The Smiths fronte a Nirvana, Pearl Jam ou Radiohead. Levo anos escoitando a mesma leria. Hai uns días, curioseando en besteveralbums.com, ocorréuseme unha idea para pechar o debate: e se usamos o ranking para obter datos que digan quen dos dous ten razón?
Que é bestalbumever?
Esta web ofrece un ranking dos mellors álbumes de todos os tempos usando máis de 50.000 listaxes de terceiros. Deste xeito, o resultado podería considerarse unha especie de “wisdom of the crowd” musical ou de consenso.
A técnica é sinxela: cun pequeno script de python cun par de librerías, escrapeamos 100 urls que conteñen os 500 primeiros álbumes do ranking para identificar o HTML que contén a década e a puntuación de cada un.
Logo facemos unha pequena limpeza, agrupamos os datos por décadas e facemos unha comparación.
Eis o script:
from bs4 import BeautifulSoup
import requests
import re
import pandas as pd
def scrape_data(url):
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
chart_stats = soup.find_all('div', class_='chart-stats')
data = []
for chart in chart_stats:
stats = {}
keys = chart.find_all('div', class_='chartstring')
values = chart.find_all('div', class_='chart-stats-metric')
for key, value in zip(keys, values):
key_text = key.get_text(strip=True).replace(':', '')
value_text = value.get_text(strip=True)
if key_text in ["Year of Release", "Rank Score"]:
stats[key_text] = value_text
if stats:
data.append(stats)
return data
urls = []
for i in range(1,101):
urls.append('https://www.besteveralbums.com/overall.php?o=&f=&fv=&orderby=-InfoRankScore&sortdir=asc&page='+str(i))
all_data = []
for url in urls:
all_data.extend(scrape_data(url))
df = pd.DataFrame(all_data)
df['Rank Score'] = df['Rank Score'].str.replace(',', '')
df['Rank Score'] = df['Rank Score'].astype('int64')
df['decade'] = df['Year of Release'].apply(lambda x: x[:3]+'0s')
acumulutaded_rank = df.groupby('decade')['Rank Score'].sum()
mean_rank = df.groupby('decade')['Rank Score'].mean()
albums_per_decade = df.groupby('decade')['Rank Score'].count()
result = pd.concat([acumulutaded_rank, albums_per_decade, mean_rank], axis=1)
result.columns = ['acumulutaded_rank', 'albums_per_decade', 'mean rank']
result.sort_values(by='mean rank', ascending=False,inplace=True)
result = result[result['decade'].isin(['1990s','1980s'])]
the_90s = result[result['decade']=='1990s']
the_80s = result[result['decade']=='1980s']
print("Difference in percentage between 1990s and 1980s")
print("Average rank: {:.1f}%".format(100 * (the_90s['mean rank'].values[0] / the_80s['mean rank'].values[0] - 1)))
print("Number of albums: {:.1f}%".format(100 * (the_90s['albums_per_decade'].values[0] / the_80s['albums_per_decade'].values[0] - 1)))
print("Accumulated rank: {:.1f}%".format(100 * (the_90s['acumulutaded_rank'].values[0] / the_80s['acumulutaded_rank'].values[0] - 1)))
Os resultados de correr o script son os seguintes:
Diferencia porcentual entre 1990s o os 1980s
Puntuación media: +9,4 %
Número de álbumes: +26,0 %
Puntuación acumulado: 37,9%
Os datos falan alto e claro: os 90 gañan por goleada.
Como dixo James Barksdale, “Se temos datos, vexámolos; se o único que temos son opinións, imos coas miñas”.
p.d. Isto nin é data science, nin é disputa familiar, mais so unha escusa para se sentar a escribir. E aínda cos resultados na man, eu tamén prefiro os 80.