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