Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

194
Visualizações
NumPy máximos de grupos definidos por una matriz de etiquetas

Tengo dos matrices, una es una lista de valores y otra es una lista de ID correspondientes a cada valor. Algunas identificaciones tienen varios valores. Quiero crear una nueva matriz que contenga el valor máximo registrado para cada identificación, que tendrá una longitud igual a la cantidad de identificaciones únicas.

Ejemplo usando un bucle for :

 import numpy as np values = np.array([5, 3, 2, 6, 3, 4, 8, 2, 4, 8]) ids = np.array([0, 1, 3, 3, 3, 3, 5, 6, 6, 6]) uniq_ids = np.unique(ids) maximums = np.ones_like(uniq_ids) * np.nan for i, id in enumerate(uniq_ids): maximums[i] = np.max(values[np.where(ids == id)]) print(uniq_ids) print(maximums)
 [0 1 3 5 6] [5. 3. 6. 8. 8.]

¿Es posible vectorizar esto para que funcione rápido? Me imagino una línea que puede crear la matriz de "máximos" usando solo funciones NumPy, pero no he podido encontrar nada que funcione.

over 4 years ago · Santiago Trujillo
5 Respostas
Responde à pergunta

0

Aquí hay una solución que, aunque no está 100% vectorizada (según mis puntos de referencia), toma aproximadamente la mitad del tiempo que usted (usando sus datos de muestra). La mejora del rendimiento probablemente se vuelve más drástica con más datos:

 maximums = [a.max() for a in np.split(values, np.arange(1, ids.shape[0])[(np.diff(ids) != 0)])]

Producción:

 >>> maximums [5, 3, 6, 8, 8]
over 4 years ago · Santiago Trujillo Relatório

0

Al tratar de visualizar el problema:

 In [82]: [np.where(ids==id) for id in uniq_ids] Out[82]: [(array([0]),), (array([1]),), (array([2, 3, 4, 5]),), (array([6]),), (array([7, 8, 9]),)]

unique también puede devolver:

 In [83]: np.unique(ids, return_inverse=True) Out[83]: (array([0, 1, 3, 5, 6]), array([0, 1, 2, 2, 2, 2, 3, 4, 4, 4]))

Que es una variante de lo que produjo richardec :

 In [88]: [a for a in np.split(ids, np.arange(1, ids.shape[0])[(np.diff(ids) != ...: 0)])] Out[88]: [array([0]), array([1]), array([3, 3, 3, 3]), array([5]), array([6, 6, 6])]

Ese inverso también se produce haciendo where on all == a la vez:

 In [90]: ids[:,None] == uniq_ids Out[90]: array([[ True, False, False, False, False], [False, True, False, False, False], [False, False, True, False, False], [False, False, True, False, False], [False, False, True, False, False], [False, False, True, False, False], [False, False, False, True, False], [False, False, False, False, True], [False, False, False, False, True], [False, False, False, False, True]]) In [91]: np.nonzero(ids[:,None] == uniq_ids) Out[91]: (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 2, 2, 2, 3, 4, 4, 4]))

Todavía estoy pensando en esto...

over 4 years ago · Santiago Trujillo Relatório

0

EDITAR: Dejaré esto como un ejemplo de por qué no siempre podemos usar np.vectorize() para hacer que todo sea mágicamente más rápido:

Una solución es usar la función vectorizar de numpy:

 import numpy as np values = np.array([5, 3, 2, 6, 3, 4, 8, 2, 4, 8]) ids = np.array([0, 1, 3, 3, 3, 3, 5, 6, 6, 6]) def my_func(id): return np.max(values[np.where(ids==id)]) vector_func = np.vectorize(my_func) maximums = vector_func(np.unique(ids))

que regresa

 array([5, 3, 6, 8, 8])

Pero en cuanto a la velocidad, su versión tiene aproximadamente el mismo rendimiento cuando usamos

 values = np.array([random.randint(1, 100) for i in range(1000000)]) ids = [] for i in range(100000): r = random.randint(1, 4) if r == 3: for x in range(3): ids.append(i) elif r == 2: for x in range(4): ids.append(i) else: ids.append(i) ids = np.array(ids)

Son unos 12 segundos por ejecución.

over 4 years ago · Santiago Trujillo Relatório

0

Con pandas:

 import pandas as pd def with_pandas(ids, vals): df = pd.DataFrame({'ids': ids, 'vals': values}) return df.groupby('ids')['vals'].max().to_numpy()

Sincronización:

 import numpy as np values = np.random.randint(10000, size=10000) ids = np.random.randint(100, size=10000) %timeit with_pandas(ids, values) 692 µs ± 21.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
over 4 years ago · Santiago Trujillo Relatório

0

np.lexsort ordena por varias columnas. Sin embargo, esto no es obligatorio. Puede ordenar las ids primero y luego elegir el elemento máximo de cada grupo dividido usando numpy.maximum.reduceat

 def mathfux(values, ids, return_groups=False): argidx = np.argsort(ids) #70% time ids_sort, values_sort = ids[argidx], values[argidx] #4% time div_points = np.r_[0, np.flatnonzero(np.diff(ids_sort)) + 1] #11% time (the most part for np.flatnonzero) if return_groups: return ids[div_points], np.maximum.reduceat(values_sort, div_points) else: return np.maximum.reduceat(values_sort, div_points) mathfux(values, ids, return_groups=True) >>> (array([0, 1, 3, 5, 6]), array([5, 3, 6, 8, 8])) mathfux(values, ids) >>> mathfux(values, ids) array([5, 3, 6, 8, 8])

Por lo general, algunas partes de los códigos numpy podrían optimizarse aún más en numba . Tenga en cuenta que np.argsort es un cuello de botella en la mayoría de los problemas de groupby que no se pueden reemplazar con ningún otro método. Es poco probable que se mejore pronto en numba o numpy . Por lo tanto, está alcanzando un rendimiento óptimo aquí y no puede hacer mucho en futuras optimizaciones.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda