tutorial index from create column python pandas numpy dataframe series

index - pandas python



¿Cómo calculo un idxmax rodante? (4)

Aquí hay un enfoque que utiliza la broadcasting :

maxidx = (s.values[np.arange(s.size-3+1)[:,None] + np.arange(3)]).argmax(1) out = s.index[maxidx+np.arange(maxidx.size)]

Esto genera todos los índices correspondientes a las ventanas rotatorias, indexa en la versión de matriz extraída con esos y así obtiene los índices máximos para cada ventana. Para una indexación más eficiente, podemos usar los NumPy strides , como ese:

arr = s.values n = arr.strides[0] maxidx = np.lib.stride_tricks.as_strided(arr, / shape=(s.size-3+1,3), strides=(n,n)).argmax(1)

considerar el pd.Series

import pandas as pd import numpy as np np.random.seed([3,1415]) s = pd.Series(np.random.randint(0, 10, 10), list(''abcdefghij'')) s a 0 b 2 c 7 d 3 e 8 f 7 g 0 h 6 i 8 j 6 dtype: int64

Quiero obtener el índice para el valor máximo de la ventana móvil de 3

s.rolling(3).max() a NaN b NaN c 7.0 d 7.0 e 8.0 f 8.0 g 8.0 h 7.0 i 8.0 j 8.0 dtype: float64

Lo que quiero es

a None b None c c d c e e f e g e h f i i j i dtype: object

Qué he hecho

s.rolling(3).apply(np.argmax) a NaN b NaN c 2.0 d 1.0 e 2.0 f 1.0 g 0.0 h 0.0 i 2.0 j 1.0 dtype: float64

que obviamente no es lo que quiero


No existe una forma sencilla de hacerlo, ya que el argumento que se pasa a la función de aplicación continua es una matriz numérica simple, no una serie de pandas, por lo que no conoce el índice. Además, las funciones de balanceo deben devolver un resultado flotante, por lo que no pueden devolver directamente los valores del índice si no son flotantes.

Aquí hay un enfoque:

>>> s.index[s.rolling(3).apply(np.argmax)[2:].astype(int)+np.arange(len(s)-2)] Index([u''c'', u''c'', u''e'', u''e'', u''e'', u''f'', u''i'', u''i''], dtype=''object'')

La idea es tomar los valores de argmax y alinearlos con la serie agregando un valor que indique qué tan avanzado estamos en la serie. (Es decir, para el primer valor de argmax agregamos cero, porque nos está dando el índice en una subsecuencia que comienza en el índice 0 en la serie original; para el segundo valor de argmax agregamos uno, porque nos está dando el índice en una subsecuencia comenzando en el índice 1 en la serie original; etc.)

Esto proporciona los resultados correctos, pero no incluye los dos valores "Ninguno" al principio; Tendría que volver a agregarlos manualmente si los quisiera.

Existe un problema de pandas abierto para agregar idxmax rodante.


También puede simular la ventana DataFrame creando un DataFrame y usar idxmax siguiente manera:

window_values = pd.DataFrame({0: s, 1: s.shift(), 2: s.shift(2)}) s.index[np.arange(len(s)) - window_values.idxmax(1)] Index([''a'', ''b'', ''c'', ''c'', ''e'', ''e'', ''e'', ''f'', ''i'', ''i''], dtype=''object'', name=0)

Como puede ver, los primeros dos términos son el idxmax aplicado a las ventanas iniciales de las longitudes 1 y 2 en lugar de los valores nulos. No es tan eficiente como la respuesta aceptada y probablemente no es una buena idea para ventanas grandes, sino simplemente otra perspectiva.


Usé un generador

def idxmax(s, w): i = 0 while i + w <= len(s): yield(s.iloc[i:i+w].idxmax()) i += 1 pd.Series(idxmax(s, 3), s.index[2:]) c c d c e e f e g e h f i i j i dtype: object