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í:






















Script python:
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 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):

  if i == 0:
   if output_type == 'sql_query':
    print 'case when '+variable+' < '+str(cuantiles[i+1])+' then 1 else 0 end as '+variable+'_q'+str(i)+','
   elif output_type == 'qlik_query':
    print 'if('+variable+ ' < '+str(cuantiles[i+1])+', 1, 0) as '+variable+'_q'+str(i)+','

  elif val == cuantiles[-2]:
   if output_type == 'sql_query':
    print 'case when '+variable+' >= '+str(val)+' then 1 else 0 end as '+variable+'_q'+str(i)+','
   elif output_type == 'qlik_query':
    print 'if('+variable+' >= '+str(val)+', 1, 0) as '+variable+'_q'+str(i)+','
   break

  else:
   if output_type == 'sql_query':
    print 'case when '+variable+' >= '+str(val)+' and '+variable+' < '+str(cuantiles[i+1])+' then 1 else 0 end as '+variable+'_q'+str(i)+','
   elif output_type =='qlik_query':
    print 'if('+variable+ ' >= '+str(val)+' and '+variable+' < '+str(cuantiles[i+1])+', 1, 0) as '+variable+'_q'+str(i)+','

# Ejecucion
df = pd.read_csv('https://www.dropbox.com/s/ed4j8l550zdy78j/churn3.csv?dl=1')
variable = 'total_day_calls'
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