EL DataSet

El DataSet es un archivo que contiene una matriz de información, usualmente cada fila es un dato y cada columna son los atributos de cada dato, los DataSet´s trabajados están en formato ".json" cuyas siglas, en inglés, vienen de "JavaScript Object Notation" y es un tipo de archivo comúnmente utilizado para el intercambio de información y es un subconjunto de la notación literal de objetos de JavaScript. Como ya se indicó, se escogieron dos DataSet´s de Amazon de la subcategoría de “VideoGames” pero no se trabajó con el Data Set completo que contiene toda la información pues la capacidad de procesamiento de un computador común no es suficiente para analizar esta cantidad de datos en un tiempo razonable.

Los atributos de “Reviews” son:
-reviewerID (ID de usuario)
-reviewerName (Nombre de Usuario)
-Helpful (cuántas personas encontraron útil la review)
-Overal (calificación de 1 a 5)
-ReviewText (texto completo)
-Summary (resumen del texto)
-UnixReviewTime (fecha del review en formato unix)
-ReviewTime (fecha del review en formato normal)
-asin (código del producto)

Los atributos de “MetaData” son:
-title (título del producto)
-price (precio del producto)
-imUrl (URL de la imagen del producto)
-related (vector de los vectores; also_bought, also_viewed, bought_together y buy_after_ viewing)
    -also_bought (contiene los códigos de los demas productos que compran quienes compran el producto en cuestión)
    -also_viewed (contiene los códigos de los demás productos que observan quienes observan el producto en cuestión)
    -bought_together (contiene los códigos de los productos que se compraron en conjunto al producto en cuestión)
    -buy_after_ viewing (contiene los códigos de los productos que se compraron en después de observar al producto en cuestión)
-salesRank (ranking de ventas hasta el momento)
-brand (marca)
-categories (vector con los String’s con los nombres de los las categorías y subcategorías del producto en orden)

Primera Exploración

Para la primera exploración se vio un gran desafío, que fue la capacidad de computo del computador, pues la de un pc normal es insuficiente para procesar los 20 Gb de información que corresponden al Data Set completo de Amazon por lo tanto, como ya se indicó, se decidió por trabajar con DataSets de "subcategorías de productos", en este caso son: “reviews_Video_Games.json” y “reviews_Cell_Phones_and_Accessories.json" debido a este problema, el 90% del tiempo utilizado en exploración se perdió en abrir/crear un DataSet con el cual poder trabajar.
Para empezar con el Data Set se eliminaron las columnas ID de usuario y nombre de usuario, luego se crearon dos nuevos atributos uno que tiene la cantidad de palabras de la review y otro que dice la cantidad de reviews del mismo producto dentro del dataset. Además se filtró el Data Set de acuerdo a rating y fecha y se ordenó según rating, fecha, cantidad de palabras y cantidad de reviews.

Ahora se muestran dos Data Sets obtenidos de esta primera exploración:


Descripcion de la imagen
Foto 1: DataSet de los mejor puntuados.


Descripcion de la imagen
Foto 2: DataSet de los peor puntuados.

Código Fuente (Primera Exploración)

A continuación se presentara el código fuente de la primera exploración de los Data Sets escogidos de Amazon.

OBTENIENDO LOS DATATFRAMSE DESDE LOS ARCHIVOS .JSON

#Dataset de la categoría Videojuegos
install.packages("jsonlite") 
library(jsonlite)
archivo <- "G:/Data mining/reviews_Video_Games.json"
con <- file(archivo, open="r")
complete_json <- readLines(con)
close(con)
datojson<-paste(complete_json,collapse=",")
datojson<-paste("[",datojson,"]",ste="")
Jsondata <- fromJSON(datojson)
datos <- as.data.frame(Jsondata)
View(datos)

#Dataset de la Categoría Celulares y accesorios
archivo2 <- "G:/Data mining/reviews_Cell_Phones_and_Accessories.json"
con2 <- file(archivo2, open="r")
complete_json2 <- readLines(con2)
close(con2)
datojson2<-paste(complete_json2,collapse=",")
datojson2<-paste("[",datojson2,"]",ste="")
Jsondata2 <- fromJSON(datojson2)
datos2 <- as.data.frame(Jsondata2)
View(datos2)

ANALISIS DE LOS DATOS

#Mezclar los dos dataset
total <- rbind(datos, datos2) 
dim(total)
summary(total)

#Eliminando columnas de Usuarios
total$reviewerID <- NULL
total$reviewerName <- NULL

#Encontrando los con mejor rating del 2014
BestRating <- with(total, total[overall==5, ])
filtro <- grep("2014", BestRating$reviewTime, ignore.case=TRUE)
BestNewRating <- BestRating[filtro,]

#Encontrando los peores del 2014
WorstRating <- with(total, total[overall<=2, ])
filtro2 <- grep("2014", WorstRating$reviewTime, ignore.case=TRUE)
WorstNewRating <- WorstRating[filtro2,]
TopWorst <- WorstNewRating[order(WorstNewRating$overall, decreasing = T), ]
TopWorstOrd <- TopWorst[order(TopWorst$unixReviewTime, decreasing = T), ]


#Comentarios con mayor cantidad de palabras y añadiendolo al dataset
ComentaryWorst <-  sapply(gregexpr("[[:alpha:]]+", TopWorst$reviewText), function(x) sum(x > 0))
TopWorst$WordCount = ComentaryWorst
TopWorstOrd2 <- TopWorst[order(TopWorst$WordCount, decreasing = T), ]

#Contar cantidad de reviews por producto
library(plyr)
ReviewCount <- count(TopWorst,"asin")
Topupdates <- merge(TopWorst, ReviewCount, by="asin")
						

Pre-Procesamiento y limpieza de datos

Para realizar un pre-procesamiento correcto se combinaron los DataSet’s “MetaData” y “Reviews”; primero se trabajó con “Reviews”, este DataSet contiene la información de todos los comentarios de todos los productos de la subcategoría escogida y sus atributos se modificaron según:
-Se eliminan: reviewerID, reviewerName, Helpful, Summary, UnixReviewTime y ReviewTime
-Se mantiene: asin
Finalmente se trabaja con el atributo “ReviewText” del cual se obtienen las nuevas columnas:
-WordCountReview (cantidad de palabra del comentario)
-BlobPolarityReview (análisis de sentimiento: polaridad del comentario)
-BlobSubjetivityReview (análisis de sentimiento: subjetividad del comentario)
-VaderCompoundReview (representa un promedio compuesto de VaderPosReview, VaderNegReview y VaderNeutralReview)
-VaderPosReview (análisis de sentimiento: nivel de positivismo del comentario)
-VaderNegReview (análisis de sentimiento: nivel de negativismo del comentario)
-VaderNeutralReview (análisis de sentimiento: nivel de neutralidad del comentario)

Luego se trabajó con el “MetaData” este DataSet contiene la información de todos los productos de la subcategoría escogida y sus atributos se modificaron según:
-Se eliminan: title, imUrl, Brand y categories
-Se mantiene: Price
Luego se vio que salesRank era un diccionario que contenía la subcategoría a la que pertenecía el producto y el ranking de ventas pertinente; se procesó para que simplemente fuese un número. Finalmente related se convirtió en 4 columnas (correspondientes a los cuatro vectores que contenía este atributo), que contienen en forma de un entero la cantidad de elementos (productos) de los vectores also_bought, also_viewed, bought_together y buy_after_ viewing.

Después se unen estos DataSet’s pre-procesados utilizando el atributo “asin” y se obtiene un nuevo DataSet que ya no incluye ningún tipo de texto y solo tiene valores numéricos, amistosos con los algoritmos de clasificación y clustering. Ahora toca realizar la limpieza de datos; los datos sin precios y sin salesRank se eliminaron.

Nótese que el DataSet “Review” contiene aproximadamente un millón de datos mientras que “MetaData” contiene alrededor de cincuenta mil productos, el DataSet obtenido anteriormente se ordenó según los comentarios (un millón de datos) y se quiere un DataSet ordenado según productos (cincuenta mil datos), para esto se realizó un promedio normalizado de cada atributo con respecto a la cantidad de comentarios. Lo anterior resulta en un DataSet más pequeño de lo esperado a pesar de todo el tiempo de cálculo empleado en el pre-procesamiento (aplicar el análisis de sentimiento tomó aproximadamente 3 días); esto podría causar problemas a la hora de generalizar.

Con este DataSet se planea entrenar un clasificador con el fin de identificar productos exitosos, para esto se debe agregar un nuevo atributo, una clase, que indique si un producto es o fue exitoso en función de los comentarios y características del producto. Para lograr esto se obtuvieron los siguientes gráficos:

-Ranking: Buscando obtener un porcentaje de productos razonable, se buscó algún criterio de filtro que permitiera elegir una “elite” de productos exitosos, en este caso, se usó el Ranking (atributo “salesRank”) de los productos, mientras menor ranking más ventas. Observando este gráfico, poco se puede determinar pero dada la cantidad de productos se estimó razonable seleccionar los 15 mil productos con menor ranking, por lo que, se toman los productos con Ranking bajo 15 mil y se añade como criterio para determinar que un producto es “exitoso”.

Descripcion de la imagen
Gráfico 1: Distribución de los productos según Ranking.

-Ranking (top 15 mil): Se grafica Ranking para los productos seleccionados, donde se aprecia una distribución, más o menos, homogénea.

Descripcion de la imagen
Gráfico 2: Distribución de los productos según Ranking (top 15 mil).

-Puntaje Overall: De este grafico se tomó la decisión de “Selecionar”, a los productos que tenían un Overall sobre 4.5, pues representa un porcentaje razonable de productos para etiquetar como “deseables” o “exitosos” dentro del universo ya acotado.

Descripcion de la imagen
Gráfico 3: Distribución de los productos según puntaje Overall.

-VaderSentiment compound: Este es el criterio más interesante para seleccionar un producto “exitoso”, pues se basa –aplicando análisis de sentimiento sobre el texto- en el contenido promedio de los comentarios recibidos por este producto e indica el grado de negatividad-positividad del comentario, donde -1 es un comentario negativo y 1 es positivo. Para este criterio se determinó prudente seleccionar a los productos con un puntaje de 0.75 o mayor (comentario claramente positivo).

Descripcion de la imagen
Gráfico 4: Distribución de los productos según VaderCompound.

-Precio: Este grafico buscar responder la pregunta ¿Qué tan costosos son los productos exitosos obtenidos bajo los filtros aplicados?, se puede ver que ningún producto supera los 90 USD. Algo razonable al tratase de la categoría “VideoGames” y comprobamos que el ser exitoso, no implica ser caro (al menos en esta categoría).

Descripcion de la imagen
Gráfico 5: Distribución de los productos exitosos según precio [USD].

En resumen, los productos “exitosos” son seleccionados según; Overall ≥4.5, Ranking≤15k y VaderSent. ≥0.75 y se etiquetan en un nuevo atributo (Clase objetivo) por 1 y el resto de los productos se etiqueta con 0, de modo que los productos exitosos están representados por 1 en la clase y los productos normales (no exitosos) por 0. Luego se realiza una limpieza de datos, o sea, se eliminan los productos que tienen datos en blanco o los datos inútiles, también fue necesario eliminar 3 atributos, estos son; “Overall”, “salesRank” y “VaderCompound” con el fin de que el clasificador que se quiere entrenar no reconozca los criterios utilizados para elegir a los productos “exitosos” y reconozca patrones en el resto del análisis de sentimiento, patrones que un ser humano no podría encontrar en una base de datos de este estilo. Cabe mencionar que no fue necesario eliminar OutLayers, ya que para seleccionar a los productos interesantes se utilizaron “filtros” basados en relaciones de orden, por lo que se “comería” a cualquier OutLayer, simplemente se eliminaron atributos innecesarios, como ya se indicó más atrás.

El DataSet final obtenido -la que incluye la clase objetivo- es apropiado para entrenar a un clasificador, pero por la naturaleza del problema y el pre-procesamiento efectuado, la clase objetivo presenta un fuerte desequilibrio, es decir, hay más elemento etiquetados con 0 que con 1, tal que se cumple (N° de Productos con clase 1)/(N° de Productos con clase 0) = 0.0298. Para solucionar este problema se aplicó OverSampling en 1, resultando; (N° de Productos con clase 1)/(N° de Productos con clase 0) = 0.967 y SubSampling en 0, obteniéndose; (N° de Productos con clase 1)/(N° de Productos con clase 0) = 1.127.

Luego se procedió al entrenamiento del calificador con los DataSets obtenidos –el original, el con OverSampling y el con SubSampling-, y para el testeo de este, se reservó el 30% del DataSet utilizado para entrenar al clasificador (este porcentaje no se utilizó en el entrenamiento) con el fin de realizar el testeo del clasificador obtenido. Para cada DataSet se entrenaron 4 clasificadores – KNN N=5, Decision Tree, Gaussian Naive Bayes y Base Dummy (stratified)- a los que se le calcularon el “Score”, “Recall” y “Precision”, se muestra el Score en los siguientes gráficos (para distintos grados de OverSampling y SubSampling).

Descripcion de la imagen
Gráfico 6: Score promedio al disminuir Sub-Sampling.

Descripcion de la imagen
Gráfico 7: Score promedio al aumentar Over-Sampling.

A continuación se muestra una imagen detallada de los resultados obtenidos:

Descripcion de la imagen
Foto 3: Resultados obtenidos.

A continuación se muestra una imagen que muestra los atributos del DataSet final (post filtro):

Descripcion de la imagen
Foto 4: Atributos DataSet Final.

Código Fuente (Limpieza de datos)

A continuación se presentara el código fuente utilizado para realizar el procesamiento de datos.

#####Limpieza de datos#####################



##############################################################################################
##ADVERTENCIA: El codigo puede demorar 3 dias o mas dependiendo del tamaño del data set#######
##############################################################################################





import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set(style="ticks", color_codes=True)
from sklearn.model_selection import cross_val_score
from sklearn import metrics, cross_validation
import gzip 
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
from textblob import TextBlob


##funciones##
def parse(path): 
    g = gzip.open(path, 'rb') 
    for l in g: yield eval(l) 

def getDF(path): 
    i = 0 
    df = {} 
    for d in parse(path): 
        df[i] = d 
        i += 1 
    return pd.DataFrame.from_dict(df, orient='index') 

def word_count(string):
    if type(string)!=str:
        return 0
    tokens = string.split()
    n_tokens = len(tokens)
    return (n_tokens)

def raniking(dicc):
    return dicc[list(dicc.keys())[0]]


vader = SentimentIntensityAnalyzer()

def Sentimiento(texto):
    analysis = TextBlob(texto)
    try:
        testeo=analysis.detect_language() != 'en'
        if testeo:
            try:
                analysis=analysis.translate(to='en')
                texto = str(analysis)
            except:
                pass
    except:
        pass
    text=vader.polarity_scores(texto)
    return [text['neg'],text['neu'],text['pos'],text['compound'],analysis.sentiment.polarity,analysis.sentiment.subjectivity]


def muthelp(h):
    if h[0]==0:
        return 0.0
    else:
        return 1.*h[0]/h[1]


    
def alsob(r):
    if type(r)==float or not('also_bought' in r):
        return 0
    return len(r['also_bought'])


def aview(r):
    if type(r)==float or not('also_viewed' in r):
        return 0
    return len(r['also_viewed'])


def baftveiw(r):
    if type(r)==float or not('buy_after_viewing' in r):
        return 0
    return len(r['buy_after_viewing'])    

def bouto(r):
    if type(r)==float or not('bought_together' in r):
        return 0
    return len(r['bought_together'])  
########################################################################################
##################dataset base##########################################################
########################################################################################
data = getDF('Direccion dataset (ej: C:/Users/A/Desktop/reviews_Video_Games.json.gz)')
dfmeta=getDF('Direccion metadatos(ej: C:/Users/A/Desktop/meta_Video_Games.json.gz)')
#########################################################################################
#########################################################################################
#########################################################################################

##Eliminiacion de columnas inecesarias##


del data['reviewerID']
del data['helpful']
del data['reviewTime']
del data['unixReviewTime']
del data['summary']
del data['reviewerName']
del dfmeta['title']
del dfmeta['imUrl']
del dfmeta['brand']
del dfmeta['categories']

##Eliminacion de datos valores vacios y NaN##
dfmeta= dfmeta.dropna(subset=['salesRank'])
dfmeta= dfmeta[dfmeta["salesRank"]!={}]
dfmeta=dfmeta.reset_index(drop=True)

data=pd.merge(data,dfmeta,on='asin')
data= data.dropna(subset=['salesRank'])
data= data[data["salesRank"]!={}]
data=data.reset_index(drop=True)

del data['description']
del data['price']
del data['related']
del data['salesRank']
##Formacion de nuevas columnas##


data['word count']=data.apply(lambda row: word_count(row.reviewText), axis=1)

dfmeta['ranking']=dfmeta.apply(lambda row: raniking(row.salesRank), axis=1)
del dfmeta['salesRank']



dfmeta['also_bought']=dfmeta.apply(lambda row: alsob(row.related), axis=1)
dfmeta['also_viewed']=dfmeta.apply(lambda row: aview(row.related), axis=1)
dfmeta['buy_after_viewing']=dfmeta.apply(lambda row: baftveiw(row.related), axis=1)
dfmeta['bought_together']=dfmeta.apply(lambda row: bouto(row.related), axis=1)
del dfmeta['related']

dfmeta['descsize']=dfmeta.apply(lambda row: word_count(row.description), axis=1)
###############################


#sentimiento review #
vnegative=len(data.index)*[0]
vneutral=len(data.index)*[0]
vpositive=len(data.index)*[0]
vcompound=len(data.index)*[0]
vpolarity=len(data.index)*[0]
vsubjetivity=len(data.index)*[0]


lista=list(range(0,len(data.index),int(len(data.index)/10)))
lista.pop()
lista.append(len(data.index))


for d in range(0,9):
    for i in range(lista(d),lista(d+1)):
        ##review##
        text=data.iloc[i]['reviewText']
        vect=Sentimiento(text)
        vnegative[i]=vect[0]
        vneutral[i]=vect[1]
        vpositive[i]=vect[2]
        vcompound[i]=vect[3]
        vpolarity[i]=vect[4]
        vsubjetivity[i]=vect[5]

    data['blobPolarityReview'] = pd.Series(vpolarity, index=data.index)
    data['blobSubjetivityReview'] = pd.Series(vsubjetivity, index=data.index)
    data['vaderNegativeReview'] = pd.Series(vnegative, index=data.index)
    data['vaderNeutralReview'] = pd.Series(vneutral, index=data.index)
    data['vaderPositiveReview'] = pd.Series(vpositive, index=data.index)
    data['vaderCompoundReview'] = pd.Series(vcompound, index=data.index)
    



del data['reviewText']
##############################################################
#######se guarda data(Opcional)###############################
##############################################################
data.to_json('Direccion donde se quiere guardar/nombre archivo','records', None, 10, True, 'ms', None, False, 'gzip')

#sentimiento descripcion##

vnegatived=len(dfmeta.index)*[0]
vneutrald=len(dfmeta.index)*[0]
vpositived=len(dfmeta.index)*[0]
vcompoundd=len(dfmeta.index)*[0]
vpolarityd=len(dfmeta.index)*[0]
vsubjetivityd=len(dfmeta.index)*[0]
for i in range(len(dfmeta.index)):

    ##description##
    textd=dfmeta.iloc[i]['description']
    if type(textd)==float:
        vnegatived[i]=0.0
        vneutrald[i]=0.0
        vpositived[i]=0.0
        vcompoundd[i]=0.0
        vpolarityd[i]=0.0
        vsubjetivityd[i]=0.0
    else:
        vectd=Sentimiento(textd)
        vnegatived[i]=vectd[0]
        vneutrald[i]=vectd[1]
        vpositived[i]=vectd[2]
        vcompoundd[i]=vectd[3]
        vpolarityd[i]=vectd[4]
        vsubjetivityd[i]=vectd[5]
    
dfmeta['blobPolarityDescription'] = pd.Series(vpolarityd, index=dfmeta.index)
dfmeta['blobSubjetivityDescription'] = pd.Series(vsubjetivityd, index=dfmeta.index)
dfmeta['vaderNegativeDescription'] = pd.Series(vnegatived, index=dfmeta.index)
dfmeta['vaderNeutralDescription'] = pd.Series(vneutrald, index=dfmeta.index)
dfmeta['vaderPositiveDescription'] = pd.Series(vpositived, index=dfmeta.index)
dfmeta['vaderCompoundDescription'] = pd.Series(vcompoundd, index=dfmeta.index)
del dfmeta['description']
############################################
##############se guarda dfmeta##############
############################################
dfmeta.to_json('Direccion donde se quiere guardar metadatos/nombre archivo','records', None, 10, True, 'ms', None, False, 'gzip')

################################################################################
##############traspaso de informacio de data a dfmeta dfmeta####################
################################################################################

columnsProm=['blobPolarityReview','blobSubjetivityReview',                             
'overall'                                                                                         
,'vaderCompoundReview'               
,'vaderNegativeReview'                    
,'vaderNeutralReview'                 
,'vaderPositiveReview'                
,'word count']

def categorizador(asin,categorie):
    return np.mean(data.loc[data['asin']==asin][categorie])

for i in columnsProm:
    dfmeta[i]=dfmeta.apply(lambda row: categorizador(row.asin,i), axis=1)
    
################################################################
##############se guarda dfmeta como dataset final###############
################################################################    
    
dfmeta.to_json("C:/Users/Alvaro/Desktop/sentDescVidGam.json",'records', None, 10, True, 'ms', None, False, 'gzip')
						

Código Fuente (Clasificación)

A continuación se presentara el código fuente utilizado para entrenar a los clasificadores.

#################Clasificacion################

import pandas as pd
import numpy as np

datos=pd.read_json("Direccion de los datos del codigo anterior",'records','frame', True, True, True, True, False, False, None, None, False, None, 'gzip')

##############Esta clasificacion solo srive para los datos de videogames#################
dtaSelecta=datos.loc[(datos['overall']>=4.5)&(datos['ranking']<=15000)&(datos['vaderCompoundReview']>=0.75)]

a=dtaSelecta.index.values
def selector(i):
    if i in a:
        return 1
    else:
        return 0
datos=datos.reset_index(inplace=True)    
datos['zClases']=datos['asin'].apply(selector)


datos.to_json("Direccion",'records', None, 10, True, 'ms', None, False, 'gzip')
####los datos que se guardan incluyen mas informacion que la que se usara en el clasificador####
						

Código Fuente (Test de clasificadores)

A continuación se presentara el código fuente utilizado para testear a los clasificadores.

###Test de clasificadores, estan fuertemente basados en el laboratorio de este tema######
from sklearn.dummy import DummyClassifier
from sklearn.svm import SVC  # support vector machine classifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB  # naive bayes
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, recall_score, precision_score


def run_classifier(clf, X, y, num_tests=100):
    metrics = {'f1-score': [], 'precision': [], 'recall': []}
    
    for _ in range(num_tests):
        
        
        ### INICIO COMPLETAR ACÁ 
        #### TIP: divida el dataset, entrene y genere las predicciones.
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y)
        clf.fit(X_train, y_train)  
        predictions = clf.predict(X_test)  

        ### FIN COMPLETAR ACÁ
        
        
        
        metrics['f1-score'].append(f1_score(y_test,predictions))  # X_test y y_test deben ser definidos previamente
        metrics['recall'].append(recall_score(y_test,predictions))
        metrics['precision'].append(precision_score(y_test,predictions))
    
    return metrics


##preparacion del dataset y eliminacion de columnas que se usaron para determinar las clases###
datos=pd.read_json("Direccion de los datos del codigo anterior",'records','frame', True, True, True, True, False, False, None, None, False, None, 'gzip')
del datos['ranking']
del datos['vaderCompoundDescription']
del datos['overall']



X_orig = datos[datos.columns[:-1]] # todo hasta la penultima columna
y_orig = datos[datos.columns[-1]]

print("Distribución de clases usando (over/sub)sampling")
print()



# oversampling sobre la clase 1
###size se puede vaiar en funciona la proporcion entre los datosq ue se desee
idx = np.random.choice(datos.loc[datos.zClases == 1].index, size=38000)
data_oversampled = pd.concat([datos, datos.iloc[idx]])

print("Data oversampled on class '1'")
print(data_oversampled['zClases'].value_counts())
print()

# subsampling sobre la clase 0
###size se puede vaiar en funciona la proporcion entre los datosq ue se desee
idx = np.random.choice(datos.loc[datos.zClases == 0].index, size=39500, replace=False)
data_subsampled = datos.drop(datos.iloc[idx].index)

print("Data subsampled on class '0'")
print(data_subsampled['zClases'].value_counts())


## ejecutar este código para preparar los datos
from sklearn.metrics import classification_report

# Preparando los data frames para ser compatibles con sklearn

# datos originales 
X_orig = datos[datos.columns[:-1]] # todo hasta la penultima columna
y_orig = datos[datos.columns[-1]]

# datos "oversampleados" 
X_over = data_oversampled[dataElCastrado.columns[:-1]]
y_over = data_oversampled[dataElCastrado.columns[-1]]

# datos "subsampleados"
X_subs = data_subsampled[dataElCastrado.columns[:-1]]
y_subs = data_subsampled[dataElCastrado.columns[-1]]



####test de clasificacion#####

c0 = ("Base Dummy", DummyClassifier(strategy='stratified'))
c1 = ("Decision Tree", DecisionTreeClassifier())
c2 = ("Gaussian Naive Bayes", GaussianNB())
c3 = ("KNN", KNeighborsClassifier(n_neighbors=5))

classifiers = [c0, c1, c2, c3]


from sklearn.dummy import DummyClassifier
from sklearn.svm import SVC  # support vector machine classifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB  # naive bayes
from sklearn.neighbors import KNeighborsClassifier


c0 = ("Base Dummy", DummyClassifier(strategy='stratified'))
c1 = ("Decision Tree", DecisionTreeClassifier())
c2 = ("Gaussian Naive Bayes", GaussianNB())
c3 = ("KNN", KNeighborsClassifier(n_neighbors=5))

classifiers = [c0, c1, c2, c3]



print("orig")
for name, clf in classifiers:
    metrics = run_classifier(clf, X_orig, y_orig)   # hay que implementarla en el bloque anterior.
    print("----------------")
    print("Resultados para clasificador: ",name) 
    print("Precision promedio:",np.array(metrics['precision']).mean())
    print("Recall promedio:",np.array(metrics['recall']).mean())
    print("F1-score promedio:",np.array(metrics['f1-score']).mean())
    print("----------------\n\n")
print("over")
for name, clf in classifiers:
    metrics = run_classifier(clf, X_over, y_over)   # hay que implementarla en el bloque anterior.
    print("----------------")
    print("Resultados para clasificador: ",name) 
    print("Precision promedio:",np.array(metrics['precision']).mean())
    print("Recall promedio:",np.array(metrics['recall']).mean())
    print("F1-score promedio:",np.array(metrics['f1-score']).mean())
    print("----------------\n\n")
print("subs")    
for name, clf in classifiers:
    metrics = run_classifier(clf, X_subs, y_subs)   # hay que implementarla en el bloque anterior.
    print("----------------")
    print("Resultados para clasificador: ",name) 
    print("Precision promedio:",np.array(metrics['precision']).mean())
    print("Recall promedio:",np.array(metrics['recall']).mean())
    print("F1-score promedio:",np.array(metrics['f1-score']).mean())
    print("----------------\n\n")