Выпадающий выбор Plotly не обновляет графики правильно - PullRequest
0 голосов
/ 27 апреля 2020

Я хочу создать интерактивный график с возможностью выбора для сохранения отдельного файла HTML, поэтому я не хочу использовать da sh.

Цель состоит в том, чтобы отображать тенденции цен на жилье с помощью Возможность сделать выбор по региону и количеству номеров. Проблема в том, что после изменения выбора все графики остаются активными без корректного обновления. Может ли кто-нибудь помочь решить эту проблему? Я сделал сюжет на своем родном языке (литовский). Для удобства я перевел имена переменных в код.

Текущий вывод: Output example, with button not working corretly

Пример ввода данных

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')

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

Вы ищете что-то вроде:

Сортировка данных и добавление выпадающего списка в df

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 с помощью кнопок, которые вы хотите в раскрывающемся списке и играть с видимыми следами.

1 голос
/ 27 апреля 2020

Следующим может потребоваться немного изменить гибкость в отношении количества комнат. Но следующий график позволит вам отобразить цену за количество номеров для выбранного города. Так что это предложение с двумя кнопками.

enter image description here

Полный код:

# 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...