Графические следы, невидимые после обновления меню

CrashingWater спросил: 13 июня 2018 в 07:46 в: python

Я рисую диаграммы рассеяния на карте США (51 трассировка для 51 состояния, включая DC и 4 следа в течение 4 разных лет). У меня есть updatemenus с двумя кнопками, которые переключаются между одним рассеивателем с легендой (51 трасса) и другим рассеивателем с ползунком внизу (4 следа). Я первоначально установил 4 следа (годы) visible = False, потому что мне сначала нужно было отобразить только 51 трассировку, но когда я нажимаю кнопку, чтобы переключиться на рассеиватель со слайдером и установить первые 51 трассировку visible = False и последние 4 трассы visible = [True, False, False, False] ни одна из моих трасс не видна на карте.

Не уверен, почему это происходит. Когда я устанавливаю cities_year visible = True при первом создании рассеивателя (т. Е. Они видны изначально), появляются следы, но я не хочу этого, потому что тогда у меня все мои точки рассеяния строятся дважды друг на друга.

Вот какой код для создания набора данных:

data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv')
data = data.iloc[:400] # Keep only first 400 samples
data.loc[:100, 'year'] = '1990'
data.loc[100:200, 'year'] = '1991'
data.loc[200:300, 'year'] = '1992'
data.loc[300:, 'year'] = '1993'

Я использую плагиновую версию 2.7.0 и автономный график. Вот мой заговор код:

cities = []
for state in data['name'].value_counts().index:
    data_sub = data.loc[data['name'] == state]
    city = dict(
        type = 'scattergeo',
        visible = True,
        locationmode = 'USA-states',
        lon = data_sub['lon'],
        lat = data_sub['lat'],
        mode = 'markers',
        marker = dict(
            size = 8,
            color = "rgb(255, 102, 102)",
            opacity = 0.4,
            line = dict(
                width=0.5,
                color='rgb(255, 102, 102)'
            )
        ),
        name = state
    )
    cities.append(city)cities_year = []
for year in sorted(data.year.value_counts().index):
    data_sub = data.loc[data['year'] == year]
    city = dict(
        type = 'scattergeo',
        visible = False,
        locationmode = 'USA-states',
        lon = data_sub['lon'],
        lat = data_sub['lat'],
        mode = 'markers',
        marker = dict(
            size = 8,
            color = "rgb(255, 102, 102)",
            opacity = 0.4,
            line = dict(
                width=0.5,
                color='rgb(255, 102, 102)'
            )
        ),
        name = str(year)
    )
    cities_year.append(city)slider = [dict(active = 0,
               pad = dict(t = 1),
               steps = [dict(args = ["visible", ([False] * len(cities)) + [True, False, False, False]], 
                             label = "1990",
                             method = "restyle"
                            ),
                        dict(args = ["visible", ([False] * len(cities)) + [False, True, False, False]],
                             label = "1991", 
                             method = "restyle"
                            ),
                        dict(args = ["visible", ([False] * len(cities)) + [False, False, True, False]],
                             label = "1992",
                             method = "restyle"
                            ),
                        dict(args = ["visible", ([False] * len(cities)) + [False, False, False, True]],
                             label = "1993",
                             method = "restyle"
                            )
                       ]
              )
         ]updatemenus = list([
    dict(type="buttons",
         active=0,
         buttons=list([   
            dict(label = 'states',
                 method = 'update',
                 args = [dict(visible = ([True] * len(cities)) + ([False] * len(cities_year))),
                         dict(sliders = [],
                              showlegend = True)]),
            dict(label = 'years',
                 method = 'update',
                 args = [dict(visible = ([False] * len(cities)) + [True, False, False, False]),
                         dict(sliders = slider,
                              showlegend = False)])
        ]),
     )
])layout = dict(
    title = 'myplot',
    geo = dict(
        scope='usa',
        projection=dict(type='albers usa'),
        showland=True,
        showlakes = True,
        landcolor = 'rgb(217, 217, 217)',
        subunitwidth=1,
        countrywidth=1,
        subunitcolor="rgb(255, 255, 255)",
        countrycolor="rgb(255, 255, 255)"
    ),
    updatemenus=updatemenus
)trace_data = cities + cities_year
fig = dict(data=trace_data, layout=layout)
iplot(fig, validate=False)

1 ответ

Nilesh Ingle ответил: 19 июня 2018 в 12:44

Проблема: если я правильно понимаю, когда выполняется вышеуказанный code: iplot() создает график scattergeo() с двумя кнопками с надписью "states 'и' years '. Из этих двух кнопок кнопка "states" активна и показывает ее график (с "красными точками" и legend). Кнопка "years" соответствует графику с опцией slider (years 1990 на 1993)). Теперь, когда нажата кнопка "years", ожидается, что "красные точки" должны появиться через maps (для year 1990). Однако этого не происходит.

Задание при выполнении кода выше

Диаграмма проблем без точек данных при нажатии кнопки "лет"

Попытка решения:

Если visible установлен в True (ниже) в city dictionary для cities_year list traces, тогда проблема решена. То есть после запуска code график появляется с двумя кнопками. Теперь, когда "years" button является clicked, он показывает "красные точки" для slider в year 1990. Настройка visible=True может быть важной, поскольку она может быть для самого первого экземпляра, когда загружается или отображается plot. (Jupyter Notebook 5.0.0; Python 3.6.6)

cities_year = []
for year in sorted(data.year.value_counts().index):
    data_sub = data.loc[data['year'] == year]
    city = dict(
        type = 'scattergeo',
        visible = True,

Запуск после code:

Теперь, когда кнопка 'летний щелкают участок является:

Изменить - 1 - - - - - - - - - - - - - - - -

slider все еще не работает должным образом. Однако нашел работу, используя только legends для выбора year.

    dict(label = 'years',
         method = 'restyle',
         args = [dict(visible = ([False] * len(cities)) + [True, True, True, True]),
                 dict(sliders = slider,
                      showlegend = False)])

Edit - 2 - - - - - - - - - - - - - - - -

Проблема все еще не решена, но код ниже может помочь сузить поиск ошибки. В code ниже приведены два набора данных для: (1) go.Scatter() и (2) go.Scattergeo(). Всего в 5 всего rows dataframe, чтобы он был простым. Обратите внимание, что хотя код code для генерации набора данных выборки отличается, следующий код работает для построения обоих указанных наборов данных. Он показывает, что go.Scatter() отлично работает, и go.Scattergeo() имеет проблему, упомянутую в вопросе.

Импортировать библиотеки

import datetime
from datetime import date
import pandas as pd
import numpy as np
from plotly import __version__
%matplotlib inlineimport cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot 
init_notebook_mode(connected=True)init_notebook_mode(connected=True)
cf.go_offline()import plotly.offline as pyo
import plotly.graph_objs as go
from plotly.tools import FigureFactory as FFimport json

Создайте данные для go.Scatter()

# Create random numbers
x = np.random.randn(100)
y = 10 + np.random.randn(100)
z = np.linspace(-3,2,100)
df = pd.DataFrame({'x':x, 'y':y, 'z':z})
df.head(2)# Create traces
trace1 = go.Scatter(visible = True, x=df.x, y=df.y, mode='markers', name='trace1', marker=dict(color='red'))
trace2 = go.Scatter(visible = True, x=df.x, y=df.z, mode='markers', name='trace2', marker=dict(color='black'))trace3 = go.Scatter(visible = False, x=df.x, y=df.y*df.y, mode='markers', name='trace3', marker=dict(color='blue'))
trace4 = go.Scatter(visible = False, x=df.x, y=df.z*0.5, mode='markers', name='trace4', marker=dict(color='orange'))
trace5 = go.Scatter(visible = False, x=df.x, y=df.z*df.z, mode='markers', name='trace5', marker=dict(color='purple'))# Create list of traces 
data = [trace1, trace2, trace3, trace4, trace5]

Создайте данные для go.Scattergeo()

# Create dataframe for cities
df = pd.DataFrame({'name': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Philadelphia'],
                  'pop': [8287238, 3826423, 2705627, 2129784, 1539313],
                  'lat': [40.730599, 34.053717, 41.875555, 29.758938, 39.952335],
                  'lon': [-73.986581, -118.242727, -87.624421, -95.367697, -75.163789],
                   'year': [1990, 1991, 1992, 1993, 1991]
                })# Create city traces manually without for-loop
trace1 = go.Scattergeo(visible=True,name = 'trace1',locationmode = 'USA-states',
                   lon = df[df['name']=='New York']['lon'], lat = df[df['name']=='New York']['lat'], 
                   mode = 'markers',marker = dict(size=10, symbol='circle-open', color = "red")) 
trace2 = go.Scattergeo(visible=True,name = 'trace2',locationmode = 'USA-states',
                   lon = df[df['name']=='Los Angeles']['lon'], lat = df[df['name']=='Los Angeles']['lat'], 
                   mode = 'markers',marker = dict(size=10, symbol='circle-open', color = "red")) trace3 = go.Scattergeo(visible=False, name = 'trace3', locationmode = 'USA-states',
                   lon = df[df['year']==1990]['lon'], lat = df[df['year']==1990]['lat'],
                   mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
                  ) 
trace4 = go.Scattergeo(visible=False, name = 'trace4', locationmode = 'USA-states',
                   lon = df[df['year']==1991]['lon'], lat = df[df['year']==1991]['lat'],
                   mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
                  )  
trace5 = go.Scattergeo(visible=False, name = 'trace5', locationmode = 'USA-states',
                   lon = df[df['year']==1992]['lon'], lat = df[df['year']==1992]['lat'],
                   mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
                  ) # Create list of traces
data = [trace1, trace2, trace3, trace4, trace5]

Code ниже, является общим для двух вышеуказанных наборов данных

# Create slider
sliders = [dict(active=-1,
               pad = {"t": 1},
               currentvalue = {"prefix": "Plot Number: "},
               execute=True, 
               steps = [
                        dict(args = ["visible", [False, False, True, False, False]],
                             label = "trace3", 
                             method = "restyle"
                            ),
                        dict(args = ["visible", [False, False, False,True, False]],
                             label = "trace4",
                             method = "restyle"
                            ),
                        dict(args = ["visible", [False, False, False, False, True]],
                             label = "trace5",
                             method = "restyle"
                            )
                       ],
                transition = 0
              )
         ]# Create updatemenus
updatemenus = list([
    dict(
        buttons= list([
                        dict(
                             args = [
                                    {'visible': (True, False, False, False, False)},
                                    {'sliders':[], 'showlegend': True, 'title': 'Plots only'}
                                    ],
                             label = 'single_plot',
                             method = 'update'                    ),
                         dict(
                             args = [
                                    {'visible': (False, False, True, False, False)},
                                    {'sliders':sliders, 'showlegend': True, 'title': 'Plots with slider'}
                                    ],
                             label = 'multi_plots',
                             method = 'update'                    )
        ]),
        direction = 'left',
        pad = {'r': 10, 't': 10},
        showactive = True,
        type = 'buttons',
        x = 0.1,
        xanchor = 'left',
        y = 1,
        yanchor = 'top' 
    )])# Create layout
layout = go.Layout(title='Chart') #, geo=dict(scope='usa')) #<--uncomment for Scattergeo() ... optional
layout['updatemenus'] = updatemenus# Plot data
fig = go.Figure(data=data, layout=layout)
pyo.offline.plot(fig)

Графики с go.Scatter()

(Слева: график для button 'single_plot '; Right: plot для button' multi_plots ')

Обратите внимание, что здесь график в точках данных справа корректно отображаться после нажатия "multi_points" button.

Графики с go.Scattergeo()

(Слева: график для button 'single_plot'; для button 'multi_plots')

Обратите внимание: здесь нет данных на графике справа, после нажатия клавиши multi_points '.

CrashingWater ответил: 17 июня 2018 в 08:12
Я пробовал то, что вы сказали, но делал это каждый раз в два раза. Если вы установите цвет marker dict на что-то вроде color = "rgb(113, 8, 80)" внутри cities_year dict, то вы можете увидеть два цвета на начальном графике, где states активна
Nilesh Ingle ответил: 17 июня 2018 в 10:46
Спасибо за разъяснение. Теперь я понимаю этот вопрос. Я обновил предыдущий пост с обходным решением. Однако до сих пор не удалось выяснить, как получить slider для показа. Вероятно, отсутствует код somthing в call до updatemenus. Я обновлю сообщение, если смогу найти решение для слайдера.
Nilesh Ingle ответил: 19 июня 2018 в 12:48
Я попробовал другой подход. Edit-2 показывает, что code, который запускает два разных data набора traces через тот же code, чтобы создать разные plots. Кажется, проблема связана с go.Scattergeo(). Не уверен, что это bug или способ его реализации. Я просматриваю документацию plotly, но не могу найти, что это сделал parameter. go.Scatter() работает нормально.

Дополнительное видео по вопросу: Графические следы, невидимые после обновления меню

Getting Started with Plotly and Jupyter!

Python Hacks : Data Visualization using Plotly - Introduction

Plot.ly Introduction