3

I am new to using Altair and have crudely combined some code from here and here which gives me the plot below but I cannot work out why my columns are shown in a non-sequential order. My dataframe is as follows:

import pandas as pd

TimeMth = pd.DataFrame([['Jul-2011', '> 1.1 pu',  86],
                       ['Jul-2011', '< 0.94 pu',  18],
                       ['Aug-2011', '> 1.1 pu',  205],
                       ['Aug-2011', '< 0.94 pu', 510],
                       ['Sep-2011', '> 1.1 pu',   53],
                       ['Sep-2011', '< 0.94 pu', 140],
                       ['Oct-2011', '> 1.1 pu',   10],
                       ['Oct-2011', '< 0.94 pu',   0],
                       ['Nov-2011', '> 1.1 pu',   36],
                       ['Nov-2011', '< 0.94 pu',  13],
                       ['Dec-2011', '> 1.1 pu',    7],
                       ['Dec-2011', '< 0.94 pu',   0],
                       ['Jan-2012', '> 1.1 pu',   17],
                       ['Jan-2012', '< 0.94 pu',   0],
                       ['Feb-2012', '> 1.1 pu',    0],
                       ['Feb-2012', '< 0.94 pu',   0],
                       ['Mar-2012', '> 1.1 pu',   17],
                       ['Mar-2012', '< 0.94 pu',   1],
                       ['Apr-2012', '> 1.1 pu',   49],
                       ['Apr-2012', '< 0.94 pu',  79],
                       ['May-2012', '> 1.1 pu',    8],
                       ['May-2012', '< 0.94 pu',   0],
                       ['Jun-2012', '> 1.1 pu',   40],
                       ['Jun-2012', '< 0.94 pu',  12]],
                    columns=['Month','Voltage','No of Violations'])

which I then attempt to plot with:

import altair as alt

chartTimeMth = alt.Chart(TimeMth).mark_bar().encode(
column=alt.Column('Month',
            axis=alt.Axis(axisWidth=1.0, 
               offset=-8.0, orient='bottom', labelAngle=-45, 
labelAlign='right'),
            scale=alt.Scale(padding=4.0)),
x=alt.X('Voltage',
       axis=False),
y=alt.Y('No of Violations', title='No. of voltage violations', 
axis=alt.Axis(grid=False)),
color=alt.Color('Voltage', scale=alt.Scale(range=['#96ceb4', '#ffcc5c']))
).configure_facet_cell(
strokeWidth=0.0,)\
.configure_scale(bandSize=12)\
.configure_legend(titleFontSize=12, offset=-60, orient='right')

chartTimeMth.display()

When I use sortField on the columns it gets close to what I need but still not right. I guess this is something to do with the fact that my column (Month) data is text? Any ideas on why the above code (with the sortField class omitted) does not plot the columns in index order? If my Month data was datetimeindex, is there a way to tell Altair to label the x-axis as I have below (ie mmm-yyyy)?

enter image description here

4bears
  • 93
  • 3
  • 9

1 Answers1

6

You can specify the data type using the type keyword.

column=alt.Column('Month',type='temporal', ....

You can also use Encoding Shorthands to define the data type

column=alt.Column('Month:T', ...

As for the formatting of the axis you can pass the format keyword a date directive string when you make your axis

axis = alt.Axis(..., format='%b-%Y')

Here is the your previous code with the above changes made.

chartTimeMth = alt.Chart(TimeMth).mark_bar().encode(
    column=alt.Column(
        'Month:T',
        axis=alt.Axis(
            axisWidth=1.0, 
            offset=-8.0, 
            orient='bottom', 
            labelAngle=-45, 
            labelAlign='right', 
            format='%b-%Y'
        ),
        scale=alt.Scale(padding=4.0)
    ),
    x=alt.X('Voltage', axis=False),
    y=alt.Y(
        'No of Violations', 
        title='No. of voltage violations', 
        axis=alt.Axis(grid=False)),
        color=alt.Color(
            'Voltage', 
            scale=alt.Scale(range=['#96ceb4', '#ffcc5c'])
    )
).configure_facet_cell(strokeWidth=0.0,)\
 .configure_scale(bandSize=12)\
 .configure_legend(titleFontSize=12, offset=-60, orient='right')

enter image description here

Oskar Austegard
  • 4,599
  • 4
  • 36
  • 50
eitanlees
  • 1,244
  • 10
  • 14