una seleccionar recorrer filtros filtrar filas fila datos data crear con columnas python pandas dataframe ranking

python - recorrer - seleccionar columnas de un dataframe pandas



¿Cómo encuentro los valores más cercanos en una serie Pandas a un número de entrada? (5)

Además de no responder completamente la pregunta, una desventaja adicional de los otros algoritmos discutidos aquí es que tienen que ordenar la lista completa. Esto da como resultado una complejidad de ~ N log (N) .

Sin embargo, es posible lograr los mismos resultados en ~ N. Este enfoque separa el marco de datos en dos subconjuntos, uno más pequeño y otro más grande que el valor deseado. El vecino inferior es el valor más grande en el marco de datos más pequeño y viceversa para el vecino superior.

Esto proporciona el siguiente fragmento de código:

def find_neighbours(value): exactmatch=df[df.num==value] if !exactmatch.empty: return exactmatch.index[0] else: lowerneighbour_ind = df[df.num<value].idxmax() upperneighbour_ind = df[df.num>value].idxmin() return lowerneighbour_ind, upperneighbour_ind

Este enfoque es similar al uso de la partición en pandas , que puede ser realmente útil cuando se trata de grandes conjuntos de datos y la complejidad se convierte en un problema.

La comparación de ambas estrategias muestra que para N grande, la estrategia de partición es de hecho más rápida. Para pequeñas N, la estrategia de clasificación será más eficiente, ya que se implementa en un nivel mucho más bajo. También es de una sola línea, lo que podría aumentar la legibilidad del código.

El código para replicar esta trama se puede ver a continuación:

from matplotlib import pyplot as plt import pandas import numpy import timeit value=3 sizes=numpy.logspace(2, 5, num=50, dtype=int) sort_results, partition_results=[],[] for size in sizes: df=pandas.DataFrame({"num":100*numpy.random.random(size)}) sort_results.append(timeit.Timer("df.iloc[(df[''num'']-value).abs().argsort()[:2]].index", globals={''find_neighbours'':find_neighbours, ''df'':df,''value'':value}).autorange()) partition_results.append(timeit.Timer(''find_neighbours(df,value)'', globals={''find_neighbours'':find_neighbours, ''df'':df,''value'':value}).autorange()) sort_time=[time/amount for amount,time in sort_results] partition_time=[time/amount for amount,time in partition_results] plt.plot(sizes, sort_time) plt.plot(sizes, partition_time) plt.legend([''Sorting'',''Partitioning'']) plt.title(''Comparison of strategies'') plt.xlabel(''Size of Dataframe'') plt.ylabel(''Time in s'') plt.savefig(''speed_comparison.png'')

He visto:

Estos se relacionan con la pitón de vainilla y no con los pandas.

Si tengo la serie:

ix num 0 1 1 6 2 4 3 5 4 2

Y yo ingreso 3, ¿cómo puedo encontrar (eficientemente)?

  1. El índice de 3 si se encuentra en la serie
  2. El índice del valor inferior y superior a 3 si no se encuentra en la serie.

Es decir. Con la serie anterior {1,6,4,5,2}, y la entrada 3, debería obtener valores (4,2) con índices (2,4).


Podrías usar argsort() como

Digamos, input = 3

In [198]: input = 3 In [199]: df.ix[(df[''num'']-input).abs().argsort()[:2]] Out[199]: num 2 4 4 2

df_sort es el marco de datos con 2 valores más cercanos.

In [200]: df_sort = df.ix[(df[''num'']-input).abs().argsort()[:2]]

Para el índice,

In [201]: df_sort.index.tolist() Out[201]: [2, 4]

Para los valores,

In [202]: df_sort[''num''].tolist() Out[202]: [4, 2]

Detalle, para la solución anterior df fue

In [197]: df Out[197]: num 0 1 1 6 2 4 3 5 4 2


Recomiendo usar iloc además de la respuesta de John Galt ya que esto funcionará incluso con un índice entero sin clasificar, ya que .ix primero mira las etiquetas de índice

df.iloc[(df[''num'']-input).abs().argsort()[:2]]


Si la serie ya está ordenada, un método eficiente para encontrar los índices es usar bisect . Un ejemplo:

idx = bisect_right(df[''num''].values, 3)

Entonces, para el problema citado en la pregunta, considerando que la columna "col" del marco de datos "df" está ordenada:

from bisect import bisect_right, bisect_left def get_closests(df, col, val): lower_idx = bisect_right(df[col].values, val) higher_idx = bisect_left(df[col].values, val) if higher_idx == lower_idx: return lower_idx else: return lower_idx, higher_idx

Es bastante eficiente encontrar el índice del valor específico "val" en la columna del marco de datos "col", o sus vecinos más cercanos, pero requiere que se ordene la lista.


Si su serie ya está ordenada, podría usar algo como esto.

def closest(df, col, val, direction): n = len(df[df[col] <= val]) if(direction < 0): n -= 1 if(n < 0 or n >= len(df)): print(''err - value outside range'') return None return df.ix[n, col] df = pd.DataFrame(pd.Series(range(0,10,2)), columns=[''num'']) for find in range(-1, 2): lc = closest(df, ''num'', find, -1) hc = closest(df, ''num'', find, 1) print(''Closest to {} is {}, lower and {}, higher.''.format(find, lc, hc)) df: num 0 0 1 2 2 4 3 6 4 8 err - value outside range Closest to -1 is None, lower and 0, higher. Closest to 0 is 0, lower and 2, higher. Closest to 1 is 0, lower and 2, higher.