我正在构建一个Dash应用程序,并尝试利用Plotly的category_order
和color_discrete_sequence
为驻留在dataframe列中的唯一字符串值分配特定的颜色。这些参数似乎被描述为获取非数字数据(例如字符串)并按照用户指定的顺序为其分配颜色。但是,该代码似乎没有用,我对所有数据点仅获得单色黑点(下图)。希望有人可以看到我所缺少的内容,并提供有关如何使用这些参数或其他过程来获得预期结果的指导。
我的过程如下:
我有一个数据框,其中包含“ band”,“ lat”和“ lon”列,其中lat和lon将指定散点图框图中点的位置,并且band取值列表,例如:< / p>
data = {'band':['10m','10m','6m','2m','2m','2m','1.25m','70cm','33cm','33cm','33cm','23cm'],
'Lat': ['35.5','34.2','35.9','36.1','35.2','36.2','33.9','36.4','35.1','34.9','32.9','35.0'],
'Lon': ['-78.5','-77.3','-79.0','-78.6','-79.3','-77.0','-78.5','-77.7','-79.9','-78.8','-79.1','-79.0']}
df = pd.DataFrame.from_dict(data)
此mapplot将需要其颜色与其他图表相对应,因此我想在文档阅读时使用category_order
...
默认情况下,在Python 3.6+中,轴,图例和构面中的分类值的顺序取决于在data_frame中首次遇到这些值的顺序(默认情况下,在3.6以下的Python中无法保证顺序)。此参数用于强制每列值的特定排序。该字典的键应与列名相对应,并且值应为与所需的特定显示顺序相对应的字符串列表。”
band_categories = {'band':['10m', '6m', '2m', '1.25m', '70cm', '33cm', '23cm']}
设置为建立希望散点图框使用的顺序。
最后,color_discrete_sequence
根据定义直接与category_order一起使用...
字符串应定义有效的CSS颜色。如果设置了color并且相应列中的值不是数字,则除非color的值是color_discrete_map中的键,否则将按照category_orders中描述的顺序循环通过color_discrete_sequence为该列中的值分配颜色。
它会收到我想要的颜色顺序band_colors_list = ['green', 'red', 'blue', 'orange', 'purple', 'gray', 'yellow']
最终的标记dict被编译并分配给scattermapbox dict,并推送到Dash元素。
import pandas as pd
import numpy as np
from pandas.api.types import CategoricalDtype
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
data = {'band':['10m','10m','6m','2m','2m','2m','1.25m','70cm','33cm','33cm','33cm','23cm'],
'Lat': ['35.5','34.2','35.9','36.1','35.2','36.2','33.9','36.4','35.1','34.9','32.9','35.0'],
'Lon': ['-78.5','-77.3','-79.0','-78.6','-79.3','-77.0','-78.5','-77.7','-79.9','-78.8','-79.1','-79.0']}
df = pd.DataFrame.from_dict(data)
df.head()
token = drop_mapbox_token_string_here
layers = []
band_categories = ['10m', '6m', '2m', '1.25m', '70cm', '33cm', '23cm']
band_colors_list = ['green', 'red', 'blue', 'orange', 'purple', 'gray', 'yellow']
app = dash.Dash(__name__)
template = {'layout': {'paper_bgcolor': "#f3f3f1", 'plot_bgcolor': "#f3f3f1"}}
def blank_fig(height):
"""
Build blank figure with the requested height
"""
return {
'data': [],
'layout': {
'height': height,
'template': template,
'xaxis': {'visible': False},
'yaxis': {'visible': False},
}
}
# Build Dash layout
app.layout = html.Div(children=[
html.Div(children=[
dcc.Graph(
id='map-graph',
figure=blank_fig(500),
config={'displayModeBar': False},
),],
id="map-div"
)
])
@app.callback(
Output('map-graph', 'figure'),
[Input('map-graph', 'relayoutData')])
def update_plots(relayout_data):
marker = {
'color': df.band,
'category_order': band_categories,
'color_discrete_sequence': band_colors_list,
'size': 5,
'opacity': 0.6
}
map_graph = {'data': [{
'type': 'scattermapbox',
'lat': df.Lat, 'lon': df.Lon,
'marker': marker
}],
'layout': {
'template': template,
'uirevision':True,
'mapbox':{
'style': "light",
'accesstoken': token,
'layers': layers,
},
'margin': {"r": 0, "t": 0, "l": 0, "b": 0},
'height': 500
},
}
map_graph['layout']['mapbox'].update()
return (map_graph)
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True
app.run_server(debug=True, use_reloader=False)
答案 0 :(得分:0)
解决了这个问题。
最终,我与Plotly Express中的组件和Plotly Graph Objects中的各种散布图组件混为一谈。 category_order
和discrete_color_sequence
驻留在Plotly Express散点图中,但不在Plotly Graph Object的Scattermapbox中。
尽管一种途径是转换为使用允许离散颜色定义的其他组件之一,但我还是采用了侵入性较小的方法。只需根据band
列定义一个具有预设颜色的新数据框列,然后将此列推入color
下的marker
参数中即可。
band_categories = ['10m', '6m', '2m', '1.25m', '70cm', '33cm', '23cm']
band_colors_list = ['green', 'red', 'blue', 'orange', 'purple', 'gray', 'yellow']
band_dict = dict(zip(band_categories,band_colors_list)) #set up band to color substitution dict
df['color'] = df['band'].replace(to_replace=band_colorscale)
及以后...
marker = {
'color': df.color,
'size': 5,
'opacity': 0.6
}
可以说,它不那么优雅且占用大量内存,因为我们为大型数据集存储了额外的属性,但它确实有效。