【问题标题】:Lowering the x axis value density for dates on a seaborn line plot降低 seaborn 线图上日期的 x 轴值密度
【发布时间】:2020-11-22 21:11:37
【问题描述】:

对 python 和一般编程很陌生,所以请多多包涵。我有一个从 .csv 文件导入的数据集,我试图在 1 年内按日期(x 轴)绘制一列值(y 轴),但问题是日期太密集了,我我一生都无法弄清楚如何将它们隔开或修改它们的定义方式。这是我正在使用的代码:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl
from scipy import stats
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt

df = pd.read_csv('Vanuatu Earthquakes 2018-2019.csv')

这是线图代码:

plt.figure(figsize=(15, 7))
ax = sns.lineplot(x='date', y='mag', data=df).set_title("Earthquake magnitude May 2018-2019")

plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')
plt.savefig('EQ mag time')

目前这给了我这个线图:

目前我想通过每天的小勾号和每周开始的较大的勾号+标签来做到这一点。不必完全如此,但我主要是希望降低密度。我在这里查看了大量帖子,但似乎没有一个适合我的情况,因此我们将不胜感激。

[更新]

按照 Konqui 的建议确定日期,现在我的代码如下所示:

time = pd.date_range(start = '01-05-2018',
                     end = '01-05-2019',
                     freq = 'D')
df = pd.DataFrame({'date': list(map(lambda x: str(x), time)),
                   'mag': np.random.random(len(time))})

plt.figure(figsize=(15, 7))
df['date'] = pd.to_datetime(df['date'], format = '%Y-%m')
ax = sns.lineplot(x='date', y='mag', data=df).set_title("Earthquake magnitude May 2018-2019")
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))
plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')

这给了我一条错误消息:AttributeError: 'Text' object has no attribute 'xaxis'。有什么想法吗?

【问题讨论】:

    标签: python date datetime matplotlib seaborn


    【解决方案1】:

    假设

    我想你从一个类似于保存在Vanuatu Earthquakes 2018-2019.csv 文件中的数据框开始:

    import pandas as pd
    import numpy as np
    
    time = pd.date_range(start = '01-01-2020',
                         end = '31-03-2020',
                         freq = 'D')
    df = pd.DataFrame({'date': list(map(lambda x: str(x), time)),
                       'mag': np.random.random(len(time))})
    

    输出:

                      date       mag
    0  2020-01-01 00:00:00  0.940040
    1  2020-01-02 00:00:00  0.765570
    2  2020-01-03 00:00:00  0.951839
    3  2020-01-04 00:00:00  0.708172
    4  2020-01-05 00:00:00  0.705032
    5  2020-01-06 00:00:00  0.857500
    6  2020-01-07 00:00:00  0.866418
    7  2020-01-08 00:00:00  0.363287
    8  2020-01-09 00:00:00  0.289615
    9  2020-01-10 00:00:00  0.741499
    

    绘图:

    import seaborn as sns
    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots(figsize = (15, 7))
    
    sns.lineplot(ax = ax, x='date', y='mag', data=df).set_title('Earthquake magnitude May 2018-2019')
    
    plt.xlabel('Date')
    plt.ylabel('Magnitude (Mw)')
    
    plt.show()
    


    回答

    你应该做一系列的事情:

    1. 首先,您会得到标签的密度,因为您的 'date' 值是 str 类型,您需要将它们转换为 datetime by

      df['date'] = pd.to_datetime(df['date'], format = '%Y-%m-%d')
      

      这样你的 x 轴是datetime 类型,上面的图会变成这样:

    1. 然后你必须调整刻度;对于您应该设置的主要刻度:

      import matplotlib.dates as md
      
      # specify the position of the major ticks at the beginning of the week
      ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
      # specify the format of the labels as 'year-month-day'
      ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
      # (optional) rotate by 90° the labels in order to improve their spacing
      plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
      

      对于次要刻度:

      # specify the position of the minor ticks at each day
      ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))
      

      您可以选择编辑刻度的长度:

      ax.tick_params(axis = 'x', which = 'major', length = 10)
      ax.tick_params(axis = 'x', which = 'minor', length = 5)
      

      所以最终的情节将变成:


    完整代码

    # import required packages
    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib.dates as md
    
    # read the dataframe
    df = pd.read_csv('Vanuatu Earthquakes 2018-2019.csv')
    # convert 'date' column type from str to datetime
    df['date'] = pd.to_datetime(df['date'], format = '%Y-%m-%d')
    
    # prepare the figure
    fig, ax = plt.subplots(figsize = (15, 7))
    
    # set up the plot
    sns.lineplot(ax = ax, x='date', y='mag', data=df).set_title('Earthquake magnitude May 2018-2019')
    
    # specify the position of the major ticks at the beginning of the week
    ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
    # specify the format of the labels as 'year-month-day'
    ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
    # (optional) rotate by 90° the labels in order to improve their spacing
    plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
    
    # specify the position of the minor ticks at each day
    ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))
    
    # set ticks length
    ax.tick_params(axis = 'x', which = 'major', length = 10)
    ax.tick_params(axis = 'x', which = 'minor', length = 5)
    
    # set axes labels
    plt.xlabel('Date')
    plt.ylabel('Magnitude (Mw)')
    
    # show the plot
    plt.show()
    

    注意事项

    如果您注意我图中的 y 轴,您会看到 'mag' 的值落在 (0-1) 范围内。这是因为我使用'mag': np.random.random(len(time)) 生成了这个 fake 数据。如果您从文件Vanuatu Earthquakes 2018-2019.csv 中读取您的 数据,您将在y 轴上获得正确的值。尝试简单地复制完整代码部分中的代码。

    【讨论】:

    • 非常感谢,日期已更改!唯一的问题是现在幅度/y轴也发生了变化,有没有办法让这些值保持在数据框中的状态?它们非常具体,没有它们,这个数字就没有多大意义。
    • 在什么意义上“改变了”?您能否提供此新配置和相关更新代码的图片?
    • 所以简而言之,这是我的地质硕士论文,mag 列是一系列地震震级在 4 到 6 左右之间的里氏震级,现在它的值与你的图像相同发布在上面,介于 0.0 和 1.0 之间。只是在将数据框转换为日期时间之后才看起来像这样。同样对于ax.xaxis.set_major_locater 部分,当我添加这些部分时,我收到一条错误消息,提示 AttributeError: 'Text' object has no attribute 'xaxis'。有什么想法吗?
    • 哦,是的,当然 :-) 这是因为我没有你的数据可用,所以,为了生成我的图像,我用 'mag': np.random.random(len(time)) 创建了一些“假”数据,只有目的是向您展示调整轴的示例。在您的代码中,您应该将绘图 sns.lineplot(y = _something_...) 链接到您的真实数据
    • 关于您报告的AttributeError,您应该在上面编辑您的问题,报告更新的代码以便进行详细检查。没有你的代码,我无话可说
    猜你喜欢
    • 2020-09-03
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    相关资源
    最近更新 更多