我正在尝试创建一组
SelectMultiple
小部件,这些小部件将用作 Pandas df
的过滤器。
以下为示例数据。这个想法是,它是所有列中可用的唯一值的独特组合。
import pandas as pd
data = {
'category1': ['A', 'A', 'B', 'B', 'C', 'B'],
'category2': ['X', 'Y', 'X', 'Z', 'Y', 'K'],
'country': ['USA', 'USA', 'UK', 'UK', 'Canada', 'Germany'],
'department': ['Dept1', 'Dept2', 'Dept1', 'Dept2', 'Dept1', 'Dept4'],
'category3': ['Cat1', 'Cat2', 'Cat1', 'Cat2', 'Cat1', 'Cat2'],
'gender': ['Male', 'Female', 'Male', 'Female', 'Male', 'Male'],
'brand': ['Brand1', 'Brand2', 'Brand3', 'Brand4', 'Brand5', 'Brand2']
}
df = pd.DataFrame(data)
类别1 | 类别2 | 国家 | 部门 | 类别3 | 性别 | 品牌 | |
---|---|---|---|---|---|---|---|
0 | A | X | 美国 | 1部 | 猫1 | 男 | 品牌1 |
1 | A | 是 | 美国 | 2部 | 猫2 | 女 | 品牌2 |
2 | B | X | 英国 | 1部 | 猫1 | 男 | 品牌3 |
3 | B | Z | 英国 | 2部 | 猫2 | 女 | 品牌4 |
4 | C | 是 | 加拿大 | 1部 | 猫1 | 男 | 品牌5 |
5 | B | K | 德国 | 4 部 | 猫2 | 男 | 品牌2 |
我想要单向依赖(从左到右),这意味着我总是首先选择
category1
。这个选择限制了所有其他选择。然后我选择category2
等等。每一步的选择都会更新。
这是我最接近的解决方案:
import ipywidgets as widgets
from IPython.display import display
def update_options(category1, category2, country, department, category3, gender):
filtered_df = df.copy()
if category1:
filtered_df = filtered_df[filtered_df['category1'].isin(category1)]
if category2:
filtered_df = filtered_df[filtered_df['category2'].isin(category2)]
if country:
filtered_df = filtered_df[filtered_df['country'].isin(country)]
if department:
filtered_df = filtered_df[filtered_df['department'].isin(department)]
if category3:
filtered_df = filtered_df[filtered_df['category3'].isin(category3)]
if gender:
filtered_df = filtered_df[filtered_df['gender'].isin(gender)]
category2_options = filtered_df['category2'].unique().tolist()
country_options = filtered_df['country'].unique().tolist()
department_options = filtered_df['department'].unique().tolist()
category3_options = filtered_df['category3'].unique().tolist()
gender_options = filtered_df['gender'].unique().tolist()
brand_options = filtered_df['brand'].unique().tolist()
# Update options for dropdowns
category2_dropdown.options = category2_options
country_dropdown.options = country_options
department_dropdown.options = department_options
category3_dropdown.options = category3_options
gender_dropdown.options = gender_options
brand_dropdown.options = brand_options
# Define initial options for category1 and category2
category1_options = df['category1'].unique().tolist()
category2_options = df['category2'].unique().tolist()
# Create dropdown widgets
category1_dropdown = widgets.SelectMultiple(options=category1_options, description='Category 1:')
category2_dropdown = widgets.SelectMultiple(options=category2_options, description='Category 2:')
country_dropdown = widgets.SelectMultiple(description='Country:')
department_dropdown = widgets.SelectMultiple(description='Department:')
category3_dropdown = widgets.SelectMultiple(description='Category 3:')
gender_dropdown = widgets.SelectMultiple(description='Gender:')
brand_dropdown = widgets.SelectMultiple(description='Brand:')
# Use interact to dynamically update options
widgets.interact(update_options,
category1=category1_dropdown,
category2=category2_dropdown,
country=country_dropdown,
department=department_dropdown,
category3=category3_dropdown,
gender=gender_dropdown)
# Display widgets
display(brand_dropdown) # the others are displayed with widgets.interact() above
它仅部分起作用:后续列的选择已更新,但如果有多个列,我不能只选择一个,只能选择全部。例如,如果我选择
category1=B
,然后在 category2
小部件上,我会正确看到选项 X Z K
,但仅单击一个不起作用(它不会被选中),只能拖动所有选项。
有人知道我错过了什么吗?
非常感谢!
我设法做对了。问题是,如果小部件全部位于一个函数中(一种循环引用),那么小部件会变得混乱。它们需要向下分配。
import pandas as pd
import ipywidgets as widgets
from IPython.display import display
# Sample DataFrame
data = {
'category1': ['A', 'A', 'B', 'B', 'C'],
'category2': ['X', 'Y', 'X', 'Z', 'Y'],
'country': ['USA', 'USA', 'UK', 'UK', 'Canada'],
'department': ['Dept1', 'Dept2', 'Dept1', 'Dept2', 'Dept1'],
'category3': ['Cat1', 'Cat2', 'Cat1', 'Cat2', 'Cat1'],
'gender': ['Male', 'Female', 'Male', 'Female', 'Male'],
'brand': ['Brand1', 'Brand2', 'Brand3', 'Brand4', 'Brand5']
}
df = pd.DataFrame(data)
# Function to update options of category2_dropdown based on category1 selection
def update_category2_options(change):
if change.new:
filtered_df = df[df['category1'].isin(change.new)]
options = filtered_df['category2'].unique()
category2_dropdown.options = options
else:
category2_dropdown.options = []
# Function to update options of country_dropdown based on category1 and category2 selections
def update_country_options(change):
if change.new:
filtered_df = df[df['category1'].isin(category1_dropdown.value)]
if category2_dropdown.value:
filtered_df = filtered_df[df['category2'].isin(category2_dropdown.value)]
options = filtered_df['country'].unique()
country_dropdown.options = options
else:
country_dropdown.options = []
# Function to update options of department_dropdown based on category1, category2, and country selections
def update_department_options(change):
if change.new:
filtered_df = df[df['category1'].isin(category1_dropdown.value)]
if category2_dropdown.value:
filtered_df = filtered_df[df['category2'].isin(category2_dropdown.value)]
if country_dropdown.value:
filtered_df = filtered_df[df['country'].isin(country_dropdown.value)]
options = filtered_df['department'].unique()
department_dropdown.options = options
else:
department_dropdown.options = []
# Function to update options of category3_dropdown based on category1, category2, country, and department selections
def update_category3_options(change):
if change.new:
filtered_df = df[df['category1'].isin(category1_dropdown.value)]
if category2_dropdown.value:
filtered_df = filtered_df[df['category2'].isin(category2_dropdown.value)]
if country_dropdown.value:
filtered_df = filtered_df[df['country'].isin(country_dropdown.value)]
if department_dropdown.value:
filtered_df = filtered_df[df['department'].isin(department_dropdown.value)]
options = filtered_df['category3'].unique()
category3_dropdown.options = options
else:
category3_dropdown.options = []
# Function to update options of gender_dropdown based on category1, category2, country, department, and category3 selections
def update_gender_options(change):
if change.new:
filtered_df = df[df['category1'].isin(category1_dropdown.value)]
if category2_dropdown.value:
filtered_df = filtered_df[df['category2'].isin(category2_dropdown.value)]
if country_dropdown.value:
filtered_df = filtered_df[df['country'].isin(country_dropdown.value)]
if department_dropdown.value:
filtered_df = filtered_df[df['department'].isin(department_dropdown.value)]
if category3_dropdown.value:
filtered_df = filtered_df[df['category3'].isin(category3_dropdown.value)]
options = filtered_df['gender'].unique()
gender_dropdown.options = options
else:
gender_dropdown.options = []
def update_brand_options(change):
if change.new:
filtered_df = df[df['category1'].isin(category1_dropdown.value)]
if category2_dropdown.value:
filtered_df = filtered_df[df['category2'].isin(category2_dropdown.value)]
if country_dropdown.value:
filtered_df = filtered_df[df['country'].isin(country_dropdown.value)]
if department_dropdown.value:
filtered_df = filtered_df[df['department'].isin(department_dropdown.value)]
if category3_dropdown.value:
filtered_df = filtered_df[df['category3'].isin(category3_dropdown.value)]
if gender_dropdown.value:
filtered_df = filtered_df[df['gender'].isin(gender_dropdown.value)]
options = filtered_df['brand'].unique()
brand_dropdown.options = options
else:
brand_dropdown.options = []
# Create dropdown widgets
category1_dropdown = widgets.SelectMultiple(description='Category 1:', options=df['category1'].unique())
category2_dropdown = widgets.SelectMultiple(description='Category 2:', options=[])
country_dropdown = widgets.SelectMultiple(description='Country:', options=[])
department_dropdown = widgets.SelectMultiple(description='Department:', options=[])
category3_dropdown = widgets.SelectMultiple(description='Category 3:', options=[])
gender_dropdown = widgets.SelectMultiple(description='Gender:', options=[])
brand_dropdown = widgets.SelectMultiple(description='Brand:', options=[])
# Use observe to dynamically update options
category1_dropdown.observe(update_category2_options, names='value')
category1_dropdown.observe(update_country_options, names='value')
category1_dropdown.observe(update_department_options, names='value')
category1_dropdown.observe(update_category3_options, names='value')
category1_dropdown.observe(update_gender_options, names='value')
category1_dropdown.observe(update_brand_options, names='value')
category2_dropdown.observe(update_country_options, names='value')
category2_dropdown.observe(update_department_options, names='value')
category2_dropdown.observe(update_category3_options, names='value')
category2_dropdown.observe(update_gender_options, names='value')
category2_dropdown.observe(update_brand_options, names='value')
country_dropdown.observe(update_department_options, names='value')
country_dropdown.observe(update_category3_options, names='value')
country_dropdown.observe(update_gender_options, names='value')
country_dropdown.observe(update_brand_options, names='value')
department_dropdown.observe(update_category3_options, names='value')
department_dropdown.observe(update_gender_options, names='value')
department_dropdown.observe(update_brand_options, names='value')
category3_dropdown.observe(update_gender_options, names='value')
category3_dropdown.observe(update_brand_options, names='value')
gender_dropdown.observe(update_brand_options, names='value')
# Display widgets
display(category1_dropdown, category2_dropdown, country_dropdown, department_dropdown, category3_dropdown, gender_dropdown, brand_dropdown)