Пример #1
0
 def piece(i):
     return (base.mark_bar().encode(
         x=alt.X(cols[i], title=None, sort=alt.SortOrder(directions[i])),
         y=alt.Y("index",
                 axis=None,
                 title=None,
                 sort=alt.SortOrder("descending")),
         tooltip=alt.Tooltip([h_cols[i]]),
         color=alt.Color(f"color_{cols[i]}:N", legend=None),
     ).properties(title=titles[i], width=width,
                  height=height).interactive())
Пример #2
0
def chart(disks, tower):

    num_disks = len(disks)

    width = np.zeros(10)

    for i in range(1, num_disks + 1, 1):
        width[-i] = disks[i - 1]

    source = pd.DataFrame({'y': np.arange(10), 'x': width})

    left = alt.Chart(source).encode(
        y=alt.Y('y:O', axis=None),
        x=alt.X('x:Q',
                axis=None,
                scale=alt.Scale(domain=(0, 10)),
                sort=alt.SortOrder('descending')),
    ).mark_bar().properties(width=100, height=150)

    right = alt.Chart(source).encode(
        y=alt.Y('y:O', axis=None),
        x=alt.X('x:Q', axis=None, scale=alt.Scale(domain=(0, 10))),
    ).mark_bar().properties(width=100, height=150)

    return alt.concat(left, right,
                      spacing=5).properties(title=tower + " Tower")
Пример #3
0
def suicides_gender(source):
    group1 = source
    click = alt.selection_multi()
    alt.data_transformers.disable_max_rows()
    color_scale = alt.Scale(domain=['male', 'female'],
                            range=['#5389b8', '#c87e35'])

    left = (alt.Chart(group1).transform_filter((datum.sex == 'female')).encode(
        y=alt.Y('country', axis=None),
        x=alt.X('Average_suicides_per_capita',
                title='Average_suicides_per_capita',
                sort=alt.SortOrder('descending'),
                axis=alt.Axis(orient='top'),
                scale=alt.Scale(domain=(0, 70))),
        color=alt.Color('sex:N', scale=color_scale, legend=None),
        opacity=alt.condition(click, alt.value(1.0), alt.value(0.5)),
        tooltip=[
            alt.Tooltip('country:N'),
            alt.Tooltip('Average_suicides_per_capita:Q')
        ],
    ).mark_bar().properties(title='Female').add_selection(click))

    middle = alt.Chart(group1).encode(
        y=alt.Y('country', axis=None),
        text=alt.Text('country'),
    ).mark_text(color='white').properties(width=150)

    right = (alt.Chart(group1).transform_filter((datum.sex == 'male')).encode(
        y=alt.Y('country', axis=None),
        x=alt.X('Average_suicides_per_capita',
                title='Average_suicides_per_capita',
                axis=alt.Axis(orient='top'),
                scale=alt.Scale(domain=(0, 70))),
        color=alt.Color('sex:N', scale=color_scale, legend=None),
        opacity=alt.condition(click, alt.value(1.0), alt.value(0.5)),
        tooltip=[
            alt.Tooltip('country:N'),
            alt.Tooltip('Average_suicides_per_capita:Q'),
            alt.Tooltip('sex')
        ],
    ).mark_bar().properties(title='Male').add_selection(click))

    chartf = alt.concat(left, middle, right,
                        spacing=4).configure_axis(grid=False)
    return chartf.to_html()
Пример #4
0
def display_the_conplot():

    slider = alt.binding_range(min=2006, max=2013, step=1)
    select_year = alt.selection_single(name='Select',
                                       fields=['Year'],
                                       bind=slider,
                                       init={'Year': 2006})

    base = alt.Chart(tidy_df).add_selection(select_year).transform_filter(
        select_year).transform_calculate(types=alt.expr.if_(
            alt.datum.Half == 1.0, '1st Half', '2nd Half')).properties(
                width=250, )

    color_scale = alt.Scale(domain=['1st Half', '2nd Half'],
                            range=['green', 'orange'])

    left = base.transform_filter(alt.datum.types == '1st Half').encode(
        y=alt.Y('County Councils:O', axis=None),
        x=alt.X('sum(esb):Q',
                title='ESB Count',
                sort=alt.SortOrder('descending')),
        color=alt.Color('types:N', scale=color_scale, legend=None),
        tooltip=('sum(esb):Q')).mark_bar().properties(
            title='First Half of Year')

    middle = base.encode(
        y=alt.Y('County Councils:O', axis=None),
        text=alt.Text('County Councils:O'),
    ).mark_text(color='steelblue', size=15).properties(width=105)

    right = base.transform_filter(alt.datum.types == '2nd Half').encode(
        y=alt.Y('County Councils:O', axis=None),
        x=alt.X('sum(esb):Q', title='ESB Count'),
        color=alt.Color('types:N', scale=color_scale, legend=None),
        tooltip=('sum(esb):Q')).mark_bar().properties(
            title='Second Half of Year')

    conplot = alt.concat(left, middle, right, spacing=5)

    conplot.save("templates/conplot.html")

    return render_template("conplot.html")
Пример #5
0
def write():

    data = funcs.get_data()
    data = funcs.convertTimes(data)
    data['Country Name'] = data['Country'].apply(funcs.getCountryName)

    data = funcs.removeNotFinished(data)

    ##
    ##  Gráfico
    ##

    athletes = data['Name'].unique()

    option1 = st.sidebar.selectbox('Buscar atleta pelo nome:', sorted(athletes) )
    atleta1 = data.loc[data['Name'] == option1].drop(['Country'], axis=1)

    option2 = st.sidebar.selectbox('Segundo atleta:', sorted(athletes) )
    atleta2 = data.loc[data['Name'] == option2].drop(['Country'], axis=1)

    df = pd.DataFrame([
        {'val':'1', 'Order':1, 'name': funcs.getValueUniq(atleta1, 'Name'), 'Tempo': funcs.getValueUniq(atleta1, 'Swim'), 'TempoN': funcs.getValueUniq(atleta1, 'SwimN'), 'Atividade':'Swim'},
        {'val':'2', 'Order':1, 'name': funcs.getValueUniq(atleta2, 'Name'), 'Tempo': funcs.getValueUniq(atleta2, 'Swim'), 'TempoN': funcs.getValueUniq(atleta2, 'SwimN'), 'Atividade':'Swim'},
        {'val':'1', 'Order':2, 'name': funcs.getValueUniq(atleta1, 'Name'), 'Tempo': funcs.getValueUniq(atleta1, 'T1'), 'TempoN': funcs.getValueUniq(atleta1, 'T1N'), 'Atividade':'T1'},
        {'val':'2', 'Order':2, 'name': funcs.getValueUniq(atleta2, 'Name'), 'Tempo': funcs.getValueUniq(atleta2, 'T1'), 'TempoN': funcs.getValueUniq(atleta2, 'T1N'), 'Atividade':'T1'},
        {'val':'1', 'Order':3, 'name': funcs.getValueUniq(atleta1, 'Name'), 'Tempo': funcs.getValueUniq(atleta1, 'Bike'), 'TempoN': funcs.getValueUniq(atleta1, 'BikeN'), 'Atividade':'Bike'},
        {'val':'2', 'Order':3, 'name': funcs.getValueUniq(atleta2, 'Name'), 'Tempo': funcs.getValueUniq(atleta2, 'Bike'), 'TempoN': funcs.getValueUniq(atleta2, 'BikeN'), 'Atividade':'Bike'},
        {'val':'1', 'Order':4, 'name': funcs.getValueUniq(atleta1, 'Name'), 'Tempo': funcs.getValueUniq(atleta1, 'T2'), 'TempoN': funcs.getValueUniq(atleta1, 'T2N'), 'Atividade':'T2'},
        {'val':'2', 'Order':4, 'name': funcs.getValueUniq(atleta2, 'Name'), 'Tempo': funcs.getValueUniq(atleta2, 'T2'), 'TempoN': funcs.getValueUniq(atleta2, 'T2N'), 'Atividade':'T2'},
        {'val':'1', 'Order':5, 'name': funcs.getValueUniq(atleta1, 'Name'), 'Tempo': funcs.getValueUniq(atleta1, 'Run'), 'TempoN': funcs.getValueUniq(atleta1, 'RunN'), 'Atividade':'Run'},
        {'val':'2', 'Order':5, 'name': funcs.getValueUniq(atleta2, 'Name'), 'Tempo': funcs.getValueUniq(atleta2, 'Run'), 'TempoN': funcs.getValueUniq(atleta2, 'RunN'), 'Atividade':'Run'}
    ])

    base = alt.Chart(df).properties( width=400 )

    color_scale = alt.Scale(domain=[option1, option2], range=['#1f77b4', '#1f77b4'])


    left = base.transform_filter(
        alt.datum.val == '1'
    ).encode(
        y=alt.Y('Atividade:N', axis=None, sort=alt.EncodingSortField(field="Order", order='ascending')),
        x=alt.X('sum(TempoN):Q', title='Tempo', sort=alt.SortOrder('descending')),
        color=alt.Color('name:N', scale=color_scale, legend=None),
        tooltip=['Tempo:N'],
        order=alt.Order(
            'Order',
            sort='ascending'
        )
    ).mark_bar().properties(title=option1)


    middle = base.encode(
        y=alt.Y('Atividade:N', axis=None, sort=alt.EncodingSortField(field="Order", order='ascending')),
        text=alt.Text('Atividade:N'),
        order=alt.Order(
            'Order',
            sort='ascending'
        )
    ).mark_text().properties(width=40)

    right = base.transform_filter(
        alt.datum.val == '2'
    ).encode(
        y=alt.Y('Atividade:N', axis=None, sort=alt.EncodingSortField(field="Order", order='ascending')),
        x=alt.X('sum(TempoN):Q', title='Tempo'),
        color=alt.Color('name:N', scale=color_scale, legend=None),
        tooltip=['Tempo:N']
    ).mark_bar().properties(title=option2)

    st.altair_chart( alt.concat(left, middle, right, spacing=5) )

    ##
    ##  Tabela
    ##

    df1 = pd.DataFrame([
        {'Atividade':'Swim', 'Tempo': funcs.getValueUniq(atleta1, 'Swim')},
        {'Atividade':'T1', 'Tempo': funcs.getValueUniq(atleta1, 'T1')},
        {'Atividade':'Bike', 'Tempo': funcs.getValueUniq(atleta1, 'Bike')},
        {'Atividade':'T2', 'Tempo': funcs.getValueUniq(atleta1, 'T2')},
        {'Atividade':'Run', 'Tempo': funcs.getValueUniq(atleta1, 'Run')},
        {'Atividade':'Total', 'Tempo': funcs.getValueUniq(atleta1, 'Overall')}
    ])

    df2 = pd.DataFrame([
        {'Atividade':'Swim', 'Tempo': funcs.getValueUniq(atleta2, 'Swim')},
        {'Atividade':'T1', 'Tempo': funcs.getValueUniq(atleta2, 'T1')},
        {'Atividade':'Bike', 'Tempo': funcs.getValueUniq(atleta2, 'Bike')},
        {'Atividade':'T2', 'Tempo': funcs.getValueUniq(atleta2, 'T2')},
        {'Atividade':'Run', 'Tempo': funcs.getValueUniq(atleta2, 'Run')},
        {'Atividade':'Total', 'Tempo': funcs.getValueUniq(atleta2, 'Overall')}
    ])

    with Grid("1 1", color="#000000", background_color="#FFFFFF") as grid:
        grid.cell("a", 1, 2, 1, 2).dataframe( df1.set_index('Atividade', inplace=False) )
        grid.cell("b", 2, 3, 1, 2).dataframe( df2.set_index('Atividade', inplace=False) )


    # st.write(funcs.secondsToTime( funcs.getValueUniq(atleta2, 'RunN') ))
Пример #6
0
pop = data.population.url

slider = alt.binding_range(min=1850, max=2000, step=10)
select_year = alt.selection_single(name='year', fields=['year'], bind=slider)

base = alt.Chart(pop).add_selection(select_year).transform_filter(
    select_year).transform_calculate(
        gender=if_(datum.sex == 1, 'Male', 'Female'))

title = alt.Axis(title='population')
color_scale = alt.Scale(domain=['Male', 'Female'],
                        range=['#1f77b4', '#e377c2'])

left = base.transform_filter(datum.gender == 'Female').encode(
    y=alt.X('age:O', axis=None),
    x=alt.X('sum(people):Q', axis=title, sort=alt.SortOrder('descending')),
    color=alt.Color('gender:N', scale=color_scale,
                    legend=None)).mark_bar().properties(title='Female')

middle = base.encode(
    y=alt.X('age:O', axis=None),
    text=alt.Text('age:Q'),
).mark_text().properties(width=20)

right = base.transform_filter(datum.gender == 'Male').encode(
    y=alt.X('age:O', axis=None),
    x=alt.X('sum(people):Q', axis=title),
    color=alt.Color('gender:N', scale=color_scale,
                    legend=None)).mark_bar().properties(title='Male')

left | middle | right
slider = alt.binding_range(min=1850, max=2000, step=10)
select_year = alt.selection_single(name='year', fields=['year'], bind=slider)

base = alt.Chart(source).add_selection(select_year).transform_filter(
    select_year).transform_calculate(
        gender=alt.expr.if_(alt.datum.sex == 1, 'Male', 'Female'))

color_scale = alt.Scale(domain=['Male', 'Female'],
                        range=['#1f77b4', '#e377c2'])

left = base.transform_filter(alt.datum.gender == 'Female').encode(
    y=alt.Y('age:O', axis=None),
    x=alt.X('sum(people):Q',
            title='population',
            sort=alt.SortOrder('descending')),
    color=alt.Color('gender:N', scale=color_scale,
                    legend=None)).mark_bar().properties(title='Female')

middle = base.encode(
    y=alt.Y('age:O', axis=None),
    text=alt.Text('age:Q'),
).mark_text().properties(width=20)

right = base.transform_filter(alt.datum.gender == 'Male').encode(
    y=alt.Y('age:O', axis=None),
    x=alt.X('sum(people):Q', title='population'),
    color=alt.Color('gender:N', scale=color_scale,
                    legend=None)).mark_bar().properties(title='Male')

left | middle | right
Пример #8
0
def pyramid_chart(data,
                  left="left",
                  right="right",
                  hleft=fmt,
                  hright=fmt,
                  where=None):
    """
    A Population pyramid chart.

    Args:
        data:
            Input dataframe with ["left", "right"] columns.
        left:
            Name of the column that will be displayed to the left.
        right:
            Name of the column that will be displayed to the right.
        hleft:
            Humanized left column or function.
        hright:
            Humanized right column or function.
    """
    cols = ["left", "right"]
    titles = [left, right]
    directions = ["descending", "ascending"]
    h_cols = [left, right]

    # Transform datasets
    data = data.copy()
    data["index"] = [str(x) for x in data.index]
    data["color_left"] = "A"
    data["color_right"] = "B"

    if callable(hleft):
        data[h_cols[0]] = data["left"].apply(hleft)
    else:
        data[h_cols[0]] = hleft

    if callable(hright):
        data[h_cols[1]] = data["right"].apply(hright)
    else:
        data[h_cols[1]] = hright
    data = data.loc[::-1]

    # Chart
    base = alt.Chart(data)
    height = 250
    width = 300

    def piece(i):
        return (base.mark_bar().encode(
            x=alt.X(cols[i], title=None, sort=alt.SortOrder(directions[i])),
            y=alt.Y("index",
                    axis=None,
                    title=None,
                    sort=alt.SortOrder("descending")),
            tooltip=alt.Tooltip([h_cols[i]]),
            color=alt.Color(f"color_{cols[i]}:N", legend=None),
        ).properties(title=titles[i], width=width,
                     height=height).interactive())

    where.altair_chart(
        alt.concat(
            piece(0),
            base.encode(
                y=alt.Y("index", axis=None, sort=alt.SortOrder("descending")),
                text=alt.Text("index"),
            ).mark_text().properties(width=50, height=height),
            piece(1),
            spacing=5,
        ),
        use_container_width=False,
    )
Пример #9
0
def run_popu_dist():
    @st.cache
    def get_total_ymax(country_df, health_df):
        # fixing y range for better visualizing the change
        maxy = 0.0
        for col in country_df.columns:
            if '% of' in col and 'Population ages' in col:
                curr_max = health_df[col].max()
                if curr_max > maxy:
                    maxy = curr_max
        return maxy

    @st.cache
    def get_only_tens(country_df):
        years = list(np.sort(country_df['Year'].unique()))
        # get selection interval
        interval = math.floor(len(years) / 5)
        if interval == 0:
            only_ten = country_df
        else:
            temp = []
            idx = len(years) - 1
            count = 0
            while idx > 0 and count < 5:
                temp.append(years[idx])
                idx -= interval
                count += 1
            only_ten = country_df[country_df['Year'].isin(temp)]
        return only_ten

    @st.cache
    def get_only_ten_general(country_df, age_ranges):
        only_ten = get_only_tens(country_df)
        values2 = []
        years2 = []
        indexes = []
        ages = []
        for _, data_row in only_ten.iterrows():
            for i in range(len(age_ranges)):
                values2.append(
                    data_row['Population ages {} (% of total population)'.
                             format(str(age_ranges[i]))] *
                    data_row['Population, total'])
                years2.append(data_row['Year'])
                indexes.append(i)
                ages.append(age_ranges[i])
        overall_data = pd.DataFrame({
            'Idx': indexes,
            'Population Ages': ages,
            'Year': years2,
            'Population': values2
        })
        return overall_data

    st.markdown('''
		## Health through the lens of population age distribution

		In this section, we will look at population age distribution of a specific country. 
		Though this data might be affected by other factors like wars/regional conflicts, and willingness to birth,
		it is still a good indicator of population health and health service quality in a country.

		We have observed a general demographic shift in the past few decades, where the percentage of young dependents drops,
		and mid-ages increase [1]. Since world population has also been skyrocketting [2] and fertility rate dropping [3] in the same time frame, 
		the changes in the population distribution would suggest that population increases usually for all age groups, 
		and population with mid to old ages has the steepest upward trend. We are now having less 
		mortalities from some health threats like infectious and parasitic diseases which haunted the world in the past; 
		mortality rate also decreases for major diseases [3].

		The changes in the population age distribution, where mid-to-old age population has a smaller
		gap with young population, suggest that we are having a healthier population [1].

		## Let's look at the data

		You are free to adjust the parameters in the left side bar now,
		but we will also walk you through these options through the explanations below.

		You can select a country from **drop down menu** in the side bar. 

	''')

    # load health data
    health_df, countries = load_health_data()
    health_grouped = data_group_by_country(health_df)

    st.sidebar.header("Adjust Parameters")

    country = st.sidebar.selectbox("Country", countries)
    country_df = health_grouped[country]

    max_year = country_df['Year'].max().item()
    year = st.sidebar.select_slider("Year",
                                    options=list(
                                        np.sort(country_df['Year'].unique())),
                                    value=max_year)
    by_gender = st.sidebar.checkbox('View By Gender', value=False)

    # # plot based on the country, hack for not displaying the column index
    # st.dataframe(country_df.assign(hack='').set_index('hack'))

    # plot the histogram base on country and year
    row = country_df.loc[country_df['Year'] == year]

    percentage_max = get_total_ymax(country_df, health_df)
    age_ranges_overall = [
        '0-14', '15-19', '20-24', '25-29', '30-34', '35-39', '40-44', '45-49',
        '50-54', '55-59', '60-64', '65-69', '70-74', '75-79', '80 and above'
    ]
    values_overall = []
    for r in age_ranges_overall:
        values_overall.append(
            row['Population ages {} (% of total population)'.format(r)].item())
    curr_data_overall = pd.DataFrame({
        'Population Ages': age_ranges_overall,
        '% of Total Population': values_overall
    })

    # the layered area graph
    only_ten = get_only_ten_general(country_df, age_ranges_overall)
    # highlight selector
    keep_one = alt.selection_single(fields=['Year'],
                                    bind='legend',
                                    nearest=False,
                                    empty='all')

    area_graph = alt.Chart(only_ten).mark_area(opacity=0.4).encode(
        x=alt.X('Idx',
                title=None,
                axis=alt.Axis(ticks=True, grid=True, labels=False)),
        y=alt.Y('Population', stack=None),
        color=alt.Color("Year:N", scale=alt.Scale(scheme='lightmulti')),
        opacity=alt.condition(keep_one, alt.value(0.4),
                              alt.value(0))).add_selection(keep_one)

    xaxis = alt.Chart(only_ten).mark_point().encode(
        x=alt.X('Population Ages', axis=alt.Axis(ticks=False, grid=False)),
        opacity=alt.value(0),
    )

    st.altair_chart(alt.layer(xaxis, area_graph), use_container_width=True)

    st.markdown('''
		The above graph visualizes the population age distribution of your selected country. 
		The x-axis represents the age groups, in the order of increasing age;
		the y-axis represents the number of people in this age group.

		To see the general demographic changes of your selected country over years with ease,
		the graph only shows data from 5 separate years, chosen with a nearly fixed interval. 

		You can click on the legend to see area plot from a specific year. 
		Clicking on other parts of the graph will reset the selection and show graphs of all five years.
		



		For the specific country you have just selected, you can also choose to look at a specific year
		by sliding the **slider** on the side bar. You will have more options to choose from, other than the 
		5 sample years on the area graph.
	''')

    # get median
    median = curr_data_overall['% of Total Population'].sum() / 2.0
    p_agg = 0.0
    for _, data_row in curr_data_overall.iterrows():
        prev_p_agg = p_agg
        p_agg += data_row['% of Total Population']
        if p_agg >= median:
            median_age_range = data_row['Population Ages']
            break

    # highlight selector
    highlight = alt.selection_single(on='mouseover',
                                     fields=['Population Ages'],
                                     nearest=False,
                                     clear="mouseout")

    hist = alt.Chart(curr_data_overall).mark_bar().encode(
        y=alt.Y('% of Total Population',
                scale=alt.Scale(domain=(0, percentage_max))),
        x='Population Ages',
        color=alt.condition(
            ~highlight,
            alt.Color('Population Ages:O',
                      scale=alt.Scale(scheme='greens'),
                      legend=None),
            alt.value('orange'),  # which sets the bar orange.
        ),
        tooltip=['Population Ages', '% of Total Population'
                 ]).add_selection(highlight).interactive()

    hist_background = alt.Chart(curr_data_overall).mark_bar().encode(
        y=alt.Y('background_height:Q',
                scale=alt.Scale(domain=(0, percentage_max)),
                title='% of Total Population'),
        x=alt.X('Population Ages'),
        color=alt.condition(alt.datum['Population Ages'] == median_age_range,
                            alt.value('lightgray'), alt.value('white')),
        opacity=alt.condition(alt.datum['Population Ages'] == median_age_range,
                              alt.value(0.2), alt.value(0.0)),
    ).transform_calculate(background_height="100")

    text = alt.Chart(curr_data_overall).mark_text(
        align='left', baseline='middle', dy=-10,
        dx=-15).encode(y=alt.Y('% of Total Population'),
                       x='Population Ages',
                       text=alt.condition(
                           alt.datum['Population Ages'] == median_age_range,
                           alt.value('median'), alt.value(' ')))
    st.altair_chart(alt.layer(hist_background, hist, text),
                    use_container_width=True)

    st.markdown('''
		This is a bar chart displaying the detailed population distribution of your selected country in one specific year.
		Same as the previous graph, the x-axis shows the population age group, and the y-axis show the percentage.
		The y-axis upper limit is the max age group percentage of this country. By fixing the scale of y-axis, 
		we are hoping that you can more clearly see the percentages' change over time as you are sliding the time
		slider.

		If the median age falls in an age group, the corresponding bar will have a darker background and the word 'median' 
		on top. The median may help you get a better concept of the overall distribution, as this graph can be highly screwed
		towards the origin.

		By moving your mouse over a bar, you will see the exact percentage of this age group in the total population. 
		This bar will also be highlighted orange. You can zoom and rescale the chart with two fingers; drag and hold 
		on the graph canvas will shift the plotting area. Double clicking on the graph will reset the graph.

		You can view population distribution of the selected year of this country by gender. By checking the
		'View by Gender' **checkbox** on the side bar, you can view the population distribution pyramid graph.
	''')

    if by_gender:
        age_ranges = [
            '80 and above', '75-79', '70-74', '65-69', '60-64', '55-59',
            '50-54', '45-49', '40-44', '35-39', '30-34', '25-29', '20-24',
            '15-19'
        ]
        male_values = []
        female_values = []
        for r in age_ranges:
            male_values.append(
                row['Population ages {}, male (% of male population)'.format(
                    r)].item())
            female_values.append(
                row['Population ages {}, female (% of female population)'.
                    format(r)].item())
        curr_data = pd.DataFrame({
            'Population ages': age_ranges,
            '% of Male Population': male_values,
            '% of Female Population': female_values
        })

        # write current data
        #st.dataframe(curr_data.iloc[::-1].assign(hack='').set_index('hack'))

        maxx = curr_data['% of Male Population'].max()
        if curr_data['% of Female Population'].max().item() > maxx:
            maxx = curr_data['% of Female Population'].max()

        base2 = alt.Chart(curr_data).properties(width=300)
        # highlight selector
        highlight2 = alt.selection_single(on='mouseover',
                                          fields=['Population ages'],
                                          nearest=False,
                                          clear="mouseout")

        left = base2.encode(
            y=alt.Y('Population ages:O',
                    axis=None,
                    sort=alt.EncodingSortField(order='ascending')),
            x=alt.X('% of Female Population',
                    title='% of Female Population',
                    sort=alt.SortOrder('descending'),
                    scale=alt.Scale(domain=(0, maxx))),
            color=alt.condition(
                ~highlight2,
                alt.Color('Population ages:O',
                          scale=alt.Scale(scheme='redpurple'),
                          legend=None),
                alt.value('orange'),  # which sets the bar orange.
            ),
            tooltip=[
                'Population ages', '% of Female Population'
            ]).mark_bar().properties(title='Female').add_selection(highlight2)

        middle = base2.encode(
            y=alt.Y('Population ages:O',
                    axis=None,
                    sort=alt.EncodingSortField(order='ascending')),
            text=alt.Text('Population ages'),
        ).mark_text().properties(width=40)

        right = base2.encode(
            y=alt.Y('Population ages:O',
                    axis=None,
                    sort=alt.EncodingSortField(order='ascending')),
            x=alt.X('% of Male Population',
                    title='% of Male Population',
                    sort=alt.SortOrder('ascending'),
                    scale=alt.Scale(domain=(0, maxx))),
            color=alt.condition(
                ~highlight2,
                alt.Color('Population ages:O',
                          scale=alt.Scale(scheme='blues'),
                          legend=None),
                alt.value('orange'),  # which sets the bar orange.
            ),
            tooltip=[
                'Population ages', '% of Male Population'
            ]).mark_bar().properties(title='Male').add_selection(highlight2)

        bihist = alt.concat(left, middle, right,
                            spacing=2).resolve_scale(color='independent')
        st.altair_chart(bihist, use_container_width=True)

        st.markdown('''
			This is a classic age structure pyramid graph. The left side of the graph is the age population 
			distribution of female in the selected year of this country. By moving your mouse over a bar, 
			you will see the exact percentage of this age group in its gender population. 
			This bar and the bar of the same age group from the other gender will also be highlighted orange.
		''')

    st.markdown('''
		
		### References
		[1]
		Hannah Ritchie (2019) - "Age Structure". 
		Published online at OurWorldInData.org. 
		Retrieved from: 'https://ourworldindata.org/age-structure' [Online Resource]

		[2]
		Max Roser, Hannah Ritchie and Esteban Ortiz-Ospina (2013) - "World Population Growth". 
		Published online at OurWorldInData.org. 
		Retrieved from: 'https://ourworldindata.org/world-population-growth' [Online Resource]

		[3]
		Global Health and Aging [PDF]. (2011, October). The World Health Organization.
	''')