我想创建一个可以选择的交互式情节来保存一个独立的HTML文件,因此我不想使用dash。
我的目标是显示住房价格趋势,并可以选择地区和房间数量。问题是,一旦我改变了选择,所有的地块仍然是活动的,没有正确更新。谁能帮我解决这个问题?我已经用我自己的语言(立陶宛语)制作了绘图。为了方便,我翻译了代码中的变量名。
输入数据示例
df = pd.DataFrame({'Region_title': {0: 'Kaunas',
1: 'Kaunas',
2: 'Kaunas',
3: 'Kaunas',
4: 'Kaunas',
5: 'Kaunas',
6: 'Vilnius',
7: 'Vilnius',
8: 'Vilnius',
9: 'Vilnius',
10: 'Vilnius',
11: 'Vilnius'},
'Room_number': {0: 1,
1: 2,
2: 1,
3: 2,
4: 1,
5: 2,
6: 1,
7: 2,
8: 1,
9: 2,
10: 1,
11: 2},
'Year_quarter': {0: '2010-01',
1: '2010-01',
2: '2014-01',
3: '2014-01',
4: '2019-01',
5: '2019-01',
6: '2010-01',
7: '2010-01',
8: '2014-01',
9: '2014-01',
10: '2019-01',
11: '2019-01'},
'Price': {0: 100,
1: 200,
2: 300,
3: 400,
4: 500,
5: 600,
6: 300,
7: 500,
8: 700,
9: 900,
10: 1100,
11: 1300}})
import plotly.offline as pyo
import plotly.graph_objs as go
import numpy as np
def compare_elements_with_single_value(all_list, value):
all_comparison = []
for elem in all_list:
comp = elem == value
all_comparison.append(comp)
return(all_comparison) #e.g. [False, False, ...., True]
df = df.sort_values(["Region_title", "Room_number", "Year_quarter"])
fig = go.Figure()
region_list = df['Region_title'].unique()
room_number_list = df['Room number'].unique()
all_list = []
for region in region_list:
for room_number in room_number_list:
all_list.append(str(region) + " Room number " + str(room_number))
for region in region_list:
for room_number in room_number_list:
region_room_number = str(region) + " Room number " + str(room_number)
fig.add_trace(go.Scatter(
x = df[(df['Region_title'] == region)
& (df['Room_number'] == room_number)]['Year_quarter'],
y = df[(df['Region_title'] == region)
& (df['Room_number'] == room_number)]['price'],
text = "Average price",
hoverinfo = "x+y",
name = region_room_number,
mode ='lines+markers',
marker={'size': 10, 'opacity': 0.5, 'line': {'width': 0.5, 'color': 'white'
}}))
updatemenu= []
buttons=[]
for region in region_list:
for room_number in room_number_list:
region_room_number = str(region) + " Room number " + str(room_number)
buttons.append(dict(method='restyle',
label = str(region) + " Room_number " + str(room_number),
args = [{'x':[df[(df['Region_title'] == region)
& (df['Room_number'] == room_number)]['Year_quarter']]},
{'y':[df[(df['Region_title'] == region)
& (df['Room_number'] == room_number)]['Price']]},
{'visible': compare_elements_with_single_value(all_list, region_room_number)}
]
))
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True
fig.update_layout(updatemenus=updatemenu,
showlegend=True,
yaxis_title="EUR / m2")
fig.show()
pyo.plot(fig, filename='Output/Flat price.html')
你是否在寻找类似的东西。
import plotly.graph_objects as go
import pandas as pd
df = df.sort_values(["Region_title", "Room_number", "Year_quarter"])\
.reset_index(drop=True)
df["dropdown"] = df.apply(lambda x: '{} - Room nbr {}'.format(x['Region_title'], x["Room_number"]),
axis=1)
colors_list = ['#1f77b4', # muted blue
'#ff7f0e', # safety orange
'#2ca02c', # cooked asparagus green
'#d62728', # brick red
'#9467bd', # muted purple
'#8c564b', # chestnut brown
'#e377c2', # raspberry yogurt pink
'#7f7f7f', # middle gray
'#bcbd22', # curry yellow-green
'#17becf' # blue-teal
]
dfs = list(df.groupby('dropdown'))
first_title = dfs[0][0]
traces = []
buttons = []
for i,d in enumerate(dfs):
visible = [False]*4
visible[i] = True
name = d[0]
traces.append(
go.Scatter(x = d[1]["Year_quarter"],
y = d[1]["Price"],
text = "Average price",
hoverinfo = "x+y",
mode = 'lines+markers',
visible = True if i==0 else False,
name = name,
marker = {'color':colors_list[i%len(colors_list)],
'size': 10,
'opacity': 0.5,
'line': {'width': 0.5,
'color': 'white'}
}
))
buttons.append(dict(label=name,
method="update",
args=[{"visible":visible},
{"title":f"Title {name}"}]))
updatemenus = [{'active':0, "buttons":buttons}]
fig = go.Figure(data=traces,
layout=dict(updatemenus=updatemenus))
fig.update_layout(title=first_title, title_x=0.5)
fig.update_yaxes(range=[0, df["Price"].max()*1.2])
fig.show()
这里的想法是通过下拉中你想要的按钮来分割df,并发挥可见的痕迹。
下面可能需要对房间数量的灵活性进行一些调整。但是下面的图可以让你显示所选城市的房间数的价格。所以这是一个建议与 两种 按钮。
完整的代码。
# Imports
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# data
df = pd.DataFrame({'Region_title': {0: 'Kaunas',
1: 'Kaunas',
2: 'Kaunas',
3: 'Kaunas',
4: 'Kaunas',
5: 'Kaunas',
6: 'Vilnius',
7: 'Vilnius',
8: 'Vilnius',
9: 'Vilnius',
10: 'Vilnius',
11: 'Vilnius'},
'Room_number': {0: 1,
1: 2,
2: 1,
3: 2,
4: 1,
5: 2,
6: 1,
7: 2,
8: 1,
9: 2,
10: 1,
11: 2},
'Year_quarter': {0: '2010-01',
1: '2010-01',
2: '2014-01',
3: '2014-01',
4: '2019-01',
5: '2019-01',
6: '2010-01',
7: '2010-01',
8: '2014-01',
9: '2014-01',
10: '2019-01',
11: '2019-01'},
'Task': {0: 100,
1: 200,
2: 300,
3: 400,
4: 500,
5: 600,
6: 300,
7: 500,
8: 700,
9: 900,
10: 1100,
11: 1300}})
# split df by Region_titles
Region_titles = df['Region_title'].unique().tolist()
dates = df['Year_quarter'].unique().tolist()
dfs = {}
# dataframe collection grouped by Region_titles
for Region_title in Region_titles:
#print(Region_title)
dfs[Region_title]=pd.pivot_table(df[df['Region_title']==Region_title],
values='Task',
index=['Year_quarter'],
columns=['Room_number'],
aggfunc=np.mean)
# plotly start
fig = go.Figure()
# get column names from first dataframe in the dict
colNames = list(dfs[list(dfs.keys())[0]].columns)
#xValues=
# one trace for each column per dataframe: AI and RANDOM
for col in colNames:
fig.add_trace(go.Scatter(x=dates,
visible=True,
#name=col
)
)
# menu setup
updatemenu= []
# buttons for menu 1, names
buttons=[]
# create traces for each Room_number:
for df in dfs.keys():
buttons.append(dict(method='update',
label=df,
visible=True,
args=[#{'visible':True},
#{'x':[dfs[df]['AI'].index, dfs[df]['RANDOM'].index]},
{'y':[dfs[df][1].values, dfs[df][2].values]}])
)
# buttons for menu 2, Room_numbers
b2_labels = colNames
# matrix too feed all visible arguments for all traces
# so that they can be shown or hidden by choice
b2_show = [list(b) for b in [e==1 for e in np.eye(len(b2_labels))]]
buttons2=[]
buttons2.append({'method': 'update',
'label': 'All',
'args': [{'visible': [True]*4}]})
# create buttons to show or hide
for i in range(0, len(b2_labels)):
buttons2.append(dict(method='update',
label=b2_labels[i],
args=[{'visible':b2_show[i]}]
)
)
# add option for button two to hide all
buttons2.append(dict(method='update',
label='None',
args=[{'visible':[False]*4}]
)
)
# some adjustments to the updatemenus
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
your_menu2=dict()
updatemenu.append(your_menu2)
updatemenu[1]
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True
updatemenu[1]['buttons']=buttons2
updatemenu[1]['y']=0.6
fig.update_layout(showlegend=False, updatemenus=updatemenu)
fig.show()