【问题标题】:Matplotlib problem: tick re-mapping of x-axis of time-series dataMatplotlib 问题:时间序列数据 x 轴的刻度重新映射
【发布时间】:2020-05-03 08:04:15
【问题描述】:

我想使用 MatPlotLib 绘制时间序列数据。数据以 csv 格式存储,我使用 pd.read_csv() 处理到 Pandas DataFrame,效果很好。一个数据集包括一个时间戳列和大约 10 个值列。我通过pd.to_datetime(dataFrame['TIMESTAMP'], format='%Y-%m-%d %H:%M:%S') 将时间戳(最初是格式为 yyyy-MM-dd hh:mm:ss 的字符串)转换为 datetime。

为了绘制数据,我使用以下代码(示例数据的生成不是我的代码的一部分):

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns

N = 30
timestamps = pd.date_range('2020-01-16 8:00', periods=N, freq='72s')
# note: the original timestamps aren't evenly spaced, this is just data to test
dataFrame = pd.DataFrame({'TIMESTAMP': timestamps, 'Y1': np.random.normal(100, 30, N), 'Y2': np.random.normal(100, 30, N)})
acqFieldName = 'Y1'

fig = sns.pointplot(x='TIMESTAMP', y=acqFieldName, data=dataFrame, scale=0.75)
timestamps = dataFrame['TIMESTAMP'].dt.time
fig.axes.set_xticklabels(labels=timestamps, rotation=45)
plt.show()

结果如下:

不过,我还是想更改 x 轴:刻度太密集,所以我想要 - 比如说 - 10 个刻度,我希望以分钟为单位查看花费的时间,格式为 'mm :ss'。

我尝试了以下方法:

fig = sns.pointplot(x='TIMESTAMP', y=acqFieldName, data=dataFrame, scale=0.75)
timestamps = dataFrame['TIMESTAMP'].dt.time

xmin = dataFrame['TIMESTAMP'][0]
xmax = dataFrame['TIMESTAMP'][len(dataFrame['TIMESTAMP']) - 1]

timeDiff: timedelta = xmax - xmin
customTicks = np.linspace(0., timeDiff.seconds, 10)
fig.axes.set_xticklabels(labels=customTicks, rotation=45)
fig.axes.set_xticks(customTicks)
plt.show()

结果如下:

显然不是我想要的。

如果我可以减少格式化为时间的刻度数,或者 - 更好 - 如果这些点与所用时间给出的刻度对齐,我的问题就会得到解决。

更新:更木剑八产量建议

    fig, ax = plt.subplots()
    ax.plot(dataFrame.set_index('TIMESTAMP'), dataFrame[acqFieldName])
    plt.show()


基于 JohanC 答案的工作解决方案:

for fileName in glob.glob('*.csv'):
    plt.close()
    # NOTE: CsvFileProcessor is a custom class doing the readout of CSV and conversion to pandas.DataFrame
    dataFrame, acqFieldName, settingParameterCount = CsvFileProcessor.processFile(fileName)

    fig, ax = plt.subplots()
    ax: plt.Subplot = sns.pointplot(x='TIMESTAMP', y=acqFieldName, data=dataFrame, scale=0.75, ax=ax)
    startTime = dataFrame['TIMESTAMP'][0]

    timeProgress = []

    for timeStamp in dataFrame['TIMESTAMP']:
        timePassed = timeStamp - startTime
        timeProgress.append(timePassed)

    custom_ticks = range(0, len(timeProgress), 5)
    timestamps = [f"{datetime.timedelta(seconds=timeProgress[t].seconds)}" for t in custom_ticks]

    # for manipulating the x-axis tick labels:
    # https://stackoverflow.com/questions/51105648/ordering-and-formatting-dates-on-x-axis-in-seaborn-bar-plot
    ax.axes.set_xticklabels(labels=timestamps, rotation=45)
    ax.axes.set_xlabel(xlabel="Processing Time")
    plt.title('Setting Parameters: ' + str(settingParameterCount))
    ax.axes.set_xticks(custom_ticks)
    outFileName = fileName.upper()
    outFileName = outFileName.replace('_DATA.CSV', '')
    outFileName = outFileName + '_READOUT.PNG'
    fig.tight_layout()
    #plt.savefig(outFileName)
    plt.show()

结果:

【问题讨论】:

  • 发布或附加 csv 数据样本
  • @WolfiG 我在您的帖子中添加了一些测试数据。随时改进。

标签: python pandas matplotlib seaborn


【解决方案1】:

主要的困惑来自这个 Seaborn 点图,其中 x 刻度为数字 0,1,2,... 并为它们创建了一些令人困惑的标签。

要得到你想要的,你可以设置每 5 个刻度,并为它们提供自定义标签。还要添加次要刻度,以使每个条目都有一个刻度。

演示代码:

import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
import pandas as pd
import numpy as np
import seaborn as sns

N = 30
timestamps = pd.date_range('2020-01-16 8:00:00', periods=N, freq='73s')
dataFrame = pd.DataFrame({'TIMESTAMP': timestamps, 'Y1': np.random.normal(100, 30, N), 'Y2': np.random.normal(100, 30, N)})

fig = sns.pointplot(x='TIMESTAMP', y='Y1', data=dataFrame, scale=0.75)

custom_ticks = range(0, len(dataFrame), 5) # ticks every 5
timestamps = [f"{dataFrame['TIMESTAMP'][t].minute:02}:{dataFrame['TIMESTAMP'][t].second:02}" for t in custom_ticks]

fig.axes.set_xticklabels(timestamps)
fig.axes.set_xticks(custom_ticks)
fig.axes.xaxis.set_minor_locator(AutoMinorLocator())

plt.tight_layout()
plt.show()

【讨论】:

  • 非常感谢这个工作。只有一件事:您使用一种花哨的符号来生成时间戳数组。我在哪里/在哪个关键字下可以找到有关此语法的文档?
  • 该表示法称为f-strings,自 Python 3.6 以来新增。通常它们比其他将变量填充到字符串中的方法更方便、更易读。
【解决方案2】:

尝试简单的情节:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(df.set_index('TIMESTAMP'), df[acqFieldName])
plt.show()

【讨论】:

  • 不。代码fig, ax = plt.subplots() ax.plot(dataFrame.set_index('TIMESTAMP'), dataFrame[acqFieldName]) 产生了一些奇怪的情节(见初始帖子的修正)
  • 你的意思可能是ax.plot(dataFrame['TIMESTAMP'], dataFrame[acqFieldName])`
  • @JohanC:不,我的意思是 dataFrame.set_index('TIMESTAMP') 就像 Zaraki 建议的那样。
  • 不,我想解释一下@Zaraki 可能意味着ax.plot(dataFrame['TIMESTAMP'], ...)
猜你喜欢
  • 1970-01-01
  • 2021-04-03
  • 1970-01-01
  • 2012-03-14
  • 2021-01-31
  • 2020-03-29
  • 1970-01-01
  • 2020-04-27
  • 2017-12-15
相关资源
最近更新 更多