Agregue los valores mínimos y máximos en una columna en función de otra columna de la matriz - Python

Mohammad Islam |

Estoy tratando de concatenar los valores si tienen los mismos índices. Estoy trabajando con forma rectangular, así que sé:

  • Siempre habrá al menos 2 índices iguales.
  • Si hay más de 2 índices, solo necesito almacenar los máximos y los minutos.

Básicamente,

Desde:

a = array([
       [ 1,  5],
       [ 1,  7],
       [ 2,  8],
       [ 2, 10],
       [ 2, 22],
       [ 3, 55],
       [ 3, 77]])

A:

b = np.array([
       [ 1, 5, 7],
       [ 2, 8, 22], # [2,8,10,22] but the min is 8 and max is 22
       [ 3, 55, 77]])

He intentado convertirlo en una lista y revisar cada valor usando un bucle for, pero lleva una cantidad considerable de tiempo.

También intenté ordenar la matriz np.sort(a, axis=0)y tomar cada dos filas, pero como puede haber más de dos de los índices, falla.

Soy nuevo en numpy, así que no sé qué más probar.

Cualquier sugerencia sería útil, gracias.

Editar: su comportamiento es como un diccionario donde las claves son un [0] y los valores son un [1:]

Si hay más de 2 valores, solo conservo el mínimo y el máximo.

Divakar

Enfoque # 1

Una forma NumPy vectorizada sería:

def agg_minmax(a):
    sidx = np.lexsort(a[:,::-1].T)
    b = a[sidx]
    m = np.r_[True,b[:-1,0]!=b[1:,0],True]
    return np.c_[b[m[:-1],:2], b[m[1:],1]]

Ejecución de muestra -

# Generic case with input not-necessarily sorted by first col
In [35]: a
Out[35]: 
array([[ 3, 77],
       [ 2,  8],
       [ 1,  7],
       [ 2, 10],
       [ 1,  5],
       [ 3, 55],
       [ 2, 22]])

In [36]: agg_minmax(a)
Out[36]: 
array([[ 1,  5,  7],
       [ 2,  8, 22],
       [ 3, 55, 77]])

Enfoque # 2

Podemos mejorar la memoria para ordenar solo la primera fila sidx, así:

def agg_minmax_v2(a):
    sidx = np.lexsort(a[:,::-1].T)
    b = a[sidx,0]
    m = np.r_[True,b[:-1]!=b[1:],True]
    return np.c_[a[sidx[m[:-1]]],a[sidx[m[1:]],1]]

Esto podría ser mejor con muchas entradas por grupo.


Alternativa n. ° 1: sidxutilice el mapeo de índice lineal

Para números int positivos, podemos asumir que están en la 2Dcuadrícula y, por lo tanto, obtener equivalentes de índice lineal para cada fila. Por lo tanto, saltaremos lexsorty nos pondremos sidxasí -

sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()

El resto del código después de la obtención sidxpermanece igual en los dos enfoques publicados anteriormente.

Alternativa n. ° 2: empezar a sidxusarviews

Podríamos usar viewspara obtener sidxy, por lo tanto lexsort, saltar de nuevo , así:

# https://stackoverflow.com/a/44999009/ @Divakar
def view1D(a): # a is array
    a = np.ascontiguousarray(a)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel()

A = view1D(a)
sidx = A.argsort()

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

TOP Lista

CalienteEtiquetas

Archivo