Как я могу установить двухуровневые отметки для графика часов / дней в Пандах? - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть DataFrame, который структурно похож на следующее:

from datetime import datetime
import pandas as pd
from mpu.datetime import generate  # pip install mpu

mind, maxd = datetime(2018, 1, 1), datetime(2018, 12, 30)
df = pd.DataFrame({'datetime': [generate(mind, maxd) for _ in range(10)]})

Я хочу понять, как эти данные распределяются по часам дня и дням недели.Я могу получить их через:

df['weekday'] = df['datetime'].dt.weekday
df['hour'] = df['datetime'].dt.hour

И, наконец, у меня есть сюжет:

ax = df.groupby(['weekday', 'hour'])['datetime'].count().plot(kind='line', color='blue')
ax.set_ylabel("#")
ax.set_xlabel("time")
plt.show()

, который дает мне:

enter image description here

Но вы можете заметить, что трудно различить будни, а часы даже не заметны.Как я могу получить двухуровневые метки, похожие на следующие?

enter image description here

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Я не смог протестировать его с вашим набором данных, и pandas datetime иногда бывает сложно с matplotlib datetime.Но идея состоит в том, чтобы установить главные и второстепенные тики и , чтобы определить их свойства сетки отдельно:

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import dates as mdates

#create sample data and plot it
from io import StringIO
data = StringIO("""
X,A,B
2018-11-21T12:04:20,1,8
2018-11-21T18:14:17,6,7
2018-11-22T02:18:21,8,14
2018-11-22T12:31:54,7,8
2018-11-22T20:33:20,5,5
2018-11-23T12:23:12,13,2
2018-11-23T21:31:05,7,12
""")
df = pd.read_csv(data, parse_dates = True, index_col = "X")
ax=df.plot()

#format major locator
ax.xaxis.set_major_locator(mdates.DayLocator())
#format minor locator with specific hours
ax.xaxis.set_minor_locator(mdates.HourLocator(byhour = [8, 12, 18]))
#label major ticks
ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %d %m'))
#label minor ticks
ax.xaxis.set_minor_formatter(mdates.DateFormatter("%H:00"))
#set grid for major ticks
ax.grid(which = "major", axis = "x", linestyle = "-", linewidth = 2)
#set grid for minor ticks with different properties
ax.grid(which = "minor", axis = "x", linestyle = "--", linewidth = 1)

plt.show()

Пример вывода: enter image description here

0 голосов
/ 24 ноября 2018

Если вы предполагаете, что каждый возможный день недели и час на самом деле появляются в данных, единицами измерения осей будут просто часы, для полуночи понедельника - 0, а для 23-го воскресенья - 24 * 7-1 = 167. Затем вы можете отмечать каждые 24часы с основными отметками и маркируйте каждый полдень соответствующим днем ​​недели.

import numpy as np; np.random.seed(42)
import datetime as dt
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FuncFormatter, NullFormatter

# Generate example data
N = 5030
delta = (dt.datetime(2019, 1, 1) - dt.datetime(2018, 1, 1)).total_seconds()
df = pd.DataFrame({'datetime': np.array("2018-01-01").astype(np.datetime64) + 
                               (delta*np.random.rand(N)).astype(np.timedelta64)})

# Group the data
df['weekday'] = df['datetime'].dt.weekday
df['hour'] = df['datetime'].dt.hour

counts = df.groupby(['weekday', 'hour'])['datetime'].count()

ax = counts.plot(kind='line', color='blue')
ax.set_ylabel("#")
ax.set_xlabel("time")
ax.grid()
# Now we assume that there is data for every hour and day present
assert len(counts) == 7*24
# Hence we can tick the axis with multiples of 24h
ax.xaxis.set_major_locator(MultipleLocator(24))
ax.xaxis.set_minor_locator(MultipleLocator(1))

days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
def tick(x,pos):
    if x % 24 == 12:
        return days[int(x)//24]
    else:
        return ""
ax.xaxis.set_major_formatter(NullFormatter())
ax.xaxis.set_minor_formatter(FuncFormatter(tick))
ax.tick_params(which="major", axis="x", length=10, width=1.5)
plt.show()

enter image description here

0 голосов
/ 23 ноября 2018

Это не совсем та визуализация, о которой вы упомянули, но идея состоит в том, чтобы разложить ваши временные ряды панд и затем построить график.

df.groupby(['weekday', 'hour'])['datetime'].count().unstack(level=0).plot()

Результат с данными, указанными в вашем коде, будет следующим:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...