2010-03-20 17 views
12

Dada una matriz 'a' Me gustaría ordenar la matriz por columnas "ordenar (a, eje = 0)" hacer algunas cosas en la matriz y luego deshacer la ordenación. Por eso, no me refiero a re clasificar, sino básicamente a revertir cómo se movió cada elemento. Supongo que argsort() es lo que necesito pero no me queda claro cómo ordenar una matriz con los resultados de argsort() o más importante aplicar el inverso/inverso de argsort()deshacer o revertir argsort(), python

Aquí hay un poco más de detalle

tengo una matriz a, forma (a) = RXC que necesito para ordenar cada columna

aargsort = a.argsort(axis=0) # May use this later 
aSort = a.sort(axis=0) 

ahora un promedio de cada fila

aSortRM = asort.mean(axis=1) 

ahora reemplazar cada col en una fila con la fila yo un. hay una manera mejor que esto

aWithMeans = ones_like(a) 
for ind in range(r) # r = number of rows 
    aWithMeans[ind]* aSortRM[ind] 

ahora tengo que deshacer el tipo que hice en el primer paso. ????

+1

¿Por qué no puede simplemente hacer una copia de la matriz: 'a.copy()' antes de cualquier transformación o usar 'aSort = numpy .sort (axis = 0) '(que devolverá la copia clasificada)? Por cierto, 'a.sort()' no devuelve nada, por lo tanto, no tiene sentido asignar su valor de retorno. – jfs

+0

@ J.F. Sebastian, gracias, tienes razón, lo arreglé – Vincent

Respuesta

4

No estoy seguro de la mejor manera de hacerlo en numpy, pero, en Python puro, el razonamiento sería:

aargsort está llevando a cabo una permutación de range(len(a)) le decimos donde los elementos de aSort vinieron de - al igual que, en puro Python:

>>> x = list('ciaobelu') 
>>> r = range(len(x)) 
>>> r.sort(key=x.__getitem__) 
>>> r 
[2, 4, 0, 5, 1, 6, 3, 7] 
>>> 

es decir, el primer argumento de sorted(x) habrá x[2], el segundo x[4], y así sucesivamente.

Así que dada la versión ordenada, se puede reconstruir el original de "poner artículos de nuevo de dónde venían":

>>> s = sorted(x) 
>>> s 
['a', 'b', 'c', 'e', 'i', 'l', 'o', 'u'] 
>>> original = [None] * len(s) 
>>> for i, c in zip(r, s): original[i] = c 
... 
>>> original 
['c', 'i', 'a', 'o', 'b', 'e', 'l', 'u'] 
>>> 

Por supuesto que van a ser formas más estrictas y más rápidos para expresar esto en numpy (que desafortunadamente no sé por dentro tanto como conozco a Python ;-), pero espero que esto ayude al mostrar la lógica subyacente de la operación de "poner las cosas en su lugar" que necesita realizar.

1

No pude seguir su ejemplo, pero el problema más abstracto, es decir, cómo ordenar una matriz y luego invertir el orden, es sencillo.

import numpy as NP 
# create an 10x6 array to work with 
A = NP.random.randint(10, 99, 60).reshape(10, 6) 
# for example, sort this array on the second-to-last column, 
# breaking ties using the second column (numpy requires keys in 
# "reverse" order for some reason) 
keys = (A[:,1], A[:,4]) 
ndx = NP.lexsort(keys, axis=0) 
A_sorted = NP.take(A, ndx, axis=0) 

"reconstruir" A partir de A_sorted es trivial, ya que recuerda que utilizó una matriz de índice ('ndx') para ordenar la matriz en el primer lugar.

# ndx array for example above: array([6, 9, 8, 0, 1, 2, 4, 7, 3, 5]) 

En otras palabras, la cuarta fila de A_sorted fue la primera fila de la matriz original, A, etc.

+0

De hecho, quiero ordenar cada columna individualmente, corrijo mi código en la parte superior, pero tengo que trabajar con np.sort (A, axis = 0) para que inex sea np.argsort (x, axis = 0) – Vincent

30

probablemente hay mejores soluciones para el problema en realidad se está tratando de resolver que esto (la realización de una argsort por lo general evita la necesidad de realidad especie), pero aquí van:

>>> import numpy as np 
>>> a = np.random.randint(0,10,10) 
>>> aa = np.argsort(a) 
>>> aaa = np.argsort(aa) 
>>> a # original 
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4]) 
>>> a[aa] # sorted 
array([0, 2, 4, 4, 4, 4, 5, 6, 6, 7]) 
>>> a[aa][aaa] # reversed 
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4]) 
7

Para todos aquellos que todavía parece por respuesta:

In [135]: r = rand(10) 

In [136]: i = argsort(r) 

In [137]: r_sorted = r[i] 

In [138]: i_rev = zeros(10, dtype=int) 

In [139]: i_rev[i] = arange(10) 

In [140]: allclose(r, r_sorted[i_rev]) 

Out[140]: True 
1

Súper tarde al juego, pero aquí:

import numpy as np 
N = 1000 # or any large integer 
x = np.random.randn(N) 
I = np.argsort(x) 
J = np.argsort(I) 
print(np.allclose(x[I[J]] , x)) 
>> True 

Básicamente, argsort el argsort porque el enésimo elemento de la ordenación inversa es J [n] = k: I [k] = n. Es decir, I [J [n]] = n, por lo que J ordena I.

+0

Esta es, de lejos, la mejor solución – simeon

Cuestiones relacionadas