#python #pandas #dataframe #bar-chart #plotly-python
#python #pandas #фрейм данных #гистограмма #plotly-python
Вопрос:
создал гистограмму стека, чтобы визуализировать распределение времени для каждого дня работы машины. Но не могу получить тот же порядок данных в строке стека.
Пример: День 01-09, исходный порядок данных выполняется (36068 сек.) и состояние B (6842 сек.), Но в стековой строке первым является состояние B, а затем состояние выполнения. Таким образом, мы можем получить тот же порядок данных в строке стека?
код с фреймом данных:
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()
Ответ №1:
Plotly заботится о порядке добавления данных.
Таким образом, чтобы изменить каждый столбец, вы должны изменить порядок, в котором plotly получает данные для каждого столбца.
Для вас это означает, что для каждого дня / ночи вам нужно будет менять значения, как у меня ниже.
Вот код:
import json
## Get the values of each data dict as lists
shifts = list(data['Shifts'].values())
seconds = list(data['Seconds'].values())
states = list(data['States'].values())
shifts_indexed = []
shift_indexed = []
## Put each shift's indexes into a separate list
## Then those lists into a list of index lists
for index in range(len(shifts)):
shift = shifts[index]
## Can't get previous index yet because there isn't one
if index == 0:
shift_indexed.append(index)
## If index is the last one
elif index == (len(shifts)-1):
shift_indexed.append(index)
shifts_indexed.append(shift_indexed)
## Compare all other shifts to the last shift to see if it's a new shift
## If it's a new shift, add the shift's index to the list of shifts
## Then reset the shift_indexed list for the next shift
else:
last_index = index - 1
last_shift = shifts[last_index]
## Shift is different
if shift != last_shift:
## Add the shifts index list to list of shifts
shifts_indexed.append(shift_indexed)
## Clear the list for the next shift
shift_indexed = []
## Add the new shift to the newly cleared index list
shift_indexed.append(index)
## Shift is the same
else:
shift_indexed.append(index)
## Remake dictionary
fixed = {}
fixed_shifts = {}
fixed_secs = {}
fixed_states = {}
## For each list of shift indexes
for list in shifts_indexed:
# Get the list of shift indexes but in reverse
r_list = list[:None:-1]
## Create dictionaries using the indexes in the reversed index list (r_list)
for i in range(len(list)):
index = list[i]
r_index = r_list[i]
shift = shifts[index]
second = seconds[index]
state = states[index]
fixed_shifts[r_index] = shift
fixed_secs[r_index] = second
fixed_states[r_index] = state
## Set to final dictionary
fixed['Shifts'] = fixed_shifts
fixed['Seconds'] = fixed_secs
fixed['States'] = fixed_states
print('nDatann' json.dumps(data, sort_keys=True, indent=4))
print('nFixednn' json.dumps(fixed, sort_keys=True, indent=4))
Перед:
data = {
'Shifts': {
0: 'Day 01-05',
1: 'Day 01-05',
2: 'Day 01-05',
3: 'Day 01-05'
},
'States': {
0: 'D',
1: 'STOPPED',
2: 'B',
3: 'A'
},
'Seconds': {
0: 7439,
1: 0,
2: 10,
3: 35751
}
}
После:
data = {
'Shifts': {
0: 'Day 01-05',
1: 'Day 01-05',
2: 'Day 01-05',
3: 'Day 01-05'
},
'States': {
0: 'A',
1: 'B',
2: 'STOPPED',
3: 'D'
},
'Seconds': {
0: 35751,
1: 10,
2: 0,
3: 7439
}
}
Комментарии:
1. не могли бы вы уточнить свой ответ с помощью кода?
2. @domahc Я обновил свой ответ рабочим кодом