lunes, 7 de agosto de 2017

Crear variables dummy de un texto

Para identificar la secuencia de palabras mas repetidas en un texto, y luego hacer variables dummy en SQL, teniendo algo como:
















Puede usarse el siguiente script que sigue estos pasos:
 - Identifica la cantidad de palabras consecutivas que se desa contar (word_qty) y calcula la frecuencia
 - Filtra la secuencia de palabras con una cantidad mayor al mínimo establecido (min_freq)
 - Imprime la salida en formato SQL o QlikScript (output_type)

NOTA: Para detalle sobre otras funciones de nltk.collocations, ver referencia Nro.1. Para detalle sobre otras técnicas de procesamiento del lenguaje natural (nlp), ver referencia Nro.2

Script:
import pandas as pd 
import nltk


def tuple_to_string(dict_with_tuple):
  """Convierte (('text1','text2'),num) en {'text1 text2':num}"""
  dict_with_tuple = dict(dict_with_tuple)
  return {' '.join(k): v for k, v in dict_with_tuple.iteritems()}

def xgram_finder(tokens, word_qty):
  """Contador de palabras"""
  assert 1 <= word_qty <= 4, "word_qty out of range"
  xgrams = nltk.collocations
  return(dict(nltk.FreqDist(tokens)) if word_qty == 1 else
          xgrams.BigramCollocationFinder.from_words(tokens) if word_qty == 2 else
          xgrams.TrigramCollocationFinder.from_words(tokens) if word_qty == 3 else
          xgrams.QuadgramCollocationFinder.from_words(tokens) if word_qty == 4 else 
          None)

def dict_filter(xdict, min_freq):
  """Elimina oraciones con poca frecuencia"""
  return {k: v for k, v in xdict.iteritems() if v > min_freq}

def print_query(xdict, output_type,var_name='var1',word_qty=3):
  comment_chr = {'sql_query':'-- ','qlik_query':'// ','pandas_query':'# ','r_query':'# '}
  w = str(word_qty)+'w'
  print '\n' + comment_chr[output_type], output_type.upper()
  for i, (key, value) in enumerate(xdict.iteritems()):
    print comment_chr[output_type],'Frecuencia de palabras: ', value
    if output_type == 'sql_query':
      print '(case when position(\'%s\' in lower(%s))>0 then 1 else 0 end) as cmt%s_%s,' % (key, var_name, w, i+1)
    elif output_type == 'qlik_query':
      print 'If(SubStringCount(lower(%s), \'%s\')>0,1,0) as cmt%s_%s,' % (var_name, key, w, i+1)

def sentence_freq(text_list, word_qty=3, min_freq=10, output_type='sql_query',var_name='varible'):
  grams_frq = {}
  for sentence in text_list:
    tokens = nltk.wordpunct_tokenize(sentence)
    grams = xgram_finder(tokens, word_qty)
    grams = tuple_to_string(grams.ngram_fd.items())
    for grams, freq in grams.iteritems():
      if not grams in grams_frq:
        grams_frq[grams] = freq
      else:
        grams_frq[grams] += freq
  xdict = dict_filter(grams_frq, min_freq)
  print_query(xdict,output_type,var_name, word_qty)

if __name__ == '__main__':
 data = pd.read_csv('https://www.dropbox.com/s/5164874gvdbf6ca/data_tm2.csv?dl=1', encoding='latin-1')
 text = data['comentario']
 text = text.str.lower()
 text = text.fillna('') 

 sentence_freq(text_list= text, 
      word_qty=3, 
      min_freq = 400, 
      output_type='sql_query',
      var_name = 'comentario'
...

Referencias:
1. http://www.nltk.org/howto/collocations.html
2. https://nlp.stanford.edu/IR-book/



No hay comentarios:

Publicar un comentario