代码之家  ›  专栏  ›  技术社区  ›  Martin Thoma

如何为小时/工作日绘图设置两级刻度?

  •  0
  • Martin Thoma  · 技术社区  · 7 年前

    我有一个数据框架,其结构类似于以下内容:

    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 回复  |  直到 7 年前
        1
  •  4
  •   Martin Thoma    7 年前

    如果假设每个可能的工作日和小时都实际出现在数据中,那么轴单位将仅为小时,周一午夜为0,周日23小时为24*7-1=167。

    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

        2
  •  0
  •   Pedro Borges    7 年前

    这不完全是你提到的可视化,但一个想法是,解开你的熊猫时间序列,然后进行绘图。

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

    根据您在代码中提供的数据,结果如下:

    enter image description here

        3
  •  0
  •   Mr. T Andres Pinzon    7 年前

    major and minor ticks define their grid qualities 分别:

    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