1. Estoy ejecutando el siguiente programa para verificar la disponibilidad de determinados productos (A) en un catálogo de productos (B)


2. El programa está funcionando bien con una pequeña entrada de un producto y catálogo dado, como el ejemplo a continuación con 3 productos en productos dados y 3 productos en catálogo.


3. El problema es que cuando los productos dados y el catálogo de productos se hacen más grandes, como 50,000 productos dados y 150,000 productos en catálogo, se necesita mucho tiempo y esfuerzo para ejecutar el programa. O


4. Cada producto en A recorrerá todo el catálogo B para seleccionar la coincidencia máxima. Entonces el ciclo será de 50,000 X 150,000.


5. Todos están en Excel. La Tabla A tiene 2 columnas (Seller_Name y product_title) con 50000 filas de producto. La Tabla B tiene 2 columnas (product_code y product_title) con 150,000 filas


6. Corté el mosaico del producto por espacios en blanco como el ejemplo a continuación para ejecutar el programa.


7. Por favor, hágame saber cómo abordar esto.

¡Gracias!

Entrada:

def available(product, catalog):
    items = [_ for _ in product if _ != "NaN"]
    if isinstance(catalog[0], str):
        catalog = [catalog]

    max_match = (0, [])
    for catalog in catalog:
        matched_count = 0
        for item in items:
            if item in catalog:
                matched_count += 1
        max_match = max(max_match, (matched_count, catalog)) # tuple score + catalog_item

    return "_".join(items), max_match[1], max_match[0] / len(items) if len(items) != 0 else 0

def availables(products, catalog):
    return [available(product, catalog) for product in products]

A =([['mai', 'dubai', '200ml', 'NaN'],
                ['mai', 'dubai', 'cup'],
                ['mai', 'dubai', '1.5l']]) #multiple products

B =([['natural','mineral','water', 'cups', '200', 'ml', 'pack', 'of', '24', 'mai', 'dubai'],
                ['2-piece', 'glitzi', 'power', 'inox', 'power', 'dish'],
                ['15-piece', 'bones', 'for', 'dog', 'multicolour', 'rich']]) #

output=[]
for res in availables(A, B):
    output.append(res)

import pandas as pd
df=pd.DataFrame(output)
df

Salida:

    0   1   2
0   mai_dubai_200ml [natural, mineral, water, cups, 200, ml, pack,...   0.666667
1   mai_dubai_cup   [natural, mineral, water, cups, 200, ml, pack,...   0.666667
2   mai_dubai_1.5l  [natural, mineral, water, cups, 200, ml, pack,...   0.666667

0
singularity 28 dic. 2019 a las 17:42

2 respuestas

La mejor respuesta

Este problema es diferente de la primera publicación, por lo que trato de ser lo más flexible posible para tener diferentes entradas.

import pandas as pd
import numpy as np

def available(product, catalog):

    try:
        product.remove('NaN')
    except: 
        pass
    l = len(product)

    r = np.array([len(set(product).intersection(set(c))) for c in catalog])

    max_match = np.max(r)
    max_match_id = np.argmax(r)

    return "_".join(product), catalog[max_match_id], max_match/l

def availables(products, catalog):
    return [available(product, catalog) for product in products]

A =([['mai', 'dubai', '200ml', 'NaN'],
                ['mai', 'dubai', 'cup'],
                ['mai', 'dubai', '1.5l']]) #multiple products

B =([['natural','mineral','water', 'cups', '200', 'ml', 'pack', 'of', '24', 'mai', 'dubai'],
                ['2-piece', 'glitzi', 'power', 'inox', 'power', 'dish'],
                ['15-piece', 'bones', 'for', 'dog', 'multicolour', 'rich']]) #


output=[ res for res in availables(A, B) ]


df=pd.DataFrame(output)
df



 0                                                  1             2   
0  mai_dubai_200ml  [natural, mineral, water, cups, 200, ml, pack,...   0.666667 
1    mai_dubai_cup  [natural, mineral, water, cups, 200, ml, pack,...   0.666667 
2   mai_dubai_1.5l  [natural, mineral, water, cups, 200, ml, pack,...   0.666667 
1
FBruzzesi 28 dic. 2019 a las 16:20

Análisis de código:

A, la longitud de B es 50000.

Llamadas disponibles (A, B)

def availables(products, catalog):
    return [available(product, catalog) for product in products]

Llamadas disponibles (producto, [int * 50000]) 50000 veces

for catalog in catalog: <---- btw what is this ANYWAYS that's 50000 calls
        matched_count = 0
        for item in items: <---- Another 4 calls?
            if item in catalog:
                matched_count += 1
        max_match = max(max_match, (matched_count, catalog))

Entonces, verá que su bucle for ejecutará un total de 50000x50000x4 = 10 mil millones de veces

Lo sentimos, pero eso no se ejecutará en menos de un segundo, o incluso en unos segundos razonables.

2
Gareth Ma 28 dic. 2019 a las 15:12