I want to build two pie subplots that takes as input the country, the sector and the year. And I want to see the proportions of job positions that mens have, and the proportions of job positions that women have.
我想构建两个饼子图,将国家、行业和年份作为输入。我想看看男性在工作岗位上所占的比例,以及女性在工作岗位上所占的比例。
(for example for man 'CEo'=23%, President=20%, Member=57%).
(例如,MAN‘CEO’=23%,总裁=20%,成员=57%)。
And in the same way the pie for womens
以同样的方式,给女人的馅饼
This is the code I have done till now
这就是我到目前为止所做的代码
app=dash.Dash(__name__, meta_tags=[{"name":"viewport","content":"width=device-width"}],
external_stylesheets=[dbc.themes.BOOTSTRAP])
df=pd.read_csv('report.csv')
#fill NAs with zeros
df=df.fillna(0)
#Create the list to show in dropdown element from a specific dataset column
country = df['geo'].unique()
country = country.tolist()
country.insert(0, 'Select all')
settore = df['NACE'].unique()
app.layout=html.Div([
html.Div([
html.H1(children='A gender analysis ',
style={'textAlign':'center'}),
html.P(children='A case study of the top company from 2011 al 2023',
style={'textAlign':'left', 'margin-left':'1%'})
], style={"margin-bottom": "3vw", 'margin-left':'1%', "border":"2px purple solid", 'background-color':'#FF69B4'}),
html.Div([
"Select the year:",
dcc.Slider(id='year-slider',
included=False,
updatemode='drag',
tooltip={'always_visible':True},
min=2011,
max=2023,
step=1,
dots=True,
value=2016,
marks={str(tm):str(tm) for tm in range(2011, 2023)},
className='dcc_compon'),
], style={"margin-bottom": "3vw", 'margin-left':'1%', "border":"2px purple solid", 'background-color':'lightblue'}),
html.Div([
html.Div([
#dropdown country
html.Div([
html.H4('Select the country:', className='fix_label',style={'color':'black'}),
dcc.Dropdown(id='country-selection',
multi=False,
clearable=True,
disabled=False,
style={'display':True, 'width':'330px', 'padding':'5px', 'color':'black', 'margin-bottom':'0.5vw'},
value='Select all',
placeholder='Select country',
options=[{'label': i, 'value': i} for i in country],
className='dcc_compon'),
], style={'display': 'inline-block', 'vertical-align': 'top', 'margin-left': '0.5vw', 'margin-top': '3vw'}),
html.Br(),
html.Div(id='country-output',
style={'margin-left':'0.5vw'}),
html.Br(),
#dropdown settore
html.Div([
html.H4('Which is the sector of interest?', className= 'fix_label', style={'color':'black'}),
dcc.Dropdown(id='settore-selection',
multi=False,
clearable=True,
disabled=False,
style={'display':True, 'width':'330px', 'padding':'5px', 'color':'black', 'margin-bottom':'0.5vw'},
placeholder='Select sector',
value='All sectors',
options=[{'label': z, 'value': z} for z in settore], className='dcc_compon'),
], style={'display': 'inline-block', 'vertical-align': 'top', 'margin-left': '0.5vw', 'margin-top': '3vw'}),
html.Br(),
html.Div(id='settore-output',
style={'margin-left':'0.5vw'}),
html.Br(),
], style={'background-color':'#FFF0F5','width': '30%', 'display':'inline-block', 'float':'left',"margin-bottom": "10px", 'margin-left':'1%', "border":"2px purple solid"}),
html.Div([
dcc.Graph(id='pie',
config={'displayModeBar':'hover'},
style={'width':'90%','display':'inline-block','float':'left','margin-left':'0.5%', 'margin-bottom':'1%'}),
], style={'width': '68%', 'display':'inline-block','float':'right',"margin-bottom": "10px", 'margin-left':'1%', "border":"2px purple solid"}),
])
], id="mainContainer", style={"display":"flex", "flex-direction":"column"})
@app.callback(Output('pie', 'figure'),
[Input('year-slider', 'value'),
Input('country-selection', 'value'),
Input('settore-selection', 'value')])
def update_graph(year_slider, country_selection, settore_selection):
m3=df.groupby(['time','geo', 'NACE', 'POSITION'])['sex'].count().reset_index(name='count')
if country_selection != 'Select all':
m3 = m3[m3['geo']==country_selection]
m3 = m3[m3['time'] == year_slider]
if settore_selection is not None and settore_selection in m3['NACE'].unique():
m3 = m3[m3['NACE']==settore_selection]
fig = make_subplots(rows=1, cols=2, specs=[[{'type':'pie'}, {'type':'pie'}]])
fig.add_trace(go.Pie( values=['count'],labels=m3['POSITION'],
domain=dict(x=[0, 0.5]), name='Men'),
1, 1)
fig.add_trace(go.Pie( values=['count'],labels=m3['POSITION'],
domain=dict(x=[0.5, 1.0]), name='Women'),
1, 2)
# Use `hole` to create a donut-like pie chart
fig.update_traces(hole=.4, hoverinfo="label+percent+name")
fig.update_layout(
title_text="How the positions are distributed in men and women?",
# Add annotations in the center of the donut pies.
annotations=[dict(text='Men', x=0.18, y=0.5, font_size=20, showarrow=False),
dict(text='Women', x=0.82, y=0.5, font_size=20, showarrow=False)])
return fig
The dash web does not give me any error, the title appears, also the annotations. But there is no graph.
破折号网站没有给我任何错误,标题和注释都会出现。但没有图表。
Part of my .csv file is like this:
我的.csv文件的一部分如下所示:
,time,_geo,geo,value,UNIT,_UNIT,EGROUP,_EGROUP,POSITION,_POSITION,sex,_sex,NACE,_NACE
1,2015,AT,Austria,2.0,Number of persons (headcount),NR,Largest listed companies,COMP,Employee representatives,EMP_REP,Women,W,"C, E & F (Mining & quarrying; electricity, gas and water; construction)",CEF
2,2015,AT,Austria,8.0,Number of persons (headcount),NR,Largest listed companies,COMP,Employee representatives,EMP_REP,Men,M,"C, E & F (Mining & quarrying; electricity, gas and water; construction)",CEF
3,2015,AT,Austria,0.0,Number of persons (headcount),NR,Largest listed companies,COMP,Executives,EXEC,Women,W,"C, E & F (Mining & quarrying; electricity, gas and water; construction)",CEF
4,2015,AT,Austria,2.0,Number of persons (headcount),NR,Largest listed companies,COMP,CEO (Chief Executive Officer),CEO,Men,M,"C, E & F (Mining & quarrying; electricity, gas and water; construction)",CEF
I have looked online but there are only examples where you single drop the values instead of the column. So presumably the problem may be there
我在网上看过,但只有一些例子表明,你只删除了值,而不是列。因此,问题可能就在那里
更多回答
can you also include the app.layout
from your code? this will make it easier for people to reproduce your dash app, thanks!
您还可以在代码中包含app.layout吗?这将使人们更容易复制您的Dash应用程序,谢谢!
There's a few problems in your callback function. Since you want headcount, after you filter by country, year, and settore, you should filter only rows where the field _UNIT = NR
because these represent absolute numbers of men and women in these positions, then groupby gender and position (we don't need to include country, year, or settore in the groupby because these are already accounted for in the selection), and then sum the values column.
您的回调函数中有一些问题。由于您需要人数,因此在按国家/地区、年份和Settore进行筛选后,您应该只筛选FIELD_UNIT=NR的行,因为这些行代表担任这些职位的男性和女性的绝对数,然后按性别和职位分组(我们不需要在Groupby中包括Country、Year或Settore,因为这些已经在所选内容中考虑在内),然后对Values列求和。
@app.callback(Output('pie', 'figure'),
[Input('year-slider', 'value'),
Input('country-selection', 'value'),
Input('settore-selection', 'value')])
def update_graph(year_slider, country_selection, settore_selection):
## to avoid modifying the original data
m3 = df.copy()
if country_selection != 'Select all':
m3 = m3[m3['geo']==country_selection]
m3 = m3[m3['time'] == year_slider]
if settore_selection is not None and settore_selection in m3['NACE'].unique():
m3 = m3[m3['NACE']==settore_selection]
## you want the headcount of people so use _UNIT == 'NR'
m3_grouped = m3[m3['_UNIT'] == 'NR'].groupby(['POSITION','sex'])['value'].sum().reset_index(name='count')
m3_grouped_men = m3_grouped[m3_grouped['sex'] == 'Men']
m3_grouped_women = m3_grouped[m3_grouped['sex'] == 'Women']
fig = make_subplots(rows=1, cols=2, specs=[[{'type':'pie'}, {'type':'pie'}]])
fig.add_trace(go.Pie( values=m3_grouped['count'],labels=m3_grouped_men['POSITION'],
domain=dict(x=[0, 0.5]), name='Men'),
1, 1)
fig.add_trace(go.Pie( values=m3_grouped_women['count'],labels=m3_grouped_women['POSITION'],
domain=dict(x=[0.5, 1.0]), name='Women'),
1, 2)
# Use `hole` to create a donut-like pie chart
fig.update_traces(hole=.4, hoverinfo="label+percent+name")
fig.update_layout(
title_text="How the positions are distributed in men and women?",
# Add annotations in the center of the donut pies.
annotations=[dict(text='Men', x=0.18, y=0.5, font_size=20, showarrow=False),
dict(text='Women', x=0.82, y=0.5, font_size=20, showarrow=False)])
return fig
Here is the full code and dash app:
以下是完整的代码和Dash应用程序:
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import dash_bootstrap_components as dbc
import dash
from dash import Input, Output, html, dcc
app=dash.Dash(__name__, meta_tags=[{"name":"viewport","content":"width=device-width"}],
external_stylesheets=[dbc.themes.BOOTSTRAP])
df=pd.read_csv('report.csv')
#fill NAs with zeros
df=df.fillna(0)
#Create the list to show in dropdown element from a specific dataset column
country = df['geo'].unique()
country = country.tolist()
country.insert(0, 'Select all')
settore = df['NACE'].unique()
app.layout=html.Div([
html.Div([
html.H1(children='A gender analysis ',
style={'textAlign':'center'}),
html.P(children='A case study of the top company from 2011 al 2023',
style={'textAlign':'left', 'margin-left':'1%'})
], style={"margin-bottom": "3vw", 'margin-left':'1%', "border":"2px purple solid", 'background-color':'#FF69B4'}),
html.Div([
"Select the year:",
dcc.Slider(id='year-slider',
included=False,
updatemode='drag',
tooltip={'always_visible':True},
min=2011,
max=2023,
step=1,
dots=True,
value=2016,
marks={str(tm):str(tm) for tm in range(2011, 2023)},
className='dcc_compon'),
], style={"margin-bottom": "3vw", 'margin-left':'1%', "border":"2px purple solid", 'background-color':'lightblue'}),
html.Div([
html.Div([
#dropdown country
html.Div([
html.H4('Select the country:', className='fix_label',style={'color':'black'}),
dcc.Dropdown(id='country-selection',
multi=False,
clearable=True,
disabled=False,
style={'display':True, 'width':'330px', 'padding':'5px', 'color':'black', 'margin-bottom':'0.5vw'},
value='Select all',
placeholder='Select country',
options=[{'label': i, 'value': i} for i in country],
className='dcc_compon'),
], style={'display': 'inline-block', 'vertical-align': 'top', 'margin-left': '0.5vw', 'margin-top': '3vw'}),
html.Br(),
html.Div(id='country-output',
style={'margin-left':'0.5vw'}),
html.Br(),
#dropdown settore
html.Div([
html.H4('Which is the sector of interest?', className= 'fix_label', style={'color':'black'}),
dcc.Dropdown(id='settore-selection',
multi=False,
clearable=True,
disabled=False,
style={'display':True, 'width':'330px', 'padding':'5px', 'color':'black', 'margin-bottom':'0.5vw'},
placeholder='Select sector',
value='All sectors',
options=[{'label': z, 'value': z} for z in settore], className='dcc_compon'),
], style={'display': 'inline-block', 'vertical-align': 'top', 'margin-left': '0.5vw', 'margin-top': '3vw'}),
html.Br(),
html.Div(id='settore-output',
style={'margin-left':'0.5vw'}),
html.Br(),
], style={'background-color':'#FFF0F5','width': '30%', 'display':'inline-block', 'float':'left',"margin-bottom": "10px", 'margin-left':'1%', "border":"2px purple solid"}),
html.Div([
dcc.Graph(id='pie',
config={'displayModeBar':'hover'},
style={'width':'90%','display':'inline-block','float':'left','margin-left':'0.5%', 'margin-bottom':'1%'}),
], style={'width': '68%', 'display':'inline-block','float':'right',"margin-bottom": "10px", 'margin-left':'1%', "border":"2px purple solid"}),
])
], id="mainContainer", style={"display":"flex", "flex-direction":"column"})
@app.callback(Output('pie', 'figure'),
[Input('year-slider', 'value'),
Input('country-selection', 'value'),
Input('settore-selection', 'value')])
def update_graph(year_slider, country_selection, settore_selection):
## to avoid modifying the original data
m3 = df.copy()
if country_selection != 'Select all':
m3 = m3[m3['geo']==country_selection]
m3 = m3[m3['time'] == year_slider]
if settore_selection is not None and settore_selection in m3['NACE'].unique():
m3 = m3[m3['NACE']==settore_selection]
## you want the headcount of people so use _UNIT == 'NR'
m3_grouped = m3[m3['_UNIT'] == 'NR'].groupby(['POSITION','sex'])['value'].sum().reset_index(name='count')
m3_grouped_men = m3_grouped[m3_grouped['sex'] == 'Men']
m3_grouped_women = m3_grouped[m3_grouped['sex'] == 'Women']
fig = make_subplots(rows=1, cols=2, specs=[[{'type':'pie'}, {'type':'pie'}]])
fig.add_trace(go.Pie( values=m3_grouped['count'],labels=m3_grouped_men['POSITION'],
domain=dict(x=[0, 0.5]), name='Men'),
1, 1)
fig.add_trace(go.Pie( values=m3_grouped_women['count'],labels=m3_grouped_women['POSITION'],
domain=dict(x=[0.5, 1.0]), name='Women'),
1, 2)
# Use `hole` to create a donut-like pie chart
fig.update_traces(hole=.4, hoverinfo="label+percent+name")
fig.update_layout(
title_text="How the positions are distributed in men and women?",
# Add annotations in the center of the donut pies.
annotations=[dict(text='Men', x=0.18, y=0.5, font_size=20, showarrow=False),
dict(text='Women', x=0.82, y=0.5, font_size=20, showarrow=False)])
return fig
if __name__ == '__main__':
app.run_server(debug=True, port=4000)
更多回答
@user22300466 it looks like you're not including sex
in the groupby, and you're passing the same data to both pie charts. i've rewritten your callback function and have updated my answer using sample data
@user22300466看起来您没有将性别包括在Groupby中,并且您正在将相同的数据传递给两个饼图。我已经重写了您的回调函数,并使用示例数据更新了我的答案
If you have a link to the actual data set you’re using, I’d be happy to take a look
如果你有一个链接到你正在使用的实际数据集,我很乐意看一看
@user22300466 I've updated my answer – i'm modifying the groupby in your callback function to sum up the values column instead of using count
@user22300466我已经更新了我的答案--我正在修改回调函数中的groupby,以求和值列,而不是使用count
我是一名优秀的程序员,十分优秀!