Comparacion de cadenas, mediante aproximacion con python.

El problema a resolver es el siguiente es combinar los dos catálogos de productos farmacéuticos. Uno lo tengo car cargado en web que tiene relacionada al producto, la imagen en formato PNG de la caja que lo contiene, pero que no corresponde a lo que en realidad la farmacia vende.

El segundo catalogo real que manejan en la farmacia, que son en realidad los productos que venden al publico, el problema es que en este catalogo REAL, no sabemos que imagenes PNG le corresponden a cada registro.
Lo que haremos es un script que recorre el catalogo que tenemos en web, registro por registro y buscara a cual registro en el catalogo REAL le corresponde. Para realizar esta operación, tomaremos la descripcion del registro del catalogo WEB y haremos un proceso de comparacion para saber a que descripcion del catalogo real se aproxima mas y de esta forma sabremos que registros corresponden y asi saber que imagen le va a cada registro del catalogo REAL.

Los catalogos se ven asi:

Catalogo WEB

Codigo    Descripcion            Imagen
 001     ACARBOSA c/30 TABS. 50 MG.    sheet01/imagen0001.png
 ...
 ..
 .

Catalogo REAL

Codigo    Descripcion            Precio1    Precio2        Etc    Etc.
.
..
...
32267    G.I ACARBOSA 30 TABS 50MG    $XX.XX    $XX.XX        ETC    ETC.
...
..
.

Podemos darnos cuenta que el registro 001 del WEB le corresponde al codigo 32267 del catalogo REAL, pero las cadenas de la descripción no son exactamente iguales lo que nos hace que no podamos hacer una comparación directa de las cadenas.

Para resolver esto intentaremos hacer una comparación de palabra por palabra y hacer un sistema de «scores» para saber que descripción del catalogo WEB se «aproxima» mas a alguna del catalogo REAL.

El script esta hecho en python por la facilidad que tiene este lenguaje para manejar cadenas.

Comenzamos de esta forma

for i in range(len(lines_web)):
   des_web = lines_web[i].split('\t')[W_DES]
   des_web = des_web.replace('.',' ')
   des_web = des_web.replace('/',' ')
   des_web = des_web.replace('(',' ')
   des_web = des_web.replace(')',' ')
   des_web = des_web.replace('"',' ')
   des_web = des_web.replace('-',' ')
   des_web = des_web.replace('*',' ')
   des_web = des_web.split(' ')

Descomponemos la cadena de la descripción del catalogo WEB, y quitamos los caracteres . / ( ) » – * que solo son caracteres de relleno en la descripción, y que no dicen nada en realidad del nombre del producto. Y después partimos la descripción en una lista de palabras que estan separadas por un espacio en blanco ‘ ‘

Con un ciclo para recorrer todas las descripciones del catalogo REAL, empezamos a comparar cada uno de los registros con con la lista de palabras que tenemos de la descripción del catalogo WEB.

	for j in range(len(lines_moz)):
		des_moz = lines_moz[j].split('\t')[M_DES] 	# descomponemos la descripcion del catalogo REAL.
		score.append(0) 				# Nuestra lista de scores, "Que tan aproximada es la cadena con la otra"
                # Comparar
 		for l in range(len(des_web)):
                       if len(des_web[l]) > 1:                  # Solo comparamos las palabras que sean mayores de un caracter.
				plus = compara(des_web[l],des_moz,l)
				...
				..
				.

Dentro del proceso compara, generaremos un score que basándonos en la posicion de la palabra encontrada en la descripcion REAL, sera mas alto o mas bajo, si es de las primeras recibe una mejor «calificacion»

Las premisas para generar nuestro score son asi:

Iniciamos con score = 0

plus = X
  Donde plus le daremos un valor de 10 si la palabra que estamos comparando del catalogo WEB es la primera
                                    5 si la palabra que estamos comparando es la segunda
                                    2 si es la tercera
                                    1 si es la cuarta en adelante.

Si encontramos la palabra del catalogo WEB en la descripcion del catalogo REAL le daremos el siguiente score

  score = 10 si es la primera palabra de la descripcion del catalogo REAL
  score = 5 si es la segunda
  score = 2 si es la tercera
  score = 1 si es de la cuarta en adelante.

y se suma el plus que hayamos calculado.
  score = score + plus

Si la primera palabra de mas de dos caracteres del catalogo REAL se encontró en la descripción WEB se agrega este score:
       score = score + 20

Si no esta:
       score = score - 10

Guardamos una lista score donde a cada descripción del catalogo REAL le damos una calificación, donde la que tenga mayor score consideraremos como la que le corresponde.
Una vez ubicada esta relacion, quitamos el registro del catalogo REAL que corresponde de las siguientes comparaciones.

En base a los resultados y a lo observado, consideramos las comparaciones hechas que tengan un score mayor a 20 son correctas y las de menor score son incorrectas.

Los resultados:

«Correctos»

--ACARBOSA c/30 TABS. 50 MG. -- Score: 45-- Indice que le corresponde: 563 -- G.I ACARBOSA 30 TABS 50MG
--DEXENAC c/10 TABS. 100 MG. -- Score: 54-- Indice que le corresponde: 2097 -- DEXENAC 10 TABS 100MG
--MYCINADOL CREMA Tubo 60 GR. 1.5 GR. -- Score: 49-- Indice que le corresponde: 2455 -- MYCINADOL CRA 60GR 1.5GR
--IGNIS Unguento Oftalmico TUBO c/4.5GR. -- Score: 42-- Indice que le corresponde: 2356 -- IGNIS UNG OFT 4.5GR
--DYSKLY c/20 TABS. 200 MG. -- Score: 62-- Indice que le corresponde: 2816 -- DYSKLY 200MG 20TABS
--ZIVERONE c/25 TABS. 200 MG. -- Score: 54-- Indice que le corresponde: 3081 -- ZIVERONE 25 TABS 200MG
--"CLORIXAN ""Macro"" c/50 TABS. 200 MG." -- Score: 53-- Indice que le corresponde: 82 -- CLORIXAN 50 TABS 200MG
--CLORIXAN c/20 TABS. 200 MG. -- Score: 54-- Indice que le corresponde: 465 -- CLORIXAN 20 TABS 200MG
--SOVICLOR c/25 TABS. 200 MG. -- Score: 54-- Indice que le corresponde: 129 -- SOVICLOR 25 TABS 200MG
--ZIVERONE SUSP. 120 ML. 200 MG. -- Score: 57-- Indice que le corresponde: 2994 -- ZIVERONE SUSP 120ML
--LESACLOR SUSP. 125 ML. 200 MG. -- Score: 61-- Indice que le corresponde: 1390 -- LESACLOR SUSP 125ML 200MG
--MACLOV c/25 TABS. 200 MG. -- Score: 54-- Indice que le corresponde: 2632 -- MACLOV 25 TABS 200MG
--MACLOV c/35 TABS. 400 MG. -- Score: 54-- Indice que le corresponde: 3449 -- MACLOV 35 TABS 400MG
--"CLORIXAN ""Macro"" c/50 TABS. 400 MG." -- Score: 53-- Indice que le corresponde: 284 -- CLORIXAN 50 TABS 400MG
--ZIVERONE CREMA TUBO c/5 GR. -- Score: 53-- Indice que le corresponde: 1490 -- ZIVERONE CREMA 5GR
--LESACLOR CREMA TUBO c/5 GR. -- Score: 43-- Indice que le corresponde: 2300 -- LESACLOR CRA 5GR
--SOVICLOR CREMA Tubo c/5 GR. -- Score: 43-- Indice que le corresponde: 3500 -- SOVICLOR CRA 5GR
--ACICLOVIR (Clociver) CREMA Tubo c/5 GR. -- Score: 50-- Indice que le corresponde: 3326 -- ACICLOVIR 5GR CREMA 1GR
--"CLORIXAN ""Macro"" c/50 TABS. 800 MG." -- Score: 53-- Indice que le corresponde: 1619 -- CLORIXAN 50 TABS 800MG
--VALINIR c/10 TABS. 500 MG. -- Score: 54-- Indice que le corresponde: 2293 -- VALINIR 10 TABS 500MG

«Malos»

--ACYPRIN c/30 TABS. 300 MG. -- Score: 15-- Indice que le corresponde: 2586 -- PIREMOL-300 3 SUPS 300MG
--CIBRONAL SUSP. 90 ML. 250/15 MG. -- Score: 13-- Indice que le corresponde: 1125 -- VANMOXOL SUSP 90ML 250/15MG
--FENAGEL GEL Tubo c/60 GR. 1.16 GR. -- Score: 18-- Indice que le corresponde: 1349 -- REGRIPAX 60 CAPS
--BETADURE c/28 TABS. 100 MG. -- Score: 9-- Indice que le corresponde: 2683 -- PRILKENZIDE 100MG 28TABS
--SICALAN SUSP. 30 ML. 200 MG. -- Score: 14-- Indice que le corresponde: 752 -- LERGIBRUMIZOL 30ML SUSP 200MG
--MERTODOL BLANCO Caja FCO. 40 ML. -- Score: 4-- Indice que le corresponde: 2539 -- FLAMIN-400 SUSP 120ML 125/100MG
--MERTODOL ROJO Caja FCO. 40 ML. -- Score: 3-- Indice que le corresponde: 903 -- SIMLO 30 TABS 40MG
--MERTODOL BLANCO Atomizador c/40 ML. -- Score: 2-- Indice que le corresponde: 2694 -- ALUMAG 240ML
--LUBRI-6 Jalea Lubricante Tubo c/135 GR. 0.10 GR. -- Score: 18-- Indice que le corresponde: 698 -- GRIVER 10 CAPS 275/10MG
--CEPACAINA Sabor Cereza c/18 TABS. 1.45/10 MG. -- Score: 7-- Indice que le corresponde: 2809 -- M-BENTABS 20ML 100MG
--BENZOILO GEL TUBO c/60 GR. -- Score: 8-- Indice que le corresponde: 2523 -- DOLZYCAM GEL TUBO 60GR
--K-Y-6 c/10 TABS. 500/25/5/4 MG. -- Score: 8-- Indice que le corresponde: 2831 -- TEMPERAL 10TABS 500MG
--DOMEBORO POLVO c/12 SOBS. 2.2 GR. -- Score: 7-- Indice que le corresponde: 2700 -- SINGRILEN 12TABS
--KAPECFURAN SUSP. 120 ML. -- Score: 20-- Indice que le corresponde: 483 -- RAN-LEVO 7 TABS 500MG
--ULTREPYL c/20 TABS. 200 MG. -- Score: 11-- Indice que le corresponde: 2421 -- PARSENIDA 200MG 6 TABS
--FAMTO Sol. Iny. c/1 AMP. 1 GR. -- Score: 12-- Indice que le corresponde: 3445 -- AMPIGRIN SOL INY AD 1PZ
--CEFEPIMA Sol. Iny. c/1 AMP. 10 ML. 1 GR. -- Score: 12-- Indice que le corresponde: 3446 -- AMPIGRIN SOL INY INF 1PZ
--AMCEF Sol. Iny. I.M. c/1 AMP. 1 GR. -- Score: 1-- Indice que le corresponde: 156 -- CORTIGRIN SOL INY AD
--XORUFEC Sol. Iny. c/1 AMP. 750 MG. -- Score: 3-- Indice que le corresponde: 749 -- CLORAMPER 20 CAPS 500MG
--KENICET c/10 TABS. 10 MG. -- Score: 16-- Indice que le corresponde: 2771 -- KENDRICK KENICET 10 TABS 10MG

Pero en su mayoría los resultados son bastante aproximados, por lo que eh revisado a ojo calculo un 95% de entradas correctas, con lo cual me quedare, y ya el resto se podran corregir por el usuario en modo particular para cada registro.

::Codigo::

 

Deja un comentario