Tokens

library(tidyverse)
library(knitr)
library(stringr)
library(stringi)
library(quanteda)

Arrancamos

Leemos el mismo datosautos de la vez pasada sólo que esta vez ya viene con una columna extra “cilindradaforest” que es el valor de la cilindrada por cada auto según el random forest de la vez anterior. Leemos y hacemos un par de cosas (como ajustar la cilindrada a un dígito de precisión decimal y combinar en un campo “text” las columnas title y trim).

datosautos <- read.csv(file = "datosautosf.csv", stringsAsFactors = FALSE, row.names = 1)
datosautos$cilindrada <- round(datosautos$cilindrada,1)
datosautos$text <- paste0(datosautos$TRIM, " ", datosautos$title)

head(datosautos)
##   X           id                                                title
## 1 1 MLA850265335                             Chevrolet Prisma Ls 2011
## 2 2 MLA843044678                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 3 3 MLA840209496 Chevrolet Prisma Ls 1.4 Anticipo $ 145 Contado $ 275
## 4 4 MLA840017595                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 5 5 MLA851712209                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 6 6 MLA845309211                       Chevrolet Prisma Lt Imperdible
##    price currency_id listing_type_id ENGINE_DISPLACEMENT DOORS FUEL_TYPE
## 1 365000         ARS    gold_premium                1389     4     Nafta
## 2 358000         ARS            gold                1389     4     Nafta
## 3 450000         ARS            gold                1389     4     Nafta
## 4 390000         ARS          silver                1389     4     Nafta
## 5 345000         ARS            free                1389     4     Nafta
## 6 379000         ARS            gold                1389     4     Nafta
##   KILOMETERS  MODEL        TRIM VEHICLE_YEAR cilindrada cilindradaforest
## 1     155000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 2      98000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 3     130000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 4     108000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 5      90000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 6    1111111 Prisma 1.4 Lt 92cv         2011        1.4              1.4
##                                                               text
## 1                             1.4 Ls 92cv Chevrolet Prisma Ls 2011
## 2                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 3 1.4 Ls 92cv Chevrolet Prisma Ls 1.4 Anticipo $ 145 Contado $ 275
## 4                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 5                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 6                       1.4 Lt 92cv Chevrolet Prisma Lt Imperdible

Dejamos la lista de tokens en otra columna. Acá el token es simple y sólo se hace cortando por espacio dado que asumimos que estas características (al menos en principio) ya vienen bien armadas. Y si no nos vamos a dar cuenta rápido. Para eso nos vamos a ayudar con una función que creamos para este fin que nos facilite el procesamiento de los datos.

La función armar_tokens toma una cadena(string), reemplaza las comas con puntos, la pasa a minúsculas (tolower), deja sólo los caracteres de la “a” a la “z” (en minúsculas), los números y el punto, sacar los indicadores de potencia en cv (ej 106cv), todo esto se divide según los espacios (str_split) y finalmente deja sólo los tokens que no se repiten (unique).

armar_tokens <- function(string1){
    temp <- tolower(string1)
    temp <- stringr::str_replace_all(temp,",", ".")
    temp <- stringr::str_replace_all(temp,"[^a-z0-9.\\s]", " ")
    temp <- stringr::str_replace_all(temp,"[0-9]+cv", " ")
    temp <- stringr::str_split(temp, " ")
    temp <- lapply(temp, unique)
#    indexes <- which(temp == "")
#    if(length(indexes) > 0){
#      temp <- temp[-indexes]
#    } 
    return(temp)
}

datosautos$tokens <- armar_tokens(datosautos$text)
head(datosautos$tokens)
## [[1]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[2]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[3]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "anticipo" 
## [7] "145"       "contado"   "275"      
## 
## [[4]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[5]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[6]]
## [1] "1.4"        "lt"         ""           "chevrolet"  "prisma"    
## [6] "imperdible"

Hasta acá nada nuevo. Vamos a aprovechar que en todo eso hay datos que ya conocemos. A simple vista vemos que el año, la cilindrada y el modelo se pueden sacar de las columnas que ya tenemos. Con algún amasijo de datos y formato para que lo podamos usar armo tres listas y al final las sumo junto al espacio vacío ("“). También”abrimos" los nombres de modelos para que si un auto aparece con nombre compuesto como “Fiesta Kinetic Design” podamos captar si sale aunque sea “Fiesta” solamente.

listacil <- unique(datosautos$cilindrada)
listacil <- listacil[!is.na(listacil)]
listacil <- sprintf("%1.1f", listacil)
listamodelos <- tolower(unique(datosautos$MODEL))
listamodeloscomp <- unique(unlist(armar_tokens(datosautos$MODEL)))
listaanios <- sprintf("%4d",unique(datosautos$VEHICLE_YEAR))
listatokens <- unique(c(listamodelos, listamodeloscomp, listaanios, listacil, ""))
listatokens
##  [1] "prisma"                "classic"              
##  [3] "corsa classic"         "siena"                
##  [5] "logan"                 "etios"                
##  [7] "corolla"               "voyage"               
##  [9] "suran"                 "gol"                  
## [11] "207 compact"           "fiesta kinetic design"
## [13] "focus iii"             "palio"                
## [15] "clio"                  "ecosport"             
## [17] "kangoo"                "partner"              
## [19] "fox"                   "sandero"              
## [21] "ka"                    "spin"                 
## [23] "ranger"                "hilux"                
## [25] "tiida"                 "fluence"              
## [27] "meriva"                "duster"               
## [29] "corsa"                 "207"                  
## [31] "compact"               "fiesta"               
## [33] "kinetic"               "design"               
## [35] "focus"                 "iii"                  
## [37] "2011"                  "2012"                 
## [39] "2013"                  "2014"                 
## [41] "2015"                  "2016"                 
## [43] "2017"                  "2018"                 
## [45] "2019"                  "1999"                 
## [47] "2000"                  "2002"                 
## [49] "2004"                  "2005"                 
## [51] "2006"                  "2007"                 
## [53] "2008"                  "2009"                 
## [55] "2010"                  "2001"                 
## [57] "2003"                  "1.4"                  
## [59] "1.6"                   "1.7"                  
## [61] "1.3"                   "1.8"                  
## [63] "1.5"                   "2.0"                  
## [65] "1.9"                   "1.0"                  
## [67] "1.2"                   "1.1"                  
## [69] "2.5"                   "2.8"                  
## [71] "3.0"                   "2.3"                  
## [73] "2.2"                   "3.2"                  
## [75] "2.7"                   ""

El problema original de todo esto era obtener la cilindrada, eso se puede hacer con una función sencilla que detecte el token correspondiente en la lista de cilindradas (listacil) y lo devuelva. Todo eso a una nueva columna. Como esto es una lista hay que hacerlo con lapply o map, en este caso usaré el primero hasta que maneje mejor el segundo.

tokencil <- function(list1){
  cilindr <- unlist(intersect(list1, listacil))[1]
  if(length(cilindr)==0){cilindr=0}
  return(as.numeric(cilindr))
}
datosautos$cilindradatokens <- unlist(lapply(datosautos$tokens, tokencil))
head(datosautos)
##   X           id                                                title
## 1 1 MLA850265335                             Chevrolet Prisma Ls 2011
## 2 2 MLA843044678                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 3 3 MLA840209496 Chevrolet Prisma Ls 1.4 Anticipo $ 145 Contado $ 275
## 4 4 MLA840017595                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 5 5 MLA851712209                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 6 6 MLA845309211                       Chevrolet Prisma Lt Imperdible
##    price currency_id listing_type_id ENGINE_DISPLACEMENT DOORS FUEL_TYPE
## 1 365000         ARS    gold_premium                1389     4     Nafta
## 2 358000         ARS            gold                1389     4     Nafta
## 3 450000         ARS            gold                1389     4     Nafta
## 4 390000         ARS          silver                1389     4     Nafta
## 5 345000         ARS            free                1389     4     Nafta
## 6 379000         ARS            gold                1389     4     Nafta
##   KILOMETERS  MODEL        TRIM VEHICLE_YEAR cilindrada cilindradaforest
## 1     155000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 2      98000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 3     130000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 4     108000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 5      90000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 6    1111111 Prisma 1.4 Lt 92cv         2011        1.4              1.4
##                                                               text
## 1                             1.4 Ls 92cv Chevrolet Prisma Ls 2011
## 2                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 3 1.4 Ls 92cv Chevrolet Prisma Ls 1.4 Anticipo $ 145 Contado $ 275
## 4                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 5                    1.4 Ls 92cv Chevrolet Prisma 1.4 Ls 92cv 2011
## 6                       1.4 Lt 92cv Chevrolet Prisma Lt Imperdible
##                                                      tokens
## 1                        1.4, ls, , chevrolet, prisma, 2011
## 2                        1.4, ls, , chevrolet, prisma, 2011
## 3 1.4, ls, , chevrolet, prisma, anticipo, 145, contado, 275
## 4                        1.4, ls, , chevrolet, prisma, 2011
## 5                        1.4, ls, , chevrolet, prisma, 2011
## 6                  1.4, lt, , chevrolet, prisma, imperdible
##   cilindradatokens
## 1              1.4
## 2              1.4
## 3              1.4
## 4              1.4
## 5              1.4
## 6              1.4

Si corren el código completo van a ver que en las columnas donde detecta cilindrada en el texto del título o del trim (modelo) lo va a levantar y poner como dato, si no deja NA. Veamos los primeros casos a ver que traen, comparando con los resultados el primero y el sexto no tienen un token asimilable a una cilindrada entonces queda en NA, para el resto lo detecta y carga.

head(datosautos$tokens)
## [[1]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[2]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[3]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "anticipo" 
## [7] "145"       "contado"   "275"      
## 
## [[4]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[5]]
## [1] "1.4"       "ls"        ""          "chevrolet" "prisma"    "2011"     
## 
## [[6]]
## [1] "1.4"        "lt"         ""           "chevrolet"  "prisma"    
## [6] "imperdible"

De ahora en adelante quedan dos cosas: definir cuál de las tres columnas de cilindrada queda y levantar la info de cada modelo. Lo primero es dentro de todo fácil. Vamos a leer la columna cilindradatoken, si no es NA nos quedamos con esa, si no leemos la que viene por tabla (cilindrada) y si esa también está vacía nos quedamos con la que fue calculada por el random forest. Fun fact: todo esto por que el Clio si bien se auspicia como 1.2 tiene motor de 1149cm3, al redondear queda 1.1 y quedarían dos categorías para el mismo tamaño de motor. Con esto evitamos en lo posible esos temas.

datosautos$cilindradafinal <- ifelse(is.na(datosautos$cilindradatokens)==TRUE, (ifelse(is.na(datosautos$cilindrada)==TRUE, datosautos$cilindradaforest, datosautos$cilindrada)), datosautos$cilindradatokens)

Veamos cómo estamos en cada columna. Al caer en la cilindrada provista por el random forest en caso de no encontrar otra tanto esa como la final son 0 pero lo que nos interesa son las otras dos, las que no llega a completar por tabla.

datosautos %>% select(cilindrada, cilindradaforest, cilindradatokens, cilindradafinal) %>% map(~sum(is.na(.)))
## $cilindrada
## [1] 3140
## 
## $cilindradaforest
## [1] 0
## 
## $cilindradatokens
## [1] 1033
## 
## $cilindradafinal
## [1] 0

Entonces por tabla faltaban 3140 datos y por tokens de descripción quedaron afuera 1033. Esto cierra la parte original que era calcular la cilindrada faltante, se hizo oportunamente con OneR, con el Random Forest y ahora combinando diferentes métodos.

Vamos por la segunda parte: asociar características. En principio vamos a querer saber qué tokens están más asociados a determinado modelo de auto para ir viendo como podemos encarar el problema de la clasificación. O sea lo que quiero saber es para cada auto que modelos específicos tiene (ejemplo: el Gol viene en versiones “GL”, “CL”, etc mientras que el Palio podría ser “EL”, “HX” o “adventure”). No tengo una lista de modelos por auto de esa forma, así que habrá que construirla con lo que hay. Notar que este dato no viene por campo así que lo vamos a tener que buscar en la lista de tokens que ya tenemos.

Recordar que teníamos la lista de los tokens que ya conocíamos de las columnas que esperamos ver de las columnas que ya teníamos. O sea en la lista de tokens tipo “chevrolet” “prisma” “1.4” “joy” “aire” “2014” “130.000km” podemos afirmar que “prisma” es el modelo (MODEL), 2014 el año (VEHICLE_YEAR) y “1.4” la cilindrada. Como esos datos ya los tenemos y sabemos que significan los vamos a sacar así podemos precisar mejor qué es el resto.

Con una función y un lapply vamos buscando en cada lista de tokens los que matchean con características conocidas y los mandamos al cielo de los datos.

sacartoken <- function(list1){
  salida <- setdiff(list1, listatokens)
  return(salida)
}
datosautos$tokens <- lapply(datosautos$tokens, sacartoken)
head(datosautos$tokens)
## [[1]]
## [1] "ls"        "chevrolet"
## 
## [[2]]
## [1] "ls"        "chevrolet"
## 
## [[3]]
## [1] "ls"        "chevrolet" "anticipo"  "145"       "contado"   "275"      
## 
## [[4]]
## [1] "ls"        "chevrolet"
## 
## [[5]]
## [1] "ls"        "chevrolet"
## 
## [[6]]
## [1] "lt"         "chevrolet"  "imperdible"

Hay un dato muy obvio ahí pero lo tiene que pensar el algoritmo, no nosotros. Movemos la columna de datos a text para que lea eso en la comparación.

datosautos$text <- ifelse(unlist(lapply(datosautos$tokens, length))==0," ", stri_paste_list(datosautos$tokens, sep = " "))
corpusdatos <- corpus(datosautos)
dfm_datos <- dfm(corpusdatos)
tokenspormodelo <- topfeatures(dfm_datos, 5, groups = "MODEL")
tokenspormodelo
## $`207 Compact`
## peugeot      xs  allure      xt      5p 
##     602     179     136     111      71 
## 
## $Classic
## chevrolet        ls       abs    airbag        lt 
##       467       308       189       184       164 
## 
## $Clio
##     renault        pack         mio     confort authentique 
##         744         381         270         172         161 
## 
## $Corolla
## toyota    xei     mt    cvt   pack 
##    894    570    377    286    206 
## 
## $`Corsa Classic`
## chevrolet        gl        aa      full        dh 
##       432       126        86        49        49 
## 
## $Duster
##   renault       4x2       ph2 privilege   confort 
##       669       576       292       223       160 
## 
## $Ecosport
##     ford      4x2 titanium       se      xls 
##     1279     1191      336      323      271 
## 
## $Etios
## toyota    xls  sedan     xs     at 
##    546    347    296    122     63 
## 
## $`Fiesta Kinetic Design`
##     ford titanium       se     plus        s 
##      867      387      318      246      200 
## 
## $Fluence
##   renault       ph2      luxe dynamique privilege 
##       366       150       127        82        76 
## 
## $`Focus III`
##  ford    se  plus sedan     s 
##   715   409   295   281   259 
## 
## $Fox
##  volkswagen comfortline           p   trendline           3 
##         481         185         145         134          91 
## 
## $Gol
## volkswagen      power          i          p        601 
##        635        436        225        117        112 
## 
## $Hilux
## toyota     cd    4x4    4x2    srv 
##   1237    850    684    605    514 
## 
## $Ka
##  ford     p   fly     5 viral 
##   784   316   249   231   223 
## 
## $Kangoo
## renault confort  furgon     ph3    1plc 
##     917     628     510     424     393 
## 
## $Logan
##     renault authentique        plus          ge      privil 
##         430         190         156         124         123 
## 
## $Meriva
## chevrolet        gl       gls      plus        aa 
##       217       147        91        88        33 
## 
## $Palio
##       fiat       fire       pack attractive          . 
##        701        282        239        196        184 
## 
## $Partner
## peugeot  furgon confort     hdi     5as 
##     547     470     444     291      81 
## 
## $Prisma
## chevrolet       ltz        lt        ls       joy 
##       473       202       158       140       133 
## 
## $Ranger
## ford   cd tdci  4x2   xl 
## 1231 1015  781  718  526 
## 
## $Sandero
##    renault       pack expression  privilege         rs 
##        571        172        114        111         90 
## 
## $Siena
##       fiat         el       fire attractive       pack 
##        357        176        117         97         95 
## 
## $Spin
## chevrolet       ltz       5as       7as        lt 
##       335       242       222       126       113 
## 
## $Suran
##  volkswagen comfortline    highline   trendline           i 
##         791         319         318         209         132 
## 
## $Tiida
## nissan  visia  tekna      5      p 
##    125     56     54     44     43 
## 
## $Voyage
##  volkswagen comfortline    trenline        plus         gnc 
##         328         178          95          64          55

Por cada modelo la asoiación más fuerte es con la marca de cada uno, ahora sí. Tengo que meterme en la lista sacar el primer elemento pero relacionándolo con cada modelo para no perder la asociación. Finalmente ponerlo en un vector para matchear y asignarle el valor de marca en el df original.

tokenspormodelo <- topfeatures(dfm_datos, 1, groups = "MODEL")
listamarcas <- lapply(tokenspormodelo, names)
datosautos$marca <- unlist(listamarcas[datosautos$MODEL])
head(datosautos)
##   X           id                                                title
## 1 1 MLA850265335                             Chevrolet Prisma Ls 2011
## 2 2 MLA843044678                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 3 3 MLA840209496 Chevrolet Prisma Ls 1.4 Anticipo $ 145 Contado $ 275
## 4 4 MLA840017595                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 5 5 MLA851712209                    Chevrolet Prisma 1.4 Ls 92cv 2011
## 6 6 MLA845309211                       Chevrolet Prisma Lt Imperdible
##    price currency_id listing_type_id ENGINE_DISPLACEMENT DOORS FUEL_TYPE
## 1 365000         ARS    gold_premium                1389     4     Nafta
## 2 358000         ARS            gold                1389     4     Nafta
## 3 450000         ARS            gold                1389     4     Nafta
## 4 390000         ARS          silver                1389     4     Nafta
## 5 345000         ARS            free                1389     4     Nafta
## 6 379000         ARS            gold                1389     4     Nafta
##   KILOMETERS  MODEL        TRIM VEHICLE_YEAR cilindrada cilindradaforest
## 1     155000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 2      98000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 3     130000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 4     108000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 5      90000 Prisma 1.4 Ls 92cv         2011        1.4              1.4
## 6    1111111 Prisma 1.4 Lt 92cv         2011        1.4              1.4
##                                    text
## 1                          ls chevrolet
## 2                          ls chevrolet
## 3 ls chevrolet anticipo 145 contado 275
## 4                          ls chevrolet
## 5                          ls chevrolet
## 6               lt chevrolet imperdible
##                                       tokens cilindradatokens
## 1                              ls, chevrolet              1.4
## 2                              ls, chevrolet              1.4
## 3 ls, chevrolet, anticipo, 145, contado, 275              1.4
## 4                              ls, chevrolet              1.4
## 5                              ls, chevrolet              1.4
## 6                  lt, chevrolet, imperdible              1.4
##   cilindradafinal     marca
## 1             1.4 chevrolet
## 2             1.4 chevrolet
## 3             1.4 chevrolet
## 4             1.4 chevrolet
## 5             1.4 chevrolet
## 6             1.4 chevrolet

Volvemos al vector de tokens reconocidos ahora que tenemos las marcas reconocidas las podemos sacar también de la lista de tokens y seguir viendo que queda.

listatokens <- unique(unlist(unname(c(listatokens, listamarcas))))
listatokens
##  [1] "prisma"                "classic"              
##  [3] "corsa classic"         "siena"                
##  [5] "logan"                 "etios"                
##  [7] "corolla"               "voyage"               
##  [9] "suran"                 "gol"                  
## [11] "207 compact"           "fiesta kinetic design"
## [13] "focus iii"             "palio"                
## [15] "clio"                  "ecosport"             
## [17] "kangoo"                "partner"              
## [19] "fox"                   "sandero"              
## [21] "ka"                    "spin"                 
## [23] "ranger"                "hilux"                
## [25] "tiida"                 "fluence"              
## [27] "meriva"                "duster"               
## [29] "corsa"                 "207"                  
## [31] "compact"               "fiesta"               
## [33] "kinetic"               "design"               
## [35] "focus"                 "iii"                  
## [37] "2011"                  "2012"                 
## [39] "2013"                  "2014"                 
## [41] "2015"                  "2016"                 
## [43] "2017"                  "2018"                 
## [45] "2019"                  "1999"                 
## [47] "2000"                  "2002"                 
## [49] "2004"                  "2005"                 
## [51] "2006"                  "2007"                 
## [53] "2008"                  "2009"                 
## [55] "2010"                  "2001"                 
## [57] "2003"                  "1.4"                  
## [59] "1.6"                   "1.7"                  
## [61] "1.3"                   "1.8"                  
## [63] "1.5"                   "2.0"                  
## [65] "1.9"                   "1.0"                  
## [67] "1.2"                   "1.1"                  
## [69] "2.5"                   "2.8"                  
## [71] "3.0"                   "2.3"                  
## [73] "2.2"                   "3.2"                  
## [75] "2.7"                   ""                     
## [77] "peugeot"               "chevrolet"            
## [79] "renault"               "toyota"               
## [81] "ford"                  "volkswagen"           
## [83] "fiat"                  "nissan"

Repetimos la limpieza de tokens a ver que sigue quedando.

datosautos$tokens <- lapply(datosautos$tokens, sacartoken)
head(datosautos$tokens)
## [[1]]
## [1] "ls"
## 
## [[2]]
## [1] "ls"
## 
## [[3]]
## [1] "ls"       "anticipo" "145"      "contado"  "275"     
## 
## [[4]]
## [1] "ls"
## 
## [[5]]
## [1] "ls"
## 
## [[6]]
## [1] "lt"         "imperdible"

Bien, cada vez menos cosas. Hacemos otro análisis de características a ver cómo queda la asociación sacando las marcas.

datosautos$text <- ifelse(unlist(lapply(datosautos$tokens, length))==0," ", stri_paste_list(datosautos$tokens, sep = " "))
corpusdatos <- corpus(datosautos)
dfm_datos <- dfm(corpusdatos)
tokenspormodelo <- topfeatures(dfm_datos, 5, groups = "MODEL")
tokenspormodelo
## $`207 Compact`
##       xs   allure titanium       xt    sedan 
##      140      119      113       67       58 
## 
## $Classic
##     ls    abs airbag     lt   pack 
##    307    188    183    163    137 
## 
## $Clio
##    pack     mio    plus confort       o 
##     363     266     216     168     147 
## 
## $Corolla
##  xei   mt  cvt pack    g 
##  522  377  286  207  169 
## 
## $`Corsa Classic`
##  gl  aa gnc  dh  lt 
## 113  84  49  47  40 
## 
## $Duster
##       4x2       ph2 privilege   confort       4x4 
##       422       271       165       122       102 
## 
## $Ecosport
##      4x2 titanium       se     my10     plus 
##     1142      336      323      228      189 
## 
## $Etios
##   xls sedan    xs    at     x 
##   298   259   106    77    49 
## 
## $`Fiesta Kinetic Design`
##       se     plus titanium        s    sedan 
##      383      292      290      242      214 
## 
## $Fluence
##  ph2   gl luxe  gls plus 
##  150  113   95   74   72 
## 
## $`Focus III`
##    se  plus     s sedan   at6 
##   338   234   229   209   163 
## 
## $Fox
##        pack comfortline     confort   trendline           p 
##         120         113          86          86          78 
## 
## $Gol
## power     i     p   601     3 
##   418   216   107   104    91 
## 
## $Hilux
##  cd 4x4 4x2 srv   i 
## 848 593 533 452 316 
## 
## $Ka
##     p     5   fly viral   sel 
##   315   247   191   168   147 
## 
## $Kangoo
## confort  furgon     ph3    1plc       2 
##     657     618     422     370     316 
## 
## $Logan
## authentique        plus          ge      privil  expression 
##         170         146         124         123          78 
## 
## $Meriva
##       4x2 privilege dynamique      plus   confort 
##       154        59        53        48        38 
## 
## $Palio
##       pack       fire          . attractive        top 
##        246        233        211        196        125 
## 
## $Partner
##     confort      furgon         hdi         5as comfortline 
##         339         333         231          81          72 
## 
## $Prisma
## ltz  lt  ls joy gnc 
## 202 158 140 133  45 
## 
## $Ranger
##   cd tdci  4x2  4x4   xl 
##  966  780  679  548  431 
## 
## $Sandero
##       pack expression  privilege         rs        nac 
##        111        109        108         90         74 
## 
## $Siena
##         el       pack attractive       fire        gnc 
##        173        126         97         84         64 
## 
## $Spin
## ltz 5as 4x2  xl   i 
## 126 122 111  96  94 
## 
## $Suran
##    highline comfortline   trendline         msi         11b 
##         289         288         203          87          82 
## 
## $Tiida
##   confort dynamique      luxe privilege         . 
##        40        35        25        24        15 
## 
## $Voyage
## comfortline    trenline           i    highline   trendline 
##         155          92          75          67          62

Lo bueno es que ahora tenemos para asociar por marca también a ver si sale algo más limpio.

topfeatures(dfm_datos, 10)
##     4x2      cd    plus    pack confort       .      se     4x4     gnc 
##    3091    2047    1828    1660    1656    1460    1374    1367     984 
##  furgon 
##     978
topfeatures(dfm_datos, 10, groups = "marca")
## $chevrolet
##     ls     lt    ltz    4x2    abs airbag    gnc     aa     gl      . 
##    483    417    329    265    201    189    183    161    157    153 
## 
## $fiat
##       pack       fire attractive          .         el        top 
##        372        317        293        232        173        125 
##        gnc        seg  seguridad         aa 
##        123        100         86         85 
## 
## $ford
##      4x2       se       cd     plus     tdci        s titanium      4x4 
##     1821     1185      987      878      812      688      688      574 
##       xl    sedan 
##      534      438 
## 
## $nissan
##   confort dynamique      luxe privilege         .       cvt       gnc 
##        40        35        25        24        15        13        12 
##         t       con        mt 
##        11        10        10 
## 
## $peugeot
##  confort   furgon      hdi       xs   allure titanium        5        . 
##      339      333      278      140      119      113      104       92 
##      5as        p 
##       81       72 
## 
## $renault
##     confort        plus      furgon        pack         4x2 authentique 
##         960         690         618         578         472         442 
##         ph3         ph2   privilege        1plc 
##         423         422         377         370 
## 
## $toyota
##   cd  4x4  xei  4x2  srv   mt pack   at    i  xls 
##  848  593  571  533  452  420  391  390  317  298 
## 
## $volkswagen
## comfortline       power    highline   trendline           i           p 
##         593         427         421         378         359         192 
##         gnc           3           .           5 
##         160         151         147         144
topfeatures(dfm_datos, 10, groups = "MODEL")
## $`207 Compact`
##       xs   allure titanium       xt    sedan        .       5p        5 
##      140      119      113       67       58       53       53       47 
##      hdi   active 
##       47       39 
## 
## $Classic
##     ls    abs airbag     lt   pack spirit     aa    gnc      .     da 
##    307    188    183    163    137    101     64     61     40     33 
## 
## $Clio
##        pack         mio        plus     confort           o authentique 
##         363         266         216         168         147         128 
##           m         xls         abs        abcp 
##         114          83          78          75 
## 
## $Corolla
##         xei          mt         cvt        pack           g          se 
##         522         377         286         207         169         167 
##         xli          at           . comfortline 
##         149         142          61          50 
## 
## $`Corsa Classic`
##    gl    aa   gnc    dh    lt  full    ls super     3  fire 
##   113    84    49    47    40    39    36    36    28    27 
## 
## $Duster
##       4x2       ph2 privilege   confort       4x4      plus      luxe 
##       422       271       165       122       102        98        97 
##       ltz       abs        lt 
##        93        77        76 
## 
## $Ecosport
##       4x2  titanium        se      my10      plus       xls freestyle 
##      1142       336       323       228       189       189       172 
##       mp3        xl       gnc 
##       128       103        85 
## 
## $Etios
##     xls   sedan      xs      at       x     xei       .       5 puertas 
##     298     259     106      77      49      49      46      46      43 
##    my19 
##      40 
## 
## $`Fiesta Kinetic Design`
##         se       plus   titanium          s      sedan powershift 
##        383        292        290        242        214        118 
##          .         mt         5p         kd 
##         55         52         50         47 
## 
## $Fluence
##       ph2        gl      luxe       gls      plus      pack dynamique 
##       150       113        95        74        72        66        41 
## privilege       gnc         . 
##        40        31        25 
## 
## $`Focus III`
##       se     plus        s    sedan      at6       mt titanium        5 
##      338      234      229      209      163      155       62       60 
##        .       5p 
##       59       52 
## 
## $Fox
##        pack comfortline     confort   trendline           p    highline 
##         120         113          86          86          78          60 
##           5 confortline           3         saf 
##          53          48          47          47 
## 
## $Gol
## power     i     p   601     3    ps    ac     5   701     . 
##   418   216   107   104    91    86    86    75    64    41 
## 
## $Hilux
##    cd   4x4   4x2   srv     i    dx    sr   srx cuero  pack 
##   848   593   533   452   316   243   199   198   192   183 
## 
## $Ka
##     p     5   fly viral   sel    se   ltz     s   5as     4 
##   315   247   191   168   147   141   116   111   101    92 
## 
## $Kangoo
## confort  furgon     ph3    1plc       2      lc      da      aa     5as 
##     657     618     422     370     316     312     219     218     215 
##      cd 
##     161 
## 
## $Logan
## authentique        plus          ge      privil  expression         nac 
##         170         146         124         123          78          73 
##   privilege         xls       sedan         gnc 
##          64          50          42          40 
## 
## $Meriva
##        4x2  privilege  dynamique       plus    confort         gl 
##        154         59         53         48         38         34 
##        4x4 expression        ph2          . 
##         26         23         22         19 
## 
## $Palio
##       pack       fire          . attractive        top        seg 
##        246        233        211        196        125         97 
##  seguridad      nuevo         aa  adventure 
##         69         68         68         65 
## 
## $Partner
##     confort      furgon         hdi         5as comfortline           p 
##         339         333         231          81          72          68 
##           5   trendline           3    presence 
##          57          48          44          43 
## 
## $Prisma
##        ltz         lt         ls        joy        gnc         at 
##        202        158        140        133         45         41 
##          . imolaautos          t         km 
##         33         25         20         19 
## 
## $Ranger
##      cd    tdci     4x2     4x4      xl     xlt limited  safety     xls 
##     966     780     679     548     431     313     216     176     167 
##       d 
##     165 
## 
## $Sandero
##        pack  expression   privilege          rs         nac           . 
##         111         109         108          90          74          68 
##         fly authentique      tattoo       viral 
##          57          56          55          54 
## 
## $Siena
##         el       pack attractive       fire        gnc         da 
##        173        126         97         84         64         53 
##         my      rstii    confort        elx 
##         28         27         25         24 
## 
## $Spin
## ltz 5as 4x2  xl   i  dc 4x4 7as xlt  lt 
## 126 122 111  96  94  85  60  59  57  56 
## 
## $Suran
##    highline comfortline   trendline         msi         11b     imotion 
##         289         288         203          87          82          77 
##         11c         11a           i         gnc 
##          74          70          66          59 
## 
## $Tiida
##   confort dynamique      luxe privilege         .       cvt       gnc 
##        40        35        25        24        15        13        12 
##         t       con        mt 
##        11        10        10 
## 
## $Voyage
## comfortline    trenline           i    highline   trendline         gnc 
##         155          92          75          67          62          57 
##        plus confortline         60a         abs 
##          46          28          28          27

En algunas marcas/modelos se va viendo como se aproxima la lista. Acá es un poco arbitrario pero voy a sacar a mano algunos tokens que sabemos que no son específicos de cada modelo.

listatokens <- unique(unlist(unname(c(listatokens, "4x2", "4x4", "gnc", "aa", "cvt", "p", "i", ".", "o", "m", "t", "3", "5", "5as"))))
datosautos$tokens <- lapply(datosautos$tokens, sacartoken)
#head(datosautos$tokens)
datosautos$text <- ifelse(unlist(lapply(datosautos$tokens, length))==0," ", stri_paste_list(datosautos$tokens, sep = " "))
corpusdatos <- corpus(datosautos)
dfm_datos <- dfm(corpusdatos)
topfeatures(dfm_datos, 10)
##       cd     plus  confort     pack        .       se   furgon    sedan 
##     2040     1828     1657     1656     1400     1373      974      851 
##     tdci titanium 
##      830      802
topfeatures(dfm_datos, 10, groups = "FUEL_TYPE")
## $Diésel
##      cd    tdci     srv      xl confort      at  furgon     xlt      dx 
##    1805     726     503     400     363     303     292     291     278 
##     cab 
##     266 
## 
## $Eléctrico
##     simple        cab         dx         ls   anticipo        145 
##          1          1          1          0          0          0 
##    contado        275         lt imperdible 
##          0          0          0          0 
## 
## $GNC
##    pack confort      el       .      da       2     con  furgon    plus 
##      10      10       9       8       8       7       7       6       5 
##      se 
##       5 
## 
## $`Híbrido/Nafta`
##         lt          2       gris       pack        cpm         da 
##          1          1          1          1          1          1 
##         el attractive    confort  trendline 
##          1          1          1          1 
## 
## $Nafta
##        plus          se        pack     confort           .       sedan 
##        1500        1314        1277        1162        1070         806 
##    titanium          mt           s comfortline 
##         733         676         657         612 
## 
## $`Nafta/GNC`
##     confort        pack        plus      furgon          ls           . 
##         121         110          97          82          77          68 
##         ph3          lt comfortline         ph2 
##          59          57          50          48

Lo podemos ver gráficamente. Hasta acá llegué por ahora.

datosautos$text <- paste0(datosautos$text, " ", datosautos$marca)
corpusdatos <- corpus(datosautos)
dfm_datos <- dfm(corpusdatos)
dfm_datos_trim <- dfm_trim(dfm_datos, min_termfreq = 300, max_termfreq = 7000)
textplot_network(dfm_datos_trim, min_freq = 300)
## Registered S3 method overwritten by 'network':
##   method            from    
##   summary.character quanteda