У меня есть вопрос, связанный с временными рядами, о том, как наносить метки времени вдоль горизонтальной оси для нескольких случаев, приписываемых одному и тому же лицу. Позвольте мне объяснить:
Допустим, у нас есть Джейсон и Джорджия. Оба они работают в разных случаях, которые в основном имеют эти потенциальные «события»: начало, пауза, возобновление, конец. Во многих случаях есть только «начало» и «конец», тогда как другие также включают интервал паузы-возобновления. Пока один случай приостановлен, пользователь может работать над другим делом. У меня есть вся эта информация на Pandas DataFrame, и я собираю информацию на уровне пользователей и дел, выполняя groupby
.
Пример данных для воспроизводимого кода (при условии, что импортированы pandas
и numpy
):
raw_data = {'user': ['Jason', 'Georgia', 'Jason', 'Jason', 'Georgia'],
'case': ['a', 'b', 'c', 'd', 'e'],
'date_picked_up': ['2018-10-25 14:06', '2019-01-25 10:44', '2019-01-25 09:14', '2019-01-25 12:12', '2019-02-21 10:01'],
'date_paused': ['2018-10-26 11:08', '2019-01-25 12:11', np.nan, np.nan, '2019-02-21 12:37'],
'date_resumed': ['2018-10-26 11:20', '2019-01-25 15:21', np.nan, np.nan, '2019-02-21 13:24'],
'date_closed': ['2018-10-29 16:57', '2019-01-25 16:34', '2019-01-25 11:46', '2019-01-25 15:24', '2019-01-25 13:56']}
df = pd.DataFrame(raw_data, columns = ['user', 'case', 'date_picked_up', 'date_paused', 'date_resumed', 'date_closed'])
df
Возвращает df
, pandas DataFrame с последовательностью каждого случая. Когда у нас нет интервала паузы возобновления, значения np.nan
. Панды groupby
автоматически игнорируют nan
значения, которые нам не нужны, поэтому для решения этой проблемы я использую fillna
с Timestamp
в 1900 году, после применения ко всем столбцам pd.to_datetime
:
date_cols = ['date_picked_up', 'date_paused', 'date_resumed', 'date_closed']
for c in date_cols:
df[c] = pd.to_datetime(df[c], format='%Y%m%d %H:%M')
Теперь я нашел лучший способ агрегирования данных по пользователям, а затем по конкретным случаям:
df.fillna(pd.Timestamp('19000101'))\
.groupby(['user', 'case', 'date_picked_up', 'date_paused', 'date_resumed', 'date_closed'])[['date_picked_up', 'date_paused', 'date_resumed', 'date_closed']].count()
Моя цель (из данных этого примера) - два графика, один для Джейсона и один для Джорджии, где отметки времени (в идеале, не 1900) будут отображаться вдоль горизонтальных «линий», по одному для каждого случая (на ось). Ближайший пример здесь: Построение помеченных временных рядов в пандах , где вместо собак, кошек и коров у нас были бы (для Джейсона) случаи a, c и d на оси y.
Я нашел идеи о том, как переместить все в bokeh
или d3
для того, что я действительно хочу (например: https://github.com/jiahuang/d3-timeline, Как построить график продолжительности событий (диаграммы Ганта) с помощью Python Pandas ? ), но я надеюсь найти решение в Python и Matplotlib / Seaborn, так как считаю, что моя структура данных уже находится в достаточно хорошем формате.