lunes, 12 de febrero de 2018

Estadisticas de un Texto

El siguiente script calcula estadísticos y métricas de palabras en un texto. La mayoría de estas métricas provienen de otras publicaciones (ver Referencia 1, 2, 3 y 4).

Conceptualmente seria así:


DESCRIPCION DE METRICAS
chr_len: Cantidad de palabras únicas
chr_rt: Total de letras / Total caracteres
chr_max: Cantidad de letras de la palabra mas larga
chr_min: Cantidad de letras de la palabra mas corta
chr_avg: Cantidad de letras promedio de las palabras
chr_std: Desviación estándar de cantidad de letras de las palabras
chr_unq_rt: Cantidad palabras únicas / Total de palabras
chr_rep_rt: Cantidad de palabras repetidas/ Total de palabras
chr_upp_rt Cantidad de palabras mayúsculas / Total de palabras
chr_cpt_rt: Cantidad de palabras CapitalCases / Total de palabras
chr_cpt_ini: Tendrá valor 1 si la primera palabra es CapitalCases, sino 0
chr_tkn_qty: Cantidad de letras en el texto
chr_vcl_rt: Total de vocales / Total de letras
chr_pnt_rt: Cantidad de signos puntuación / Total de palabras
chr_1gram_rt: Cantidad de palabras de una letra / Total de palabras
chr_2gram_rt: Cantidad de palabras de dos letra / Total de palabras
chr_3gram_rt: Cantidad de palabras de tres letra / Total de palabras
chr_4gram_rt: Cantidad de palabras de cuatro letra / Total de palabras
chr_Lgram_rt: Cantidad de palabras con mas de ocho letras / Total de palabras

script
Preview:
# LIBRERIAS y FUNCIONES
# ----------------------------------------------------------------------------
library(stringr)

text_stats = function(xvec){
  # VECTORES
  chr_len<-chr_rt<-chr_max<-chr_min<-chr_avg<-chr_std<-NA
  chr_unq_rt<-chr_rep_rt<-chr_upp_rt<-chr_pnt_rt<-NA
  chr_cpt_rt<-chr_cpt_ini<-chr_tkn_qty<-chr_vcl_rt<-NA 
  chr_1gram_rt<-chr_2gram_rt<-chr_3gram_rt<-chr_4gram_rt<-chr_Lgram_rt<-NA
  
  for (i in 1:length(xvec)){
    # VARIABLES
    txt_cln = trimws(gsub("[^[:alpha:] ]", "", xvec[i]))
    txt_cln = ifelse(txt_cln=='',' ',txt_cln)
    tkn = strsplit(txt_cln, "\\s+")[[1]]
    tkn_lw = tolower(tkn)
    tkn_lw_tbl = table(tkn_lw)
    tkn_len = nchar(tkn_lw)
    upp_qty = str_count(txt_cln, "\\b[A-Z]{1,}\\b")
    cpt_qty = str_count(txt_cln, "(\\b[A-Z]+([a-z]))")
    vocals_qty = sum(str_count(tolower(txt_cln), c('a','e','i','o','u')))
    # STATS
    chr_len[i] = length(unique(names(tkn_lw_tbl)[names(tkn_lw_tbl)!='']))
    chr_rt[i] = nchar(txt_cln) / nchar(as.character(xvec[i]))
    chr_max[i] = max(tkn_len)
    chr_min[i] = min(tkn_len)
    chr_avg[i] = mean(tkn_len) # avg word len
    chr_std[i] = sd(tkn_len, na.rm = TRUE)
    chr_unq_rt[i] = length(tkn_lw_tbl[tkn_lw_tbl==1 & names(tkn_lw_tbl) !=''])/length(tkn_lw)
    chr_rep_rt[i] = length(tkn_lw_tbl[tkn_lw_tbl>1]) / length(tkn_lw)
    chr_upp_rt[i] = upp_qty  / length(tkn)
    chr_cpt_rt[i] = cpt_qty / length(tkn)
    chr_cpt_ini[i] = str_count(tkn[1], "(\\b[A-Z]+([a-z]))")
    chr_tkn_qty[i] = sum(tkn_len)
    chr_vcl_rt[i] = vocals_qty / sum(tkn_len)
    chr_pnt_rt[i] = str_count(xvec[i], "[[:punct:]]") / length(tkn_lw)
    chr_1gram_rt[i] = length(tkn_len[tkn_len==1]) / length(tkn_lw)
    chr_2gram_rt[i] = length(tkn_len[tkn_len==2]) / length(tkn_lw)
    chr_3gram_rt[i] = length(tkn_len[tkn_len==3]) / length(tkn_lw)
    chr_4gram_rt[i] = length(tkn_len[tkn_len==4]) / length(tkn_lw)
    chr_Lgram_rt[i] = length(tkn_len[tkn_len>=8]) / length(tkn_lw)  
  }
  # DATA FRAME
  xdf = data.frame(chr_len, chr_rt, chr_max, chr_min, chr_avg, chr_std, chr_unq_rt, 
                   chr_rep_rt, chr_upp_rt,chr_cpt_rt, chr_cpt_ini, chr_tkn_qty,chr_vcl_rt, chr_pnt_rt,
                   chr_1gram_rt, chr_2gram_rt, chr_3gram_rt, chr_4gram_rt, chr_Lgram_rt)
  xdf[is.na(xdf)] = 0   
  return(xdf)
} 

# EJEMPLO
#--------------------------------------------------------------
df1 = data.frame(tx = c('ejemplo uno, y ejemplo dos',
                        'EJEMPLO uno EJEMPLO dos EJEMPLO tres',
                        'ejemplos de palabras diversas consecutivas',
                        'Palabras consecutivas de diversidad aleatoria',
                        'Aleatoriedad expresada en palabras',
                        'eje dos tres y cuatro'))

(df_stats = text_stats(df1$tx)) 
...

REFERENCIAS:
1. Vandalism Detection in Wikidata (Ver seccion 3.1.1): 
https://arxiv.org/ftp/arxiv/papers/1712/1712.06919.pdf
2. Web que calcula metricas de un texto:
http://textalyser.net/
3.Gunning fog index:
https://en.wikipedia.org/wiki/Gunning_fog_index
4. Introduction to Information Retrieval
https://nlp.stanford.edu/IR-book/html/htmledition/features-for-text-1.html




No hay comentarios:

Publicar un comentario