2
votes

Hi created a stack bar chart using python plotly. But gives the wrong X-axis order.

DF :

Day-Shift   State          seconds
Day 01-05   A              7439
Day 01-05   STOPPED        0
Day 01-05   B              10
Day 01-05   C              35751
Night 01-05 C              43200
Day 01-06   STOPPED        7198
Day 01-06   F              18
Day 01-06   A              14
Day 01-06   A              29301
Day 01-06   STOPPED        6
Day 01-06   A              6663
Night 01-06 A              43200

In df Day-Shift represent shift and Date, it goes Day 01-05, Night 01-05, Day 01-06, Night 01-06, and so on. But in the graph, gives the wrong order on X-axis. Ex: After the Day 01-05 graph shows Night 01-08 instead of Night 01-05.

enter image description here

Sample df and my code attached below:

import plotly.express as px
fig = px.bar(df, x="Day-Shift", y="seconds", color="State")
fig.show()

Df ad Dict:

import pandas as pd
import plotly.express as px


df = pd.DataFrame({'Day-Shift': {0: 'Day 01-05',
  1: 'Day 01-05',
  2: 'Day 01-05',
  3: 'Day 01-05',
  4: 'Night 01-05',
  5: 'Day 01-06',
  6: 'Day 01-06',
  7: 'Day 01-06',
  8: 'Day 01-06',
  9: 'Day 01-06',
  10: 'Day 01-06',
  11: 'Night 01-06',
  12: 'Day 01-07',
  13: 'Night 01-07',
  14: 'Night 01-07',
  15: 'Night 01-07',
  16: 'Night 01-07',
  17: 'Night 01-07',
  18: 'Night 01-08',
  19: 'Night 01-08',
  20: 'Night 01-08',
  21: 'Night 01-08',
  22: 'Day 01-08',
  23: 'Day 01-08',
  24: 'Day 01-08',
  25: 'Night 01-09',
  26: 'Night 01-09',
  27: 'Night 01-09',
  28: 'Day 01-09',
  29: 'Day 01-09',
  30: 'Day 01-09',
  31: 'Day 01-09',
  32: 'Day 01-10',
  33: 'Night 01-10',
  34: 'Day 01-11',
  35: 'Day 01-11',
  36: 'Day 01-11',
  37: 'Day 01-11',
  38: 'Day 01-11',
  39: 'Night 01-11',
  40: 'Day 01-12',
  41: 'Night 01-12',
  42: 'Day 01-13',
  43: 'Day 01-13',
  44: 'Day 01-13',
  45: 'Day 01-13',
  46: 'Day 01-13',
  47: 'Day 01-13',
  48: 'Day 01-13',
  49: 'Night 01-13',
  50: 'Day 01-14',
  51: 'Day 01-14',
  52: 'Day 01-14',
  53: 'Day 01-14',
  54: 'Day 01-14',
  55: 'Day 01-14',
  56: 'Day 01-14',
  57: 'Day 01-14',
  58: 'Day 01-14',
  59: 'Night 01-14'},
 'State': {0: 'D',
  1: 'STOPPED',
  2: 'B',
  3: 'A',
  4: 'A',
  5: 'A',
  6: 'A1',
  7: 'A2',
  8: 'A3',
  9: 'A4',
  10: 'B1',
  11: 'B1',
  12: 'B1',
  13: 'B1',
  14: 'B2',
  15: 'STOPPED',
  16: 'RUNNING',
  17: 'B',
  18: 'STOPPED',
  19: 'B',
  20: 'RUNNING',
  21: 'D',
  22: 'STOPPED',
  23: 'B',
  24: 'RUNNING',
  25: 'STOPPED',
  26: 'RUNNING',
  27: 'B',
  28: 'RUNNING',
  29: 'STOPPED',
  30: 'B',
  31: 'D',
  32: 'B',
  33: 'B',
  34: 'B',
  35: 'RUNNING',
  36: 'STOPPED',
  37: 'D',
  38: 'A',
  39: 'A',
  40: 'A',
  41: 'A',
  42: 'A',
  43: 'A1',
  44: 'A2',
  45: 'A3',
  46: 'A4',
  47: 'B1',
  48: 'B2',
  49: 'B2',
  50: 'B2',
  51: 'B',
  52: 'STOPPED',
  53: 'A',
  54: 'A1',
  55: 'A2',
  56: 'A3',
  57: 'A4',
  58: 'B1',
  59: 'B1'},
 'seconds': {0: 7439,
  1: 0,
  2: 10,
  3: 35751,
  4: 43200,
  5: 7198,
  6: 18,
  7: 14,
  8: 29301,
  9: 6,
  10: 6663,
  11: 43200,
  12: 43200,
  13: 5339,
  14: 8217,
  15: 0,
  16: 4147,
  17: 1040,
  18: 24787,
  19: 1500,
  20: 14966,
  21: 1410,
  22: 2499,
  23: 1310,
  24: 39391,
  25: 3570,
  26: 17234,
  27: 47390,
  28: 36068,
  29: 270,
  30: 6842,
  31: 20,
  32: 43200,
  33: 43200,
  34: 2486,
  35: 8420,
  36: 870,
  37: 30,
  38: 31394,
  39: 43200,
  40: 43200,
  41: 43200,
  42: 36733,
  43: 23,
  44: 6,
  45: 4,
  46: 4,
  47: 3,
  48: 6427,
  49: 43200,
  50: 620,
  51: 0,
  52: 4,
  53: 41336,
  54: 4,
  55: 4,
  56: 4,
  57: 23,
  58: 1205,
  59: 43200}})

Really appreciate your support !!!

2
cannot test plotly at the moment but try assigning the values as categorical to retain ordering of original column and then plot? df['Day-Shift'] = pd.Categorical(df['Day-Shift'],df['Day-Shift'].unique(),ordered=True)anky
Really appreciate your answer, But it didn't change the chart.domahc
@domahc Could you specify how this question is different from this?vestland
@vestland your mentioned question I asked what is the error behind my code to give an unexpected graph. Here i visualized it correctly (using your suggestions to the previous question) but the order of the X-axis is different from the original dataframe.domahc
this question occurred in the previous question's comment section..That's why I asked it separately.domahc

2 Answers

2
votes

You can use category_orders to set the order of values:

import pandas as pd 
import plotly.express as px 
df = pd.DataFrame({'Day-Shift': {0: 'Day 01-05', 1: 'Day 01-05', 2: 'Day 01-05', 3: 'Day 01-05', 4: 'Night 01-05', 5: 'Day 01-06', 6: 'Day 01-06', 7: 'Day 01-06', 8: 'Day 01-06', 9: 'Day 01-06', 10: 'Day 01-06', 11: 'Night 01-06', 12: 'Day 01-07', 13: 'Night 01-07', 14: 'Night 01-07', 15: 'Night 01-07', 16: 'Night 01-07', 17: 'Night 01-07', 18: 'Night 01-08', 19: 'Night 01-08', 20: 'Night 01-08', 21: 'Night 01-08', 22: 'Day 01-08', 23: 'Day 01-08', 24: 'Day 01-08', 25: 'Night 01-09', 26: 'Night 01-09', 27: 'Night 01-09', 28: 'Day 01-09', 29: 'Day 01-09', 30: 'Day 01-09', 31: 'Day 01-09', 32: 'Day 01-10', 33: 'Night 01-10', 34: 'Day 01-11', 35: 'Day 01-11', 36: 'Day 01-11', 37: 'Day 01-11', 38: 'Day 01-11', 39: 'Night 01-11', 40: 'Day 01-12', 41: 'Night 01-12', 42: 'Day 01-13', 43: 'Day 01-13', 44: 'Day 01-13', 45: 'Day 01-13', 46: 'Day 01-13', 47: 'Day 01-13', 48: 'Day 01-13', 49: 'Night 01-13', 50: 'Day 01-14', 51: 'Day 01-14', 52: 'Day 01-14', 53: 'Day 01-14', 54: 'Day 01-14', 55: 'Day 01-14', 56: 'Day 01-14', 57: 'Day 01-14', 58: 'Day 01-14', 59: 'Night 01-14'}, 'State': {0: 'D', 1: 'STOPPED', 2: 'B', 3: 'A', 4: 'A', 5: 'A', 6: 'A1', 7: 'A2', 8: 'A3', 9: 'A4', 10: 'B1', 11: 'B1', 12: 'B1', 13: 'B1', 14: 'B2', 15: 'STOPPED', 16: 'RUNNING', 17: 'B', 18: 'STOPPED', 19: 'B', 20: 'RUNNING', 21: 'D', 22: 'STOPPED', 23: 'B', 24: 'RUNNING', 25: 'STOPPED', 26: 'RUNNING', 27: 'B', 28: 'RUNNING', 29: 'STOPPED', 30: 'B', 31: 'D', 32: 'B', 33: 'B', 34: 'B', 35: 'RUNNING', 36: 'STOPPED', 37: 'D', 38: 'A', 39: 'A', 40: 'A', 41: 'A', 42: 'A', 43: 'A1', 44: 'A2', 45: 'A3', 46: 'A4', 47: 'B1', 48: 'B2', 49: 'B2', 50: 'B2', 51: 'B', 52: 'STOPPED', 53: 'A', 54: 'A1', 55: 'A2', 56: 'A3', 57: 'A4', 58: 'B1', 59: 'B1'}, 'seconds': {0: 7439, 1: 0, 2: 10, 3: 35751, 4: 43200, 5: 7198, 6: 18, 7: 14, 8: 29301, 9: 6, 10: 6663, 11: 43200, 12: 43200, 13: 5339, 14: 8217, 15: 0, 16: 4147, 17: 1040, 18: 24787, 19: 1500, 20: 14966, 21: 1410, 22: 2499, 23: 1310, 24: 39391, 25: 3570, 26: 17234, 27: 47390, 28: 36068, 29: 270, 30: 6842, 31: 20, 32: 43200, 33: 43200, 34: 2486, 35: 8420, 36: 870, 37: 30, 38: 31394, 39: 43200, 40: 43200, 41: 43200, 42: 36733, 43: 23, 44: 6, 45: 4, 46: 4, 47: 3, 48: 6427, 49: 43200, 50: 620, 51: 0, 52: 4, 53: 41336, 54: 4, 55: 4, 56: 4, 57: 23, 58: 1205, 59: 43200}})

fig = px.bar(df, x="Day-Shift", y="seconds", category_orders={'Day-Shift': df['Day-Shift'].to_list()},color="State")
fig.show()

Output: enter image description here

2
votes

Setting category_orders = {"Day-Shift":df['Day-Shift'].unique()} will work, but only reliably if your dataset has the correct order to begin with. Another condition is that you only have data for one unique year. In order to guarantee the correct order regardless of original order, and to make it possible to have data for december 2020 combinde with january 2021 I would suggest you to:

  1. split "Day-Shift" into two separate columns; time of day == tod and day of month = date,
  2. append year to youe dates, like dfs['date2'] = dfs['date'] + '-2021',
  3. turn 'date2' into datetime using dfs['date2'] = pd.to_datetime(dfs['date2']),
  4. sort your values chronologically, and
  5. retrive "Day-Shift" in the now correct order with new_order = list(df['Day-Shift'].unique()), and then
  6. apply the chronologially correct order through category_orders = {'Day-Shift': new_order}

Plot

enter image description here

Complete code:

import pandas as pd
import plotly.express as px

df = pd.DataFrame({'Day-Shift': {0: 'Day 01-05',
  1: 'Day 01-05',
  2: 'Day 01-05',
  3: 'Day 01-05',
  4: 'Night 01-05',
  5: 'Day 01-06',
  6: 'Day 01-06',
  7: 'Day 01-06',
  8: 'Day 01-06',
  9: 'Day 01-06',
  10: 'Day 01-06',
  11: 'Night 01-06',
  12: 'Day 01-07',
  13: 'Night 01-07',
  14: 'Night 01-07',
  15: 'Night 01-07',
  16: 'Night 01-07',
  17: 'Night 01-07',
  18: 'Night 01-08',
  19: 'Night 01-08',
  20: 'Night 01-08',
  21: 'Night 01-08',
  22: 'Day 01-08',
  23: 'Day 01-08',
  24: 'Day 01-08',
  25: 'Night 01-09',
  26: 'Night 01-09',
  27: 'Night 01-09',
  28: 'Day 01-09',
  29: 'Day 01-09',
  30: 'Day 01-09',
  31: 'Day 01-09',
  32: 'Day 01-10',
  33: 'Night 01-10',
  34: 'Day 01-11',
  35: 'Day 01-11',
  36: 'Day 01-11',
  37: 'Day 01-11',
  38: 'Day 01-11',
  39: 'Night 01-11',
  40: 'Day 01-12',
  41: 'Night 01-12',
  42: 'Day 01-13',
  43: 'Day 01-13',
  44: 'Day 01-13',
  45: 'Day 01-13',
  46: 'Day 01-13',
  47: 'Day 01-13',
  48: 'Day 01-13',
  49: 'Night 01-13',
  50: 'Day 01-14',
  51: 'Day 01-14',
  52: 'Day 01-14',
  53: 'Day 01-14',
  54: 'Day 01-14',
  55: 'Day 01-14',
  56: 'Day 01-14',
  57: 'Day 01-14',
  58: 'Day 01-14',
  59: 'Night 01-14'},
 'State': {0: 'D',
  1: 'STOPPED',
  2: 'B',
  3: 'A',
  4: 'A',
  5: 'A',
  6: 'A1',
  7: 'A2',
  8: 'A3',
  9: 'A4',
  10: 'B1',
  11: 'B1',
  12: 'B1',
  13: 'B1',
  14: 'B2',
  15: 'STOPPED',
  16: 'RUNNING',
  17: 'B',
  18: 'STOPPED',
  19: 'B',
  20: 'RUNNING',
  21: 'D',
  22: 'STOPPED',
  23: 'B',
  24: 'RUNNING',
  25: 'STOPPED',
  26: 'RUNNING',
  27: 'B',
  28: 'RUNNING',
  29: 'STOPPED',
  30: 'B',
  31: 'D',
  32: 'B',
  33: 'B',
  34: 'B',
  35: 'RUNNING',
  36: 'STOPPED',
  37: 'D',
  38: 'A',
  39: 'A',
  40: 'A',
  41: 'A',
  42: 'A',
  43: 'A1',
  44: 'A2',
  45: 'A3',
  46: 'A4',
  47: 'B1',
  48: 'B2',
  49: 'B2',
  50: 'B2',
  51: 'B',
  52: 'STOPPED',
  53: 'A',
  54: 'A1',
  55: 'A2',
  56: 'A3',
  57: 'A4',
  58: 'B1',
  59: 'B1'},
 'seconds': {0: 7439,
  1: 0,
  2: 10,
  3: 35751,
  4: 43200,
  5: 7198,
  6: 18,
  7: 14,
  8: 29301,
  9: 6,
  10: 6663,
  11: 43200,
  12: 43200,
  13: 5339,
  14: 8217,
  15: 0,
  16: 4147,
  17: 1040,
  18: 24787,
  19: 1500,
  20: 14966,
  21: 1410,
  22: 2499,
  23: 1310,
  24: 39391,
  25: 3570,
  26: 17234,
  27: 47390,
  28: 36068,
  29: 270,
  30: 6842,
  31: 20,
  32: 43200,
  33: 43200,
  34: 2486,
  35: 8420,
  36: 870,
  37: 30,
  38: 31394,
  39: 43200,
  40: 43200,
  41: 43200,
  42: 36733,
  43: 23,
  44: 6,
  45: 4,
  46: 4,
  47: 3,
  48: 6427,
  49: 43200,
  50: 620,
  51: 0,
  52: 4,
  53: 41336,
  54: 4,
  55: 4,
  56: 4,
  57: 23,
  58: 1205,
  59: 43200}})

dfs = df['Day-Shift'].str.extract('([a-zA-Z]+)([^a-zA-Z]+)', expand=True)
dfs.columns = ['tod', 'date']
dfs['date2'] = dfs['date'] + '-2021'
dfs['date2'] = pd.to_datetime(dfs['date2'])

df = pd.concat([df, dfs], axis = 1)
df = df.sort_values(['date2', 'tod'], ascending = [True, True])

new_order = list(df['Day-Shift'].unique())
# df['Day-Shift'] = pd.Categorical(df['Day-Shift'], categories=new_order, ordered=True)

fig = px.bar(df, x="Day-Shift", y="seconds", color="State",
            category_orders = {'Day-Shift': new_order})
fig.update_xaxes(type='category')
fig.show()