How to create a nested Grouped Bar Chart using Altair? - Added sample data

不打扰是莪最后的温柔 提交于 2019-12-02 17:53:12

问题


<table class="table table-bordered table-hover table-condensed">
<thead><tr><th title="Field #1">year</th>
<th title="Field #2">primary_type</th>
<th title="Field #3">Number_of_Incidents</th>
<th title="Field #4">number_of_arrests</th>
<th title="Field #5">percent_arrest</th>
<th title="Field #6">rank</th>
</tr></thead>
<tbody><tr>
<td align="right">2018</td>
<td>THEFT</td>
<td align="right">57330</td>
<td align="right">5503</td>
<td align="right">9.6</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2018</td>
<td>BATTERY</td>
<td align="right">44667</td>
<td align="right">8886</td>
<td align="right">19.89</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2018</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">24889</td>
<td align="right">1498</td>
<td align="right">6.02</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2018</td>
<td>ASSAULT</td>
<td align="right">18229</td>
<td align="right">2931</td>
<td align="right">16.08</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2018</td>
<td>DECEPTIVE PRACTICE</td>
<td align="right">15879</td>
<td align="right">713</td>
<td align="right">4.49</td>
<td align="right">5</td>
</tr>
<tr>
<td align="right">2017</td>
<td>THEFT</td>
<td align="right">64334</td>
<td align="right">6459</td>
<td align="right">10.04</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2017</td>
<td>BATTERY</td>
<td align="right">49213</td>
<td align="right">10060</td>
<td align="right">20.44</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2017</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">29040</td>
<td align="right">1747</td>
<td align="right">6.02</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2017</td>
<td>ASSAULT</td>
<td align="right">19298</td>
<td align="right">3455</td>
<td align="right">17.9</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2017</td>
<td>DECEPTIVE PRACTICE</td>
<td align="right">18816</td>
<td align="right">805</td>
<td align="right">4.28</td>
<td align="right">5</td>
</tr>
<tr>
<td align="right">2016</td>
<td>THEFT</td>
<td align="right">61600</td>
<td align="right">6518</td>
<td align="right">10.58</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2016</td>
<td>BATTERY</td>
<td align="right">50292</td>
<td align="right">10328</td>
<td align="right">20.54</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2016</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">31018</td>
<td align="right">1668</td>
<td align="right">5.38</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2016</td>
<td>ASSAULT</td>
<td align="right">18738</td>
<td align="right">3490</td>
<td align="right">18.63</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2016</td>
<td>DECEPTIVE PRACTICE</td>
<td align="right">18733</td>
<td align="right">815</td>
<td align="right">4.35</td>
<td align="right">5</td>
</tr>
<tr>
<td align="right">2015</td>
<td>THEFT</td>
<td align="right">57335</td>
<td align="right">6771</td>
<td align="right">11.81</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2015</td>
<td>BATTERY</td>
<td align="right">48918</td>
<td align="right">11558</td>
<td align="right">23.63</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2015</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">28675</td>
<td align="right">1835</td>
<td align="right">6.4</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2015</td>
<td>NARCOTICS</td>
<td align="right">23883</td>
<td align="right">23875</td>
<td align="right">99.97</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2015</td>
<td>OTHER OFFENSE</td>
<td align="right">17552</td>
<td align="right">4795</td>
<td align="right">27.32</td>
<td align="right">5</td>
</tr>
<tr>
<td align="right">2014</td>
<td>THEFT</td>
<td align="right">61561</td>
<td align="right">7415</td>
<td align="right">12.04</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2014</td>
<td>BATTERY</td>
<td align="right">49447</td>
<td align="right">12517</td>
<td align="right">25.31</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2014</td>
<td>NARCOTICS</td>
<td align="right">29116</td>
<td align="right">29000</td>
<td align="right">99.6</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2014</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">27798</td>
<td align="right">2095</td>
<td align="right">7.54</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2014</td>
<td>OTHER OFFENSE</td>
<td align="right">16979</td>
<td align="right">4159</td>
<td align="right">24.49</td>
<td align="right">5</td>
</tr>
<tr>
<td align="right">2013</td>
<td>THEFT</td>
<td align="right">71530</td>
<td align="right">7727</td>
<td align="right">10.8</td>
<td align="right">1</td>
</tr>
<tr>
<td align="right">2013</td>
<td>BATTERY</td>
<td align="right">54002</td>
<td align="right">12927</td>
<td align="right">23.94</td>
<td align="right">2</td>
</tr>
<tr>
<td align="right">2013</td>
<td>NARCOTICS</td>
<td align="right">34127</td>
<td align="right">33819</td>
<td align="right">99.1</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">2013</td>
<td>CRIMINAL DAMAGE</td>
<td align="right">30853</td>
<td align="right">2107</td>
<td align="right">6.83</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">2013</td>
<td>OTHER OFFENSE</td>
<td align="right">17993</td>
<td align="right">3400</td>
<td align="right">18.9</td>
<td align="right">5</td>
</tr>
</tbody></table>

I have a unique situation. In my data I have year and within each year I have 5 categories and it's corresponding counts. I was able to create a stacked bar chart of those 5 categories for a corresponding year. However, I want to show 5 adjacent bars for each year on my x-axis. For y-axis it should show a corresponding total for each bar.

Here is my current viz and code:

import altair as alt


base = alt.Chart(q13a).encode(
alt.X('year:O',
    axis=alt.Axis(format='%b', title='Year'),
    scale=alt.Scale(zero=False)
),
tooltip = ['year']
)
bar = base.mark_bar().encode(
alt.Y('sum(Number_of_Incidents)',
    axis=alt.Axis(title='sum(Number_of_Incidents)'))
,color=alt.Color('primary_type')
#tooltip = ['primary_type']
)
line =  base.mark_line(color='red').encode(
#y='No_of_repos',
alt.Y('percent_arrest',
    axis=alt.Axis(title='percent_arrest')),
)
alt.layer(
bar
).resolve_scale(
y='independent'
).properties(
height=500,
width=1200
)

My question is, instead of a stacked bar, how can I create 5 adjacent bars for each year on my x-axis ?

Thanks for your help in advance.


回答1:


The only way to do side-by-side bars is to use a column encoding alongside an x encoding. You can follow the grouped bar chart example from Altair's example gallery here: https://altair-viz.github.io/gallery/grouped_bar_chart.html

The result for your data would be something like this:

import altair as alt
import pandas as pd
import numpy as np

q13a = pd.DataFrame({
    'year': np.random.randint(2000, 2018, 100),
    'Number_of_Incidents': np.random.randint(0, 20, 100),
    'percent_arrest': np.random.rand(100),
    'primary_type': np.random.choice(['a', 'b', 'c', 'd', 'e'], 100)
})

alt.Chart(q13a).mark_bar().encode(
    x=alt.X('primary_type', scale=alt.Scale(rangeStep=8), title=None),
    y=alt.Y('sum(Number_of_Incidents)', title='sum(Number_of_Incidents)'),
    color='primary_type',
    column='year',
    tooltip=['year']
).configure_view(
    stroke='transparent'
)




回答2:


@jakevdp has already answered, but for the sake of answering your last question (even though you should ask several questions if you have several points), you can sort the bars with alt.EncodingSortField.

import altair as alt

alt.Chart(q13a).mark_bar().encode(
    x=alt.X('primary_type:N', 
            scale=alt.Scale(rangeStep=8), 
            axis=None,
            sort=alt.EncodingSortField(field='Number_of_Incident', 
                                       op='sum', 
                                       order='ascending')
           ),
    y=alt.Y('sum(Number_of_Incidents):Q', title='sum(Number_of_Incidents)'),
    color='primary_type:N',
    tooltip=['primary_type:N', 
             'year:O', 
             alt.Tooltip('sum(Number_of_Incidents):Q',
                         title='Number of incidents')
            ]
).facet(
    column=alt.Column('year:O', 
                      header=alt.Header(title=None)),
).resolve_scale(
    x='independent'
).configure_view(
    stroke='transparent'
)


Data

import pandas as pd
from io import StringIO

q13a = pd.read_table(StringIO("""year   primary_type    Number_of_Incidents number_of_arrests   percent_arrest  rank
2018    THEFT   57330   5503    9.6     1
2018    BATTERY     44667   8886    19.89   2
2018    CRIMINAL DAMAGE     24889   1498    6.02    3
2018    ASSAULT     18229   2931    16.08   4
2018    DECEPTIVE PRACTICE  15879   713     4.49    5
2017    THEFT   64334   6459    10.04   1
2017    BATTERY     49213   10060   20.44   2
2017    CRIMINAL DAMAGE     29040   1747    6.02    3
2017    ASSAULT     19298   3455    17.9    4
2017    DECEPTIVE PRACTICE  18816   805     4.28    5
2016    THEFT   61600   6518    10.58   1
2016    BATTERY     50292   10328   20.54   2
2016    CRIMINAL DAMAGE     31018   1668    5.38    3
2016    ASSAULT     18738   3490    18.63   4
2016    DECEPTIVE PRACTICE  18733   815     4.35    5
2015    THEFT   57335   6771    11.81   1
2015    BATTERY     48918   11558   23.63   2
2015    CRIMINAL DAMAGE     28675   1835    6.4     3
2015    NARCOTICS   23883   23875   99.97   4
2015    OTHER OFFENSE   17552   4795    27.32   5
2014    THEFT   61561   7415    12.04   1
2014    BATTERY     49447   12517   25.31   2
2014    NARCOTICS   29116   29000   99.6    3
2014    CRIMINAL DAMAGE     27798   2095    7.54    4
2014    OTHER OFFENSE   16979   4159    24.49   5
2013    THEFT   71530   7727    10.8    1
2013    BATTERY     54002   12927   23.94   2
2013    NARCOTICS   34127   33819   99.1    3
2013    CRIMINAL DAMAGE     30853   2107    6.83    4
2013    OTHER OFFENSE   17993   3400    18.9    5"""))

Created on 2018-11-28 by the reprexpy package



来源:https://stackoverflow.com/questions/53517044/how-to-create-a-nested-grouped-bar-chart-using-altair-added-sample-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!