David Contreras
2019-Feb-07 16:23 UTC
[R-es] Optimización identificación de casos similares
Buen día a todos, Agradezco su ayuda con lo siguiente: Tengo 100.000 registros con nombres de personas con su respectivo número de documento, quiero identificar casos que tengan un porcentaje de igualdad alto, no del 100% porque ya esos los tengo identificados, sino casos como por ejemplo: Nombre: Juan Pérez Documento: 123456789 Nombre: Juan Pérez Documento: 1234056789 Este caso sería una alerta de posible duplicado y tendría que revisarse porque posiblemente en uno de los dos casos se ingreso errado el número de documento. Para calcular esta diferencia uso la función adist del paquete (utils), el problema es que la forma en que tengo el código para revisar los 100.000 casos, la máquina no lo soporta por los recorridos que se hacen: *El dataframe se llama Citacion.* *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* *Citacion[,"RNomDoc1"]<-0* *Citacion[,"RNomDoc2"]<-0* *ii<-1* *for(ii in 1:(nrow(Citacion)-1)){* * jj<-ii+1* * while(jj<=nrow(Citacion)){* * if (adist(Citacion[ii,"NombreDoc"], Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # Criterio para marcar los posibles casos duplicados* * Citacion[ii,"RNomDoc1"]<-1* * Citacion[jj,"RNomDoc2"]<-1* * jj<-jj+1* * } else {* * Citacion[jj,"RNomDoc2"]<-0* * jj<-jj+1* * } * * } * *} * La idea es optimizar el código de alguna forma para agilizar el proceso y lograr que se identifiquen los casos a revisar. Mil gracias de nuevo. [[alternative HTML version deleted]]
Jesús Para Fernández
2019-Feb-07 16:31 UTC
[R-es] Optimización identificación de casos similares
Pues a mi se me ocurre algo chapuceril psp que puede funcionar. Separas cada dni ponkendo cada n?mero en una columna. A continuaci?n calculas las distancias y te quedas con aquellos cuya distancia sea menor o igual a nueve. Tendras mucho falso positivo, eso si, pero se podria afinar mas.... Obtener Outlook para Android<https://aka.ms/ghei36> ________________________________ From: R-help-es <r-help-es-bounces en r-project.org> on behalf of David Contreras <davidcontreras00 en gmail.com> Sent: Thursday, February 7, 2019 5:23:45 PM To: r-help-es Subject: [R-es] Optimizaci?n identificaci?n de casos similares Buen d?a a todos, Agradezco su ayuda con lo siguiente: Tengo 100.000 registros con nombres de personas con su respectivo n?mero de documento, quiero identificar casos que tengan un porcentaje de igualdad alto, no del 100% porque ya esos los tengo identificados, sino casos como por ejemplo: Nombre: Juan P?rez Documento: 123456789 Nombre: Juan P?rez Documento: 1234056789 Este caso ser?a una alerta de posible duplicado y tendr?a que revisarse porque posiblemente en uno de los dos casos se ingreso errado el n?mero de documento. Para calcular esta diferencia uso la funci?n adist del paquete (utils), el problema es que la forma en que tengo el c?digo para revisar los 100.000 casos, la m?quina no lo soporta por los recorridos que se hacen: *El dataframe se llama Citacion.* *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* *Citacion[,"RNomDoc1"]<-0* *Citacion[,"RNomDoc2"]<-0* *ii<-1* *for(ii in 1:(nrow(Citacion)-1)){* * jj<-ii+1* * while(jj<=nrow(Citacion)){* * if (adist(Citacion[ii,"NombreDoc"], Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # Criterio para marcar los posibles casos duplicados* * Citacion[ii,"RNomDoc1"]<-1* * Citacion[jj,"RNomDoc2"]<-1* * jj<-jj+1* * } else {* * Citacion[jj,"RNomDoc2"]<-0* * jj<-jj+1* * } * * } * *} * La idea es optimizar el c?digo de alguna forma para agilizar el proceso y lograr que se identifiquen los casos a revisar. Mil gracias de nuevo. [[alternative HTML version deleted]] _______________________________________________ R-help-es mailing list R-help-es en r-project.org https://stat.ethz.ch/mailman/listinfo/r-help-es [[alternative HTML version deleted]]
David Contreras
2019-Feb-07 16:40 UTC
[R-es] Optimización identificación de casos similares
Gracias Jesús por tu ayuda. El tema es que como está el código si se identifican, pero el problema es que tiene que validar cada caso con los otros 99.999 casos y ahí la máquina no soporta el proceso. *David Contreras* Estadístico Móvil 3124345188. <%2B57%20%281%29%204841410%20Ext.%20257> davidcontreras00 en gmail.com <cparra en contratista.icfes.gov.co> El jue., 7 feb. 2019 a las 11:31, Jesús Para Fernández (< j.para.fernandez en hotmail.com>) escribió:> Pues a mi se me ocurre algo chapuceril psp que puede funcionar. > > Separas cada dni ponkendo cada número en una columna. > > A continuación calculas las distancias y te quedas con aquellos cuya > distancia sea menor o igual a nueve. > > Tendras mucho falso positivo, eso si, pero se podria afinar mas.... > > Obtener Outlook para Android <https://aka.ms/ghei36> > > ------------------------------ > *From:* R-help-es <r-help-es-bounces en r-project.org> on behalf of David > Contreras <davidcontreras00 en gmail.com> > *Sent:* Thursday, February 7, 2019 5:23:45 PM > *To:* r-help-es > *Subject:* [R-es] Optimización identificación de casos similares > > Buen día a todos, > > Agradezco su ayuda con lo siguiente: > > Tengo 100.000 registros con nombres de personas con su respectivo número de > documento, quiero identificar casos que tengan un porcentaje de igualdad > alto, no del 100% porque ya esos los tengo identificados, sino casos como > por ejemplo: > > Nombre: Juan Pérez Documento: 123456789 > Nombre: Juan Pérez Documento: 1234056789 > > Este caso sería una alerta de posible duplicado y tendría que revisarse > porque posiblemente en uno de los dos casos se ingreso errado el número de > documento. > > Para calcular esta diferencia uso la función adist del paquete (utils), el > problema es que la forma en que tengo el código para revisar los 100.000 > casos, la máquina no lo soporta por los recorridos que se hacen: > > *El dataframe se llama Citacion.* > > *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", > Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* > > *Citacion[,"RNomDoc1"]<-0* > *Citacion[,"RNomDoc2"]<-0* > > *ii<-1* > *for(ii in 1:(nrow(Citacion)-1)){* > * jj<-ii+1* > * while(jj<=nrow(Citacion)){* > > * if (adist(Citacion[ii,"NombreDoc"], > Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # > Criterio para marcar los posibles casos duplicados* > * Citacion[ii,"RNomDoc1"]<-1* > * Citacion[jj,"RNomDoc2"]<-1* > * jj<-jj+1* > * } else {* > * Citacion[jj,"RNomDoc2"]<-0* > * jj<-jj+1* > * } * > * } * > > *} * > > La idea es optimizar el código de alguna forma para agilizar el proceso y > lograr que se identifiquen los casos a revisar. > > Mil gracias de nuevo. > > [[alternative HTML version deleted]] > > _______________________________________________ > R-help-es mailing list > R-help-es en r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]
Javier Marcuzzi
2019-Feb-07 18:09 UTC
[R-es] Optimización identificación de casos similares
Estimado David Contreras Puedes compilar el código, mire lo siguiente http://homepage.divms.uiowa.edu/~luke/R/compiler/compiler.pdf Javier Ruben Marcuzzi El jue., 7 feb. 2019 a las 13:24, David Contreras (< davidcontreras00 en gmail.com>) escribió:> Buen día a todos, > > Agradezco su ayuda con lo siguiente: > > Tengo 100.000 registros con nombres de personas con su respectivo número de > documento, quiero identificar casos que tengan un porcentaje de igualdad > alto, no del 100% porque ya esos los tengo identificados, sino casos como > por ejemplo: > > Nombre: Juan Pérez Documento: 123456789 > Nombre: Juan Pérez Documento: 1234056789 > > Este caso sería una alerta de posible duplicado y tendría que revisarse > porque posiblemente en uno de los dos casos se ingreso errado el número de > documento. > > Para calcular esta diferencia uso la función adist del paquete (utils), el > problema es que la forma en que tengo el código para revisar los 100.000 > casos, la máquina no lo soporta por los recorridos que se hacen: > > *El dataframe se llama Citacion.* > > *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", > Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* > > *Citacion[,"RNomDoc1"]<-0* > *Citacion[,"RNomDoc2"]<-0* > > *ii<-1* > *for(ii in 1:(nrow(Citacion)-1)){* > * jj<-ii+1* > * while(jj<=nrow(Citacion)){* > > * if (adist(Citacion[ii,"NombreDoc"], > Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # > Criterio para marcar los posibles casos duplicados* > * Citacion[ii,"RNomDoc1"]<-1* > * Citacion[jj,"RNomDoc2"]<-1* > * jj<-jj+1* > * } else {* > * Citacion[jj,"RNomDoc2"]<-0* > * jj<-jj+1* > * } * > * } * > > *} * > > La idea es optimizar el código de alguna forma para agilizar el proceso y > lograr que se identifiquen los casos a revisar. > > Mil gracias de nuevo. > > [[alternative HTML version deleted]] > > _______________________________________________ > R-help-es mailing list > R-help-es en r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]
Hola, Puedes hacerlo de otras formas sin que tengas que calcular una matriz de distancias. Calcular la matriz de distancias de todos con todos, te lleva a tener una matriz de 1e5 x 1e5 de enteros (en el mejor de los casos) y esos son ya varias decenas de gigas. Una alternativa es esta: - Calcular la distancia de Levenstein entre un DNI y la lista de DNIs. - Del resultado ver si hay alguna distancia de "1" ó de "2" que indicaría un error a la hora de introducir el valor. Si aparece lo guardas. - Y repetir este cálculo con otro DNI y así sucesivamente. - En este escenario, solo haces una comparación en cada ciclo, no consumes RAM. Solo consumes la RAM con los DNIs que vas guardando. - Aquí, lo que ocurre es que el proceso es lento en ejecución. - He probado comparando siempre el mismo DNI con una lista (siempre la misma lista), que ordeno de forma aleatoria en cada ciclo. - Y en mi máquina tarda 20min en hacer 25000 comparaciones. - Y no he parelizado el bucle. Este problema es totalmente paralelizable... Este es el código que he usado para hacer este ejemplo (sin paralelizar): #------------- library(stringdist) a <- "123456789" b <- "1234056789" c <- as.character(sample(1:1e5, 1e5, replace = FALSE)) a <- Sys.time() for( i in 1:1000) { to_compare <- sample(c(b,c), 1e5+1, replace = FALSE) res_compa <- stringdist(a, to_compare, method="dl") to_compare[ res_compa < 2] } b <- Sys.time() ; b - #------------- Saludos, Carlos Ortega www.qualityexcellence.es El jue., 7 feb. 2019 a las 17:24, David Contreras (< davidcontreras00 en gmail.com>) escribió:> Buen día a todos, > > Agradezco su ayuda con lo siguiente: > > Tengo 100.000 registros con nombres de personas con su respectivo número de > documento, quiero identificar casos que tengan un porcentaje de igualdad > alto, no del 100% porque ya esos los tengo identificados, sino casos como > por ejemplo: > > Nombre: Juan Pérez Documento: 123456789 > Nombre: Juan Pérez Documento: 1234056789 > > Este caso sería una alerta de posible duplicado y tendría que revisarse > porque posiblemente en uno de los dos casos se ingreso errado el número de > documento. > > Para calcular esta diferencia uso la función adist del paquete (utils), el > problema es que la forma en que tengo el código para revisar los 100.000 > casos, la máquina no lo soporta por los recorridos que se hacen: > > *El dataframe se llama Citacion.* > > *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", > Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* > > *Citacion[,"RNomDoc1"]<-0* > *Citacion[,"RNomDoc2"]<-0* > > *ii<-1* > *for(ii in 1:(nrow(Citacion)-1)){* > * jj<-ii+1* > * while(jj<=nrow(Citacion)){* > > * if (adist(Citacion[ii,"NombreDoc"], > Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # > Criterio para marcar los posibles casos duplicados* > * Citacion[ii,"RNomDoc1"]<-1* > * Citacion[jj,"RNomDoc2"]<-1* > * jj<-jj+1* > * } else {* > * Citacion[jj,"RNomDoc2"]<-0* > * jj<-jj+1* > * } * > * } * > > *} * > > La idea es optimizar el código de alguna forma para agilizar el proceso y > lograr que se identifiquen los casos a revisar. > > Mil gracias de nuevo. > > [[alternative HTML version deleted]] > > _______________________________________________ > R-help-es mailing list > R-help-es en r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >-- Saludos, Carlos Ortega www.qualityexcellence.es [[alternative HTML version deleted]]
No he mirado el codigo ni los datos, pero en estos asuntos de comparación la teoría dice que se ahorra tiempo si antes de comparar ordenas la columna de mayor a menor por ejemplo .... en ese caso, más allá de cierta distancia no vale la pena seguir comparando porque los números ya serán todos diferentes al que tomaste para comparar ... ahí te ahorras comparaciones ... y te puedes ahorrar algunas más ya que el número que tomas para comparar con los demás ya sabes si es igual o no a los anteriores que ya comparaste con él, de modo que no tienes que volver a compararlo ... me explico ? Creo que esas dos ideas reducirán mucho la cantidad de comparaciones que debes hacer ... si alcanzo mañana podría probar algo y comentarte. Suerte !!!! Eric. On 07/02/2019 20:48, Carlos Ortega wrote:> Hola, > > Puedes hacerlo de otras formas sin que tengas que calcular una matriz de > distancias. > > Calcular la matriz de distancias de todos con todos, te lleva a tener una > matriz de 1e5 x 1e5 de enteros (en el mejor de los casos) y esos son ya > varias decenas de gigas. > Una alternativa es esta: > > - Calcular la distancia de Levenstein entre un DNI y la lista de DNIs. > - Del resultado ver si hay alguna distancia de "1" ó de "2" que > indicaría un error a la hora de introducir el valor. Si aparece lo guardas. > - Y repetir este cálculo con otro DNI y así sucesivamente. > - En este escenario, solo haces una comparación en cada ciclo, no > consumes RAM. Solo consumes la RAM con los DNIs que vas guardando. > - Aquí, lo que ocurre es que el proceso es lento en ejecución. > - He probado comparando siempre el mismo DNI con una lista (siempre > la misma lista), que ordeno de forma aleatoria en cada ciclo. > - Y en mi máquina tarda 20min en hacer 25000 comparaciones. > - Y no he parelizado el bucle. Este problema es totalmente > paralelizable... > > Este es el código que he usado para hacer este ejemplo (sin paralelizar): > > #------------- > library(stringdist) > > a <- "123456789" > b <- "1234056789" > c <- as.character(sample(1:1e5, 1e5, replace = FALSE)) > > a <- Sys.time() > for( i in 1:1000) { > > to_compare <- sample(c(b,c), 1e5+1, replace = FALSE) > res_compa <- stringdist(a, to_compare, method="dl") > to_compare[ res_compa < 2] > > } > b <- Sys.time() ; b - > #------------- > > Saludos, > Carlos Ortega > www.qualityexcellence.es > > > El jue., 7 feb. 2019 a las 17:24, David Contreras (< > davidcontreras00 en gmail.com>) escribió: > >> Buen día a todos, >> >> Agradezco su ayuda con lo siguiente: >> >> Tengo 100.000 registros con nombres de personas con su respectivo número de >> documento, quiero identificar casos que tengan un porcentaje de igualdad >> alto, no del 100% porque ya esos los tengo identificados, sino casos como >> por ejemplo: >> >> Nombre: Juan Pérez Documento: 123456789 >> Nombre: Juan Pérez Documento: 1234056789 >> >> Este caso sería una alerta de posible duplicado y tendría que revisarse >> porque posiblemente en uno de los dos casos se ingreso errado el número de >> documento. >> >> Para calcular esta diferencia uso la función adist del paquete (utils), el >> problema es que la forma en que tengo el código para revisar los 100.000 >> casos, la máquina no lo soporta por los recorridos que se hacen: >> >> *El dataframe se llama Citacion.* >> >> *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", >> Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* >> >> *Citacion[,"RNomDoc1"]<-0* >> *Citacion[,"RNomDoc2"]<-0* >> >> *ii<-1* >> *for(ii in 1:(nrow(Citacion)-1)){* >> * jj<-ii+1* >> * while(jj<=nrow(Citacion)){* >> >> * if (adist(Citacion[ii,"NombreDoc"], >> Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # >> Criterio para marcar los posibles casos duplicados* >> * Citacion[ii,"RNomDoc1"]<-1* >> * Citacion[jj,"RNomDoc2"]<-1* >> * jj<-jj+1* >> * } else {* >> * Citacion[jj,"RNomDoc2"]<-0* >> * jj<-jj+1* >> * } * >> * } * >> >> *} * >> >> La idea es optimizar el código de alguna forma para agilizar el proceso y >> lograr que se identifiquen los casos a revisar. >> >> Mil gracias de nuevo. >> >> [[alternative HTML version deleted]] >> >> _______________________________________________ >> R-help-es mailing list >> R-help-es en r-project.org >> https://stat.ethz.ch/mailman/listinfo/r-help-es >> >
Javier Marcuzzi
2019-Feb-08 02:32 UTC
[R-es] Optimización identificación de casos similares
Estimados Si es por la cantidad de memoria, tal como indica Carlos Ortega, yo no tengo experiencia ni conocimientos para el área referida en el hilo del correo, pero sí me tocó tener que trabajar tratando de reducir la cantidad de memoria al utilizar matrices, copio y pego un ejemplo por si es de utilidad sobre sparse matrix en R, aunque debería leer si es aplicable para el caso en concreto. library('Matrix') m1 <- matrix(0, nrow = 1000, ncol = 1000) m2 <- Matrix(0, nrow = 1000, ncol = 1000, sparse = TRUE) object.size(m1) # 8000200 bytes object.size(m2) # 5632 bytes Javier Rubén Marcuzzi El jue., 7 feb. 2019 a las 20:49, Carlos Ortega (<cof en qualityexcellence.es>) escribió:> Hola, > > Puedes hacerlo de otras formas sin que tengas que calcular una matriz de > distancias. > > Calcular la matriz de distancias de todos con todos, te lleva a tener una > matriz de 1e5 x 1e5 de enteros (en el mejor de los casos) y esos son ya > varias decenas de gigas. > Una alternativa es esta: > > - Calcular la distancia de Levenstein entre un DNI y la lista de DNIs. > - Del resultado ver si hay alguna distancia de "1" ó de "2" que > indicaría un error a la hora de introducir el valor. Si aparece lo > guardas. > - Y repetir este cálculo con otro DNI y así sucesivamente. > - En este escenario, solo haces una comparación en cada ciclo, no > consumes RAM. Solo consumes la RAM con los DNIs que vas guardando. > - Aquí, lo que ocurre es que el proceso es lento en ejecución. > - He probado comparando siempre el mismo DNI con una lista (siempre > la misma lista), que ordeno de forma aleatoria en cada ciclo. > - Y en mi máquina tarda 20min en hacer 25000 comparaciones. > - Y no he parelizado el bucle. Este problema es totalmente > paralelizable... > > Este es el código que he usado para hacer este ejemplo (sin paralelizar): > > #------------- > library(stringdist) > > a <- "123456789" > b <- "1234056789" > c <- as.character(sample(1:1e5, 1e5, replace = FALSE)) > > a <- Sys.time() > for( i in 1:1000) { > > to_compare <- sample(c(b,c), 1e5+1, replace = FALSE) > res_compa <- stringdist(a, to_compare, method="dl") > to_compare[ res_compa < 2] > > } > b <- Sys.time() ; b - > #------------- > > Saludos, > Carlos Ortega > www.qualityexcellence.es > > > El jue., 7 feb. 2019 a las 17:24, David Contreras (< > davidcontreras00 en gmail.com>) escribió: > > > Buen día a todos, > > > > Agradezco su ayuda con lo siguiente: > > > > Tengo 100.000 registros con nombres de personas con su respectivo número > de > > documento, quiero identificar casos que tengan un porcentaje de igualdad > > alto, no del 100% porque ya esos los tengo identificados, sino casos como > > por ejemplo: > > > > Nombre: Juan Pérez Documento: 123456789 > > Nombre: Juan Pérez Documento: 1234056789 > > > > Este caso sería una alerta de posible duplicado y tendría que revisarse > > porque posiblemente en uno de los dos casos se ingreso errado el número > de > > documento. > > > > Para calcular esta diferencia uso la función adist del paquete (utils), > el > > problema es que la forma en que tengo el código para revisar los 100.000 > > casos, la máquina no lo soporta por los recorridos que se hacen: > > > > *El dataframe se llama Citacion.* > > > > *Citacion[,"NombreDoc"]<- paste0(Citacion[,"NOMBRE"]," ", > > Citacion[,"DOCUMENTO"]) # Concatena Nombre y documento* > > > > *Citacion[,"RNomDoc1"]<-0* > > *Citacion[,"RNomDoc2"]<-0* > > > > *ii<-1* > > *for(ii in 1:(nrow(Citacion)-1)){* > > * jj<-ii+1* > > * while(jj<=nrow(Citacion)){* > > > > * if (adist(Citacion[ii,"NombreDoc"], > > Citacion[jj,"NombreDoc"])/nchar(Citacion[ii,"NombreDoc"])<0.15){ # > > Criterio para marcar los posibles casos duplicados* > > * Citacion[ii,"RNomDoc1"]<-1* > > * Citacion[jj,"RNomDoc2"]<-1* > > * jj<-jj+1* > > * } else {* > > * Citacion[jj,"RNomDoc2"]<-0* > > * jj<-jj+1* > > * } * > > * } * > > > > *} * > > > > La idea es optimizar el código de alguna forma para agilizar el proceso y > > lograr que se identifiquen los casos a revisar. > > > > Mil gracias de nuevo. > > > > [[alternative HTML version deleted]] > > > > _______________________________________________ > > R-help-es mailing list > > R-help-es en r-project.org > > https://stat.ethz.ch/mailman/listinfo/r-help-es > > > > > -- > Saludos, > Carlos Ortega > www.qualityexcellence.es > > [[alternative HTML version deleted]] > > _______________________________________________ > R-help-es mailing list > R-help-es en r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]