Это не совсем конкретный ответ, но я думаю, что эта общая идея может сработать для вас. Идея состоит в том, чтобы создать новые столбцы в кадре данных, которые обозначают минимум и максимум каждого значения диапазона. Тогда вы можете довольно просто отфильтровать кадр данных на основе этих значений:
import numpy as np
import pandas as pd
df = pd.DataFrame()
df['Curl Ups'] = ['100-500', '100-300', '200-300']
df['Age'] = ['20-24', '25-29', '30-34']
df['Points'] = [50, 60, 70]
df['Category'] = ['Decent', 'Average', 'Good']
# Create new min & max columns
df['min_curlups'] = [int(x[:x.index('-')]) for x in df['Curl Ups']]
df['max_curlups'] = [int(x[x.index('-')+1:]) for x in df['Curl Ups']]
df['min_age'] = [int(x[:x.index('-')]) for x in df['Age']]
df['max_age'] = [int(x[x.index('-')+1:]) for x in df['Age']]
# Filter by contestant's value being within the range
num_curlups = 200
filtered_df = df.loc[(df['min_curlups'] < num_curlups) & (num_curlups < df['max_curlups'])]
print(filtered_df[['Points', 'Category']])
РЕДАКТИРОВАТЬ
Я пропустил многоиндексную часть ранее. На самом деле, я никогда не слышал об этой функциональности в Pandas. Ура для изучения новых вещей! Вот решение, которое, кажется, работает и, надеюсь, не требует особых настроек для вашего использования:
Во-первых, настройте тестовый DataFrame и добавьте в столбцы, которые мой метод нуждается в фильтрации:
import numpy as np
import pandas as pd
df = pd.DataFrame(index=[np.array(['IST', 'IST', 'IST', 'IST', 'ELSE', 'ELSE']),np.array(['Female', 'Male', 'Female', 'Male', 'Female', 'Male'])])
df.index.names = ['TEST', 'Gender']
df['Curl Ups'] = ['100-700', '100-300', '100-300', '100-300', '200-300', '400-500']
df['Age'] = ['20-24', '25-29', '30-34', '20-24', '30-34', '20-24']
df['Points'] = [90, 60, 70, 80, 70, 80]
df['Category'] = ['Outstanding', 'Average', 'Good', 'Better-than-me', 'Good', 'Better-than-me']
df['Level'] = ['Low', 'Medium', 'High', 'Low', 'Medium', 'High']
# Create 'Category-Level' combined column
df['Category-Level'] = df['Category'] + '-' + df['Level']
# Create new min & max columns
df['min_Curl Ups'] = [int(x[:x.index('-')]) for x in df['Curl Ups']]
df['max_Curl Ups'] = [int(x[x.index('-')+1:]) for x in df['Curl Ups']]
df['min_Age'] = [int(x[:x.index('-')]) for x in df['Age']]
df['max_Age'] = [int(x[x.index('-')+1:]) for x in df['Age']]
df
А вот функция, которая должна принимать входные данные, аналогичные требуемым, и выводить необходимую информацию:
def filter_multiindex_df( df, inputs, input_fields=['TEST', 'Gender', 'Age', 'Curl Ups'], outputs=['Points', 'Category-Level'] ):
# Pull out the inputs corresponding to multi-level indices & filter to get the DF cross-section
input_idx = [i for i,x in enumerate(input_fields) for j,y in enumerate(df.index.names) if x == y]
index_inputs = [inputs[i] for i in input_idx]
filt_df = df.xs(index_inputs)
# Filter based on the rest of the inputs that weren't indices
for i, field in enumerate(input_fields):
if i not in input_idx:
filt_df = filt_df.loc[ (filt_df['min_'+field] <= inputs[i]) & (inputs[i] <= filt_df['max_'+field])]
return filt_df[outputs].values[0]
# Test the function
print(filter_multiindex_df(df, inputs=['IST', 'Female', 22, 100]))