python - una - Aplicación de función sobre la fila/columna matricial de numpy
transpuesta de una matriz en python numpy (4)
Estoy usando Numpy para almacenar datos en matrices. Viniendo desde el fondo R, ha habido una manera extremadamente simple de aplicar una función sobre filas / columnas o ambas de una matriz.
¿Hay algo similar para la combinación python / numpy? No es un problema escribir mi propia pequeña implementación, pero me parece que la mayoría de las versiones que se me ocurrirán serán significativamente menos eficientes / requerirán más memoria que cualquiera de la implementación existente.
Me gustaría evitar copiar de la matriz numpy a una variable local, etc., ¿es eso posible?
Las funciones que intento implementar son principalmente comparaciones simples (por ejemplo, cuántos elementos de una determinada columna son más pequeños que el número x o cuántos de ellos tienen un valor absoluto mayor que y).
Casi todas las funciones numpy operan en arreglos completos, y / o se les puede indicar que operen en un eje particular (fila o columna).
Siempre que pueda definir su función en términos de funciones numpy que actúen en matrices numpy o segmentos de matriz, su función operará automáticamente en matrices enteras, filas o columnas.
Puede ser más útil preguntar cómo implementar una función particular para obtener consejos más concretos.
Numpy proporciona np.vectorize y np.frompyfunc para convertir las funciones de Python que operan en números en funciones que operan en matrices numpy.
Por ejemplo,
def myfunc(a,b):
if (a>b): return a
else: return b
vecfunc = np.vectorize(myfunc)
result=vecfunc([[1,2,3],[5,6,9]],[7,4,5])
print(result)
# [[7 4 5]
# [7 6 9]]
(Los elementos de la primera matriz se reemplazan por el elemento correspondiente de la segunda matriz cuando la segunda es más grande).
Pero no te emociones demasiado; np.vectorize
y np.frompyfunc
son solo azúcar sintáctico . En realidad, no hacen tu código más rápido. Si su función Python subyacente está operando en un valor a la vez, np.vectorize
lo alimentará un elemento a la vez, y toda la operación va a ser bastante lenta (en comparación con el uso de una función numpy que llama a C o C subyacentes). Implementación Fortran).
Para contar cuántos elementos de la columna x
son más pequeños que un número y
, puede usar una expresión como:
(array[''x'']<y).sum()
Por ejemplo:
import numpy as np
array=np.arange(6).view([(''x'',np.int),(''y'',np.int)])
print(array)
# [(0, 1) (2, 3) (4, 5)]
print(array[''x''])
# [0 2 4]
print(array[''x'']<3)
# [ True True False]
print((array[''x'']<3).sum())
# 2
Seleccionar elementos de una matriz NumPy basada en una o más condiciones es sencillo usando la sintaxis hermosamente densa de NumPy:
>>> import numpy as NP
>>> # generate a matrix to demo the code
>>> A = NP.random.randint(0, 10, 40).reshape(8, 5)
>>> A
array([[6, 7, 6, 4, 8],
[7, 3, 7, 9, 9],
[4, 2, 5, 9, 8],
[3, 8, 2, 6, 3],
[2, 1, 8, 0, 0],
[8, 3, 9, 4, 8],
[3, 3, 9, 8, 4],
[5, 4, 8, 3, 0]])
¿Cuántos elementos en la columna 2 son mayores que 6?
>>> ndx = A[:,1] > 6
>>> ndx
array([False, True, False, False, True, True, True, True], dtype=bool)
>>> NP.sum(ndx)
5
¿Cuántos elementos en la última columna de A tienen un valor absoluto mayor que 3?
>>> A = NP.random.randint(-4, 4, 40).reshape(8, 5)
>>> A
array([[-4, -1, 2, 0, 3],
[-4, -1, -1, -1, 1],
[-1, -2, 2, -2, 3],
[ 1, -4, -1, 0, 0],
[-4, 3, -3, 3, -1],
[ 3, 0, -4, -1, -3],
[ 3, -4, 0, -3, -2],
[ 3, -4, -4, -4, 1]])
>>> ndx = NP.abs(A[:,-1]) > 3
>>> NP.sum(ndx)
0
¿Cuántos elementos en las primeras dos filas de A son mayores o iguales a 2?
>>> ndx = A[:2,:] >= 2
>>> NP.sum(ndx.ravel()) # ''ravel'' just flattens ndx, which is originally 2D (2x5)
2
La sintaxis de indexación de NumPy es muy similar a la de R; dada su fluidez en R, aquí están las diferencias clave entre R y NumPy en este contexto:
Los índices NumPy están basados en cero , en R, la indexación comienza con 1
NumPy (como Python) le permite indexar de derecha a izquierda utilizando índices negativos, por ejemplo,
# to get the last column in A
A[:, -1],
# to get the penultimate column in A
A[:, -2]
# this is a big deal, because in R, the equivalent expresson is:
A[, dim(A)[0]-2]
NumPy usa la notación de dos puntos ":" para indicar "sin cortar" , por ejemplo, en R, para obtener las primeras tres filas en A, usaría, A [1: 3,]. En NumPy, usaría A [0: 2,:] (en NumPy, el "0" no es necesario, de hecho, es preferible usar A [: 2,:]
También vengo de un fondo más R, y tropecé con la falta de una aplicación más versátil que podría tomar funciones personalizadas cortas. He visto los foros sugiriendo usar funciones numpy básicas porque muchos de ellos manejan arreglos. Sin embargo, me he estado confundiendo sobre la forma en que las funciones numpy "nativas" manejan la matriz (a veces 0 es en hilera y 1 en columna, a veces lo opuesto).
Mi solución personal para funciones más flexibles con apply_along_axis fue combinarlas con las funciones lambda implícitas disponibles en python. Las funciones de Lambda deberían ser muy fáciles de entender para los que piensan en R que usan un estilo de programación más funcional, como en las funciones R, aplicar, aplicar, aplicar, etc.
Entonces, por ejemplo, quería aplicar la estandarización de variables en una matriz. Típicamente en R hay una función para esto (escala) pero también puedes construirla fácilmente con apply:
(Código R)
apply(Mat,2,function(x) (x-mean(x))/sd(x) )
Usted ve cómo se aplica el cuerpo de la función en el interior (x-mean (x)) / sd (x) es el bit que no podemos escribir directamente para el python apply_along_axis. Con lambda esto es fácil de implementar PARA UN CONJUNTO DE VALORES, entonces:
(Pitón)
import numpy as np
vec=np.random.randint(1,10,10) # some random data vector of integers
(lambda x: (x-np.mean(x))/np.std(x) )(vec)
Entonces, todo lo que necesitamos es conectar esto dentro de la aplicación Python y pasar la matriz de interés a través de apply_along_axis
Mat=np.random.randint(1,10,3*4).reshape((3,4)) # some random data vector
np.apply_along_axis(lambda x: (x-np.mean(x))/np.std(x),0,Mat )
Obviamente, la función lambda podría implementarse como una función separada, pero supongo que todo el punto es usar funciones bastante pequeñas contenidas dentro de la línea donde se originó la aplicación.
Espero que le sea útil !
Pandas es muy útil para esto. Por ejemplo, DataFrame.apply() y groupby''s apply () deberían ayudarte.