sábado, 9 de diciembre de 2017

Discretizar variables continuas

Una forma de discretizar una variable continua es calcular los cuantiles y luego crear variable dummy con cada cuantil. Esta transformación es usada para entrenar modelos predictivos. Para detalle sobre cúando conviene discretizar, ver referencia 1 y 2, para otros métodos de discretización, ver referencia 3 y 4.

El siguiente script calcula los deciles de la variable total_day_calls y luego  imprime el script (sql o qlik) para crear variables dummy de cada rango.


Conceptualmente seria así:

















y la transformacion queda así:




















Python Script

import pandas as pd
import numpy as np 

# FUNCIONES
# ---------------------------------------------------------------------
def create_num_vector(df, variable):
    num_vector = df[variable]

    if num_vector.dtype == 'O':
        num_vector = num_vector.str.replace(",", ".")
        num_vector = num_vector.str.replace(" ", "")
    
    return pd.to_numeric(num_vector)

def get_quantile(num_vector, umbrales):
    q_vect = []
    for i in umbrales:
        q_vect = q_vect + [round(num_vector.quantile(i),4)]
        q_vect = list(set(q_vect))
        q_vect.sort() 
    
    return q_vect

def get_alias(variable, i):
    return variable+'_q'+str(i)+','

def print_ini(output_type, variable, cuantil, i):
    if output_type == 'sql_query':
        print('case when '+variable+' < '+cuantil+SQL_VAL+get_alias(variable, i))
    if output_type == 'qlik_query':
        print('if('+variable+ ' < '+cuantil+', 1, 0) as '+get_alias(variable, i))

def print_middle(output_type, variable, val, cuantil, i):
    val = str(val)
    if output_type == 'sql_query':
        print('case when '+variable+' >= '+val+' and '+variable+' < '+cuantil+SQL_VAL+get_alias(variable, i))
    if output_type == 'qlik_query':
        print('if('+variable+ ' >= '+val+' and '+variable+' < '+cuantil+', 1, 0) as '+get_alias(variable, i))

def print_end(output_type, variable, val, i):
    if output_type == 'sql_query':
        print('case when '+variable+' >= '+str(val)+SQL_VAL+get_alias(variable, i))
    if output_type == 'qlik_query':
        print('if('+variable+' >= '+str(val)+', 1, 0) as '+get_alias(variable, i))


def print_ranges(cuantiles, variable, output_type):
    comment_chr = {'sql_query':'-- ','qlik_query':'// ','pandas_query':'# ','r_query':'# '}
    print(comment_chr[output_type], output_type.upper(), variable.upper())

    for i, val  in enumerate(cuantiles):
        cuantil = str(cuantiles[i+1])

        if i == 0:
            print_ini(output_type, variable, cuantil, i)

        elif val == cuantiles[-2]:
            print_end(output_type, variable, val, i)
            break
        else:
            print_middle(output_type, variable, val, cuantil, i)


if __name__ == '__main__':
    df = pd.read_csv('https://www.dropbox.com/s/ed4j8l550zdy78j/churn3.csv?dl=1')
    VARIABLE = 'total_day_calls'
    SQL_VAL = ' then 1 else 0 end as '
    UMBRALES =   np.linspace(0, 1, 11)
    CUANTILES = get_quantile(create_num_vector(df, VARIABLE), UMBRALES)
    print_ranges(CUANTILES, VARIABLE, 'qlik_query')
    print_ranges(CUANTILES, VARIABLE, 'sql_query')

Referencia
1. When should we discretize
https://stats.stackexchange.com/questions/230750/when-should-we-discretize-bin-continuous-independent-variables-features-and-when

2.What is the benefit of breaking up a continuous predictor variable?
https://stats.stackexchange.com/questions/68834/what-is-the-benefit-of-breaking-up-a-continuous-predictor-variable

3. Otros metodos de transformaciones de variables continuas:
https://www.analyticsvidhya.com/blog/2015/11/8-ways-deal-continuous-variables-predictive-modeling/

4. Discretizar variables usando arbooles de decision:
https://clevertap.com/blog/how-to-convert-numerical-variables-to-categorical-variables-with-decision-trees/



No hay comentarios:

Publicar un comentario