Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

262
Vistas
determinar el rango de un valor usando una tabla de consulta

Tengo un df con números:

 numbers = pd.DataFrame(columns=['number'], data=[ 50, 65, 75, 85, 90 ])

y un df con rangos (ver tabla):

 ranges = pd.DataFrame( columns=['range','range_min','range_max'], data=[ ['A',90,100], ['B',85,95], ['C',70,80] ] )

Quiero determinar en qué rango (en la segunda tabla) cae un valor (en la primera tabla). Tenga en cuenta que los rangos se superponen y los límites son inclusivos. También tenga en cuenta que el marco de datos estándar anterior tiene 3 rangos; sin embargo, este marco de datos se genera dinámicamente. Puede tener de 2 a 7 rangos.

Resultado deseado:

 numbers = pd.DataFrame(columns=['number','detected_range'], data=[ [50,'out_of_range'], [65, 'out_of_range'], [75,'C'], [85,'B'], [90,'overlap'] * could be A or B * ])

Resolví esto con un bucle for pero esto no se adapta bien a un gran conjunto de datos que estoy usando. Además, el código es demasiado extenso y poco elegante. Vea abajo:

 numbers['detected_range'] = nan for i, row1 in number.iterrows(): for j, row2 in ranges.iterrows(): if row1.number<row2.range_min and row1.number>row2.range_max: numbers.loc[i,'detected_range'] = row1.loc[j,'range'] else if (other cases...): ...and so on...

¿Cómo podría hacer esto?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Puede usar un poco de operaciones vectoriales numpy para generar máscaras y usarlas para select sus etiquetas:

 import numpy as np a = numbers['number'].values # numpy array of numbers r = ranges.set_index('range') # dataframe of min/max with labels as index m1 = (a>=r['range_min'].values[:,None]).T # is number above each min m2 = (a<r['range_max'].values[:,None]).T # is number below each max m3 = (m1&m2) # combine both conditions above # NB. the two operations could be done without the intermediate variables m1/m2 m4 = m3.sum(1) # how many matches? # 0 -> out_of_range # 2 -> overlap # 1 -> get column name # now we select the label according to the conditions numbers['detected_range'] = np.select([m4==0, m4==2], # out_of_range and overlap ['out_of_range', 'overlap'], # otherwise get column name default=np.take(r.index, m3.argmax(1)) )

producción:

 number detected_range 0 50 out_of_range 1 65 out_of_range 2 75 C 3 85 B 4 90 overlap

editar:

Funciona con cualquier número de intervalos en rangos.

ejemplo de salida con extra ['D',50,51] :

 number detected_range 0 50 D 1 65 out_of_range 2 75 C 3 85 B 4 90 overlap
over 4 years ago · Santiago Trujillo Denunciar

0

Pandas IntervalIndex encaja aquí; sin embargo, dado que sus datos tienen puntos superpuestos, un bucle for es el enfoque que usaré aquí (para índices únicos que no se superponen, pd.get_indexer es un enfoque rápido):

 intervals = pd.IntervalIndex.from_arrays(ranges.range_min, ranges.range_max, closed='both') box = [] for num in numbers.number: bools = intervals.contains(num) if bools.sum()==1: box.append(ranges.range[bools].item()) elif bools.sum() > 1: box.append('overlap') else: box.append('out_of_range') numbers.assign(detected_range = box) number detected_range 0 50 out_of_range 1 65 out_of_range 2 75 C 3 85 B 4 90 overlap
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda