<jupyter_start><jupyter_text>¿Quién llegará al número uno en Billboard 100? A partir de atributos de cantantes y de un histórico de canciones que alcanzaron entrar al Billboard 100 (U.S.) en 2013 y 2014 se creará un árbol de decisión permita intentar predecir si un nuevo cantante podrá llegar a número uno.<jupyter_code># Imports necesarios
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')
from sklearn import tree
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from IPython.display import Image as PImage
from subprocess import check_call
from PIL import Image, ImageDraw, ImageFont<jupyter_output><empty_output><jupyter_text>Cargamos los datos de entrada<jupyter_code>artists_billboard = pd.read_csv(r'artists_billboard_fix3.csv')

artists_billboard.shape<jupyter_output><empty_output><jupyter_text>Datos de 635 artistas con 11 atributos<jupyter_code>artists_billboard.head(5)<jupyter_output><empty_output><jupyter_text>¿Cuántos alcanzaron el número 1?<jupyter_code>artists_billboard.groupby('top').size()<jupyter_output><empty_output><jupyter_text>494 canciones que no alcanzaron el top 1 y 141 que si, lo que significa que los datos están desbalanceados<jupyter_code>sb.factorplot('top',data=artists_billboard,kind="count")<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Visualizar los Atributos de entrada<jupyter_code>sb.factorplot('artist_type',data=artists_billboard,kind="count")<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Se evidencia que hay más del doble de artistas masculinos que femeninos, mientras que sólo hay alrededor de 100 mixtas<jupyter_code>sb.factorplot('top',data=artists_billboard,hue='artist_type',kind="count")<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Y ademas que la gran mayoría de esas canciones con artistas hombres no alcanzaron el top 1 de billboard (U.S.)<jupyter_code>g = sb.factorplot('mood',data=artists_billboard,kind="count", aspect=3)

for axes in g.axes.flat:
    axes.set_xticklabels(axes.get_xticklabels(), rotation=45, horizontalalignment='right')<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>De 23 tipos de "mood" hay 7 con mayor cantidad de datos: - Energizing - Excited - Yeaming - Cool - Defiant - Sensual - Empowering<jupyter_code>g = sb.factorplot('mood',data=artists_billboard,hue='top',kind="count", aspect=3)

for axes in g.axes.flat:
    axes.set_xticklabels(axes.get_xticklabels(), rotation=45, horizontalalignment='right')<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>El mood "yeaming", "defiant" y "empowering" son de los que menos canciones en top 1 han alcanzado de esos 7, mientras "cool" y "energizing" son de los que mas canciones en top 1 tuvieron<jupyter_code>sb.factorplot('tempo',data=artists_billboard,hue='top',kind="count")<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Se ven 3 tipos de "tempo" - Medium - Slow - FastPredominando el "tempo" medium para todas las canciones y también para las que han alcanzado el top 1 (azul)<jupyter_code>sb.factorplot('genre',data=artists_billboard,kind="count", aspect=3)<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Por el genero de la musica se ve que predominan el Urban y el Pop seguidos por el Tradicional Visualizar los años de nacimiento de los artistas<jupyter_code>g = sb.factorplot('anioNacimiento',data=artists_billboard,kind="count", aspect=3)
for axes in g.axes.flat:
    axes.set_xticklabels(axes.get_xticklabels(), rotation=45, horizontalalignment='right')<jupyter_output>/usr/local/lib/python3.6/dist-packages/seaborn/categorical.py:3704: UserWarning: The `factorplot` function has been renamed to `catplot`. The original name will be removed in a future release. Please update your code. Note that the default `kind` in `factorplot` (`'point'`) has changed `'strip'` in `catplot`.
  warnings.warn(msg)
/usr/local/lib/python3.6/dist-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>En el año "0" de nacimiento del artista hay aproximadamente 140 registros<jupyter_code>#artists_billboard[['anioNacimiento', 'top']].groupby(['anioNacimiento'], as_index=False).agg(['mean', 'count', 'sum'])
nacimientosPorAnio = artists_billboard['anioNacimiento']
len(nacimientosPorAnio[nacimientosPorAnio<=0])<jupyter_output><empty_output><jupyter_text>Se tienen 139 registros de canciones de las que se desconoce el año de nacimiento del artista. Se deben tratar estos datos para poder utilizar el árbol.  Comparemos los Top y los No-top Buscar si hay alguna relación evidente entre Año y duración de Canción<jupyter_code>colores=['orange','blue']
tamanios=[60,40]

f1 = artists_billboard['anioNacimiento'].values
f2 = artists_billboard['durationSeg'].values

asignar=[]
for index, row in artists_billboard.iterrows():    
    asignar.append(colores[row['top']])

plt.scatter(f1, f2, c=asignar, s=30)
plt.axis([1960,2005,0,600])
plt.show()<jupyter_output><empty_output><jupyter_text>No perece haber ningún patron a la vista, están bastante mezclados los top de los no-top. Analizar en que años se tienen las Top<jupyter_code>f1 = artists_billboard['chart_date'].values
f2 = artists_billboard['durationSeg'].values

asignar=[]
asignar2=[]
for index, row in artists_billboard.iterrows():    
    asignar.append(colores[row['top']])
    asignar2.append(tamanios[row['top']])

plt.scatter(f1, f2, c=asignar, s=30)
plt.axis([20030101,20160101,0,600])
plt.show()<jupyter_output><empty_output><jupyter_text>Esto es porque inicialmente se tomó información de 2014 y 2015 y había casi 500 no-top contra sólo 11 registros top.Entonces se agrupan a los artistas que alcanzaron el top entre 2004 y 2013 para sumar casos positivos y equilibrar un poco nuestros datos de entrada. Aún así siguen estando desbalanceados los datos.Por lo tanto se usará un parametro (class_weight) del algoritmo de árbol de decisión para compensar la diferencia.  Arreglar las Edades de Artistas El objetivo de tener el año de nacimiento del artista para conocer la edad que tenía al momento de alcanzar el top de billboard.<jupyter_code>def edad_fix(anio):
    if anio==0:
        return None
    return anio

artists_billboard['anioNacimiento']=artists_billboard.apply(lambda x: edad_fix(x['anioNacimiento']), axis=1);<jupyter_output><empty_output><jupyter_text>Cambiar los valores de "0" por "NaN" en el dataframe<jupyter_code>artists_billboard.head(10)
def calcula_edad(anio,cuando):
    cad = str(cuando)
    momento = cad[:4]
    if anio==0.0:
        return None
    return int(momento) - anio

artists_billboard['edad_en_billboard']=artists_billboard.apply(lambda x: calcula_edad(x['anioNacimiento'],x['chart_date']), axis=1);<jupyter_output><empty_output><jupyter_text>Añadiendole un campo al dataframe "edad_en_billboard" que se llena con el calculo de la edad que tenía el artista al llegar al top 1<jupyter_code>artists_billboard.head(10)<jupyter_output><empty_output><jupyter_text>Calcular promedio de edad y asignarlos a los registros Nulos<jupyter_code>age_avg = artists_billboard['edad_en_billboard'].mean()
age_std = artists_billboard['edad_en_billboard'].std()
age_null_count = artists_billboard['edad_en_billboard'].isnull().sum()
age_null_random_list = np.random.randint(age_avg - age_std, age_avg + age_std, size=age_null_count)

conValoresNulos = np.isnan(artists_billboard['edad_en_billboard'])

artists_billboard.loc[conValoresNulos, 'edad_en_billboard'] = age_null_random_list
artists_billboard['edad_en_billboard'] = artists_billboard['edad_en_billboard'].astype(int)
print("Edad Promedio: " + str(age_avg))
print("Desvió Std Edad: " + str(age_std))
print("Intervalo para asignar edad aleatoria: " + str(int(age_avg - age_std)) + " a " + str(int(age_avg + age_std)))<jupyter_output>Edad Promedio: 30.10282258064516
Desvió Std Edad: 8.40078832861513
Intervalo para asignar edad aleatoria: 21 a 38<jupyter_text>Visualizar las edades agregadas<jupyter_code>f1 = artists_billboard['edad_en_billboard'].values
f2 = artists_billboard.index

colores = ['orange','blue','green']

asignar=[]
for index, row in artists_billboard.iterrows():    
    if (conValoresNulos[index]):
        asignar.append(colores[2]) # verde
    else:
        asignar.append(colores[row['top']])

plt.scatter(f1, f2, c=asignar, s=30)
plt.axis([15,50,0,650])
plt.show()<jupyter_output><empty_output><jupyter_text>Graficando los artistas por edad vs indice se puede ver los colores azul como los que alcanzaron el top billboard mientras que los naranja son los que no lo alcanzaron, los verdes son los que llenados anteriormente con el promedio usando la desviacion estandar  Mapeo de Atributos Realizar un mapeo de los atributos de entrada para poder transformarlos a categorias que se puedan utilzar en el árbol de decisión<jupyter_code>separador = "### ### ###"
grouped11 = artists_billboard.groupby('mood').size()
neworder11 = grouped11.sort_values(ascending=False)
print(neworder11)
print(separador)
print("Tempos de Canción: " + str(artists_billboard['tempo'].unique()))
print(separador)
print("Tipos de Artista: " + str(artists_billboard['artist_type'].unique()))
print(separador)
grouped11 = artists_billboard.groupby('genre').size()
neworder11 = grouped11.sort_values(ascending=False)
print(neworder11)
# Mood Mapping 
artists_billboard['moodEncoded'] = artists_billboard['mood'].map( {'Energizing': 6, 
                                        'Empowering': 6,
                                        'Cool': 5, 
                                        'Yearning': 4,        # anhelo, deseo, ansia
                                        'Excited': 5,         # emocionado
                                        'Defiant': 3, 
                                        'Sensual': 2, 
                                        'Gritty': 3,          # coraje 
                                        'Sophisticated': 4,
                                        'Aggressive': 4,      # provocativo
                                        'Fiery': 4,           # caracter fuerte
                                        'Urgent': 3, 
                                        'Rowdy': 4,           # ruidoso alboroto
                                        'Sentimental': 4,
                                        'Easygoing': 1,       # sencillo
                                        'Melancholy': 4, 
                                        'Romantic': 2, 
                                        'Peaceful': 1, 
                                        'Brooding': 4,        # melancolico
                                        'Upbeat': 5,          # optimista alegre
                                        'Stirring': 5,        # emocionante
                                        'Lively': 5,          # animado
                                        'Other': 0,'':0} ).astype(int)<jupyter_output><empty_output><jupyter_text>Dandoles a "mood" un valor entore 0 y 6 agrupandolos de acuerdo a su similaridad<jupyter_code># Tempo Mapping 
artists_billboard['tempoEncoded'] = artists_billboard['tempo'].map( {
    'Fast Tempo': 0, 
    'Medium Tempo': 2, 
    'Slow Tempo': 1, 
    '': 0} ).astype(int)<jupyter_output><empty_output><jupyter_text>Dandole a "tempo" un valor entre 0 y 2 de acuerdo a la cantidad de canciones que tiene cada "tempo"<jupyter_code># Genre Mapping 
artists_billboard['genreEncoded'] = artists_billboard['genre'].map( {'Urban': 4, 
                                          'Pop': 3, 
                                          'Traditional': 2, 
                                          'Alternative & Punk': 1,
                                         'Electronica': 1, 
                                          'Rock': 1, 
                                          'Soundtrack': 0, 
                                          'Jazz': 0,
                                          'Other':0,'':0} 
                                       ).astype(int)<jupyter_output><empty_output><jupyter_text>Agrupandolos también por similaridad del género<jupyter_code># artist_type Mapping 
artists_billboard['artist_typeEncoded'] = artists_billboard['artist_type'].map( {
    'Female': 2, 
    'Male': 3, 
    'Mixed': 1, 
    '': 0} ).astype(int)<jupyter_output><empty_output><jupyter_text>Dando valores entre 0 y 3 de acuerdo con el tipo de artista<jupyter_code># Mapping edad en la que llegaron al billboard
artists_billboard_edad = artists_billboard['edad_en_billboard']

artists_billboard.loc[ artists_billboard_edad <= 21, 'edadEncoded']									 = 0
artists_billboard.loc[(artists_billboard_edad > 21) & (artists_billboard_edad <= 26), 'edadEncoded'] = 1
artists_billboard.loc[(artists_billboard_edad > 26) & (artists_billboard_edad <= 30), 'edadEncoded'] = 2
artists_billboard.loc[(artists_billboard_edad > 30) & (artists_billboard_edad <= 40), 'edadEncoded'] = 3
artists_billboard.loc[ artists_billboard_edad > 40, 'edadEncoded']									 = 4<jupyter_output><empty_output><jupyter_text>Cambiando por rangos entre 0 y 4:   - Menor o igual que 21 años = 0   - Mayor a 21 y menor o igual que 26 = 1   - Mayor a 26 y menor o igual que 30 = 2   - Mayor a 30 y menor o igual que 40 = 3   - Mayor a 40 = 4<jupyter_code># Mapping Song Duration
artists_billboard_seg = artists_billboard['durationSeg']
artists_billboard.loc[ artists_billboard_seg <= 150, 'durationEncoded']									 = 0
artists_billboard.loc[(artists_billboard_seg > 150) & (artists_billboard_seg <= 180), 'durationEncoded'] = 1
artists_billboard.loc[(artists_billboard_seg > 180) & (artists_billboard_seg <= 210), 'durationEncoded'] = 2
artists_billboard.loc[(artists_billboard_seg > 210) & (artists_billboard_seg <= 240), 'durationEncoded'] = 3
artists_billboard.loc[(artists_billboard_seg > 240) & (artists_billboard_seg <= 270), 'durationEncoded'] = 4
artists_billboard.loc[(artists_billboard_seg > 270) & (artists_billboard_seg <= 300), 'durationEncoded'] = 5
artists_billboard.loc[ artists_billboard_seg > 300, 'durationEncoded']									 = 6<jupyter_output><empty_output><jupyter_text>Y de la misma manera para la duracion de la canción en segundos<jupyter_code>drop_elements = ['id',
                 'title',
                 'artist',
                 'mood',
                 'tempo',
                 'genre',
                 'artist_type',
                 'chart_date',
                 'anioNacimiento',
                 'durationSeg',
                 'edad_en_billboard'
                ]
artists_encoded = artists_billboard.drop(drop_elements, axis = 1)<jupyter_output><empty_output><jupyter_text>Al eliminar los datos originales solo quedan los datos codificados en los numeros establecidos con los diccionario previos  Analizar los datos de Entrada Categóricos<jupyter_code>artists_encoded.head(10)
artists_encoded.describe().transpose()<jupyter_output><empty_output><jupyter_text>Gráfica de correlación de Pearson<jupyter_code>colormap = plt.cm.inferno
#plt.figure(figsize=(13,13))
plt.title('Pearson Correlation of Features')
sb.heatmap(artists_encoded.astype(float).corr(),
           vmax=1.0,
           cmap=colormap,
           annot=True,
           linewidths=0.1,
           linecolor='white',
           square=True)<jupyter_output><empty_output><jupyter_text>Según esta gráfica no hay variables correlacionadas, por lo que usarlas todas en nuestro modelo nos aportará información  Datos top en relación con los datos mapeados<jupyter_code>artists_encoded[['moodEncoded', 'top']].groupby(['moodEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>La mayoría de los top 1 están en el "mood" 5 y 6  con 46 y 43 canciones<jupyter_code>artists_encoded[['artist_typeEncoded', 'top']].groupby(['artist_typeEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>Hay una "buena" distribución de datos aunque se ve que mayormente están en los artistas de tipo 3 (Masculinos)<jupyter_code>artists_encoded[['genreEncoded', 'top']].groupby(['genreEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>Como era de esperarse la mayoría de los top estan en los genero 3 y 4 que son Urbano y Pop<jupyter_code>artists_encoded[['tempoEncoded', 'top']].groupby(['tempoEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>De la misma manera el "tempo" con mas canciones en el top 1 es el 2, tempo medio<jupyter_code>artists_encoded[['durationEncoded', 'top']].groupby(['durationEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>Respecto a la duración de las canciones están bastante repartidas aunque se ve una mayoría en la duracion 3<jupyter_code>artists_encoded[['edadEncoded', 'top']].groupby(['edadEncoded'], as_index=False).agg(['mean', 'count', 'sum'])<jupyter_output><empty_output><jupyter_text>La gran mayoría de la edad de los artistas al llevar una cancion al top 1 es de el rango 1 que corresponde a edades entre 21 y 25 años  Buscar los parámetros del Arbol de Decisión KFold crea varios subgrupos del dataset para validar  valorar los arboles con diferentes niveles de profundidadYa que se usará el arbol de clasificacion y no de decision, entonces se construye con la libreria sklearn tree.DecisionTreeClassifier: - criterion: para variables categoricas se suele usar "entropy" (ganancia de infromación) o gini para variables continuas - min_samples_split: cantidad minima de muestras que debe tener un nodo para subdividir - min_samples_leaf: cantidad minima que puede tener una hoja final - class_weight: Compensa de cierta manera el desbalance de los datos (top 0 [494] dividido entre los top 1 [141] da 3.5)todos estos parametros salen de prueba y error, visualizar los datos y el arbol y volver a intentar.<jupyter_code>cv = KFold(n_splits=10) # Numero deseado de "folds" que haremos
accuracies = list()
max_attributes = len(list(artists_encoded))
depth_range = range(1, max_attributes + 1)

# Testearemos la profundidad de 1 a cantidad de atributos +1
for depth in depth_range:
    fold_accuracy = []
    tree_model = tree.DecisionTreeClassifier(criterion='entropy',
                                             min_samples_split=20,
                                             min_samples_leaf=5,
                                             max_depth = depth,
                                             class_weight={1:3.5}) # Por defecto todas las clases igual peso
                                                                   # Columna 1 (top) con peso de 3.5
    for train_fold, valid_fold in cv.split(artists_encoded):
        f_train = artists_encoded.loc[train_fold] 
        f_valid = artists_encoded.loc[valid_fold] 

        model = tree_model.fit(X = f_train.drop(['top'], axis=1), 
                               y = f_train["top"]) 
        valid_acc = model.score(X = f_valid.drop(['top'], axis=1), 
                                y = f_valid["top"]) # calculamos la precision con el segmento de validacion
        fold_accuracy.append(valid_acc)

    avg = sum(fold_accuracy)/len(fold_accuracy)
    accuracies.append(avg)
    
# Mostramos los resultados obtenidos
df = pd.DataFrame({"Max Depth": depth_range, "Average Accuracy": accuracies})
df = df[["Max Depth", "Average Accuracy"]]
print(df.to_string(index=False))<jupyter_output>Max Depth  Average Accuracy
         1          0.556101
         2          0.556126
         3          0.564038
         4          0.642535
         5          0.599975
         6          0.628373
         7          0.643998<jupyter_text>4 niveles de profundidad porque es el mejor valor de accuracy  se multiplica por el valor de la proporción de los top 1 y no top 1   494/141 = 3.5 esto es para darle el mismo "peso" a los datos y evitar un sesgocon esto se evita el preprocesamiento de datos ya que el arbol permite hacer esto<jupyter_code># Crear arrays de entrenamiento y las etiquetas que indican si llegó a top o no 
y_train = artists_encoded['top']
x_train = artists_encoded.drop(['top'], axis=1).values 

# Crear Arbol de decision con profundidad = 4
decision_tree = tree.DecisionTreeClassifier(criterion='entropy',
                                            min_samples_split=20,
                                            min_samples_leaf=5,
                                            max_depth = 4,
                                            class_weight={1:3.5})
decision_tree.fit(x_train, y_train)

# exportar el modelo a archivo .dot
with open(r"tree1.dot", 'w') as f:
     f = tree.export_graphviz(decision_tree,
                              out_file=f,
                              max_depth = 7,
                              impurity = True,
                              feature_names = list(artists_encoded.drop(['top'], axis=1)),
                              class_names = ['No', 'N1 Billboard'],
                              rounded = True,
                              filled= True )
        
# Convertir el archivo .dot a png para poder visualizarlo
check_call(['dot','-Tpng',r'tree1.dot','-o',r'tree1.png'])
PImage("tree1.png")<jupyter_output><empty_output><jupyter_text>Precisión del árbol<jupyter_code>acc_decision_tree = round(decision_tree.score(x_train, y_train) * 100, 2)
print(acc_decision_tree,'%')
print(artists_billboard.shape)

artists_billboard.info<jupyter_output>(635, 18)<jupyter_text>ver las variables principales<jupyter_code>caract = 6
plt.figure(figsize=(14,6))
plt.barh(range(caract), decision_tree.feature_importances_)
plt.yticks(np.arange(caract), list(artists_billboard))
plt.xlabel('Importancia de las características')
plt.ylabel('características')<jupyter_output><empty_output><jupyter_text>Predicción del árbol de decisión<jupyter_code>#predecir artista <NAME> featuring <NAME>
# con su canción Havana llego a numero 1 Billboard US en 2017

x_test = pd.DataFrame(columns=('top','moodEncoded', 'tempoEncoded', 'genreEncoded','artist_typeEncoded','edadEncoded','durationEncoded'))
x_test.loc[0] = (1,5,2,4,1,0,3)
y_pred = decision_tree.predict(x_test.drop(['top'], axis = 1))
print("Prediccion: " + str(y_pred))
y_proba = decision_tree.predict_proba(x_test.drop(['top'], axis = 1))
print("Probabilidad de Acierto: " + str(np.round(y_proba[0][y_pred]* 100, 2)) + "%")
#predecir artista <NAME> 
# con su canción Believer llego al puesto 42 Billboard US en 2017

x_test = pd.DataFrame(columns=('top','moodEncoded', 'tempoEncoded', 'genreEncoded','artist_typeEncoded','edadEncoded','durationEncoded'))
x_test.loc[0] = (0,4,2,1,3,2,3)
y_pred = decision_tree.predict(x_test.drop(['top'], axis = 1))
print("Prediccion: " + str(y_pred))
y_proba = decision_tree.predict_proba(x_test.drop(['top'], axis = 1))
print("Probabilidad de Acierto: " + str(np.round(y_proba[0][y_pred]* 100, 2))+"%")<jupyter_output>Prediccion: [0]
Probabilidad de Acierto: [88.89]%
{'fraction_non_alphanumeric': 0.10228260869565217, 'fraction_numerical': 0.02351449275362319, 'mean_word_length': 3.7457015130674, 'pattern_counts': {'":': 2, '<': 163, '<?xml version=': 0, '>': 162, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 60, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '40', 'dir': 'jupyter-structured-clean-dedup', 'id': '543793', 'license': 'MIT', 'n_tokens_mistral': 9445, 'n_tokens_neox': 8749, 'n_words': 2373, 'path': 'Prediccion_Billboard.ipynb', 'repo_name': 'js-munozo/Prediccion_top_billboard_100', 'size': '27621'}