【问题标题】:Addressing strange plotting results using pandas and dates使用 pandas 和日期解决奇怪的绘图结果
【发布时间】:2019-10-27 19:37:33
【问题描述】:

当使用日期绘制带有 pandas 的时间序列时,绘图完全错误,x 轴上的日期也是如此。由于某种原因,数据是针对日期绘制的,甚至不在数据框中。

这用于绘制具有独立时钟和不同采样频率的多个传感器。我想在同一图中绘制所有传感器进行比较。

我尝试按升序对数据框进行排序,并将日期时间列分配为数据框索引,但没有效果。相反,当根据时间戳绘制数据集时,每个传感器的图看起来都很好。

典型 CSV 文件的摘录:

    Timestamp Date Clock DC3 HR DC4
    13 18.02.2019 08:24:00  19,12   61  3
    14 18.02.2019 08:26:00  19,12   38  0
    15 18.02.2019 08:28:00  19,12   52  0
    16 18.02.2019 08:30:00  19,12   230 2
    17 18.02.2019 08:32:00  19,12   32  3

下面的代码给我带来了问题:

import pandas as pd
from scipy.signal import savgol_filter

columns = ['Timestamp', 'Date', 'Clock', 'DC3', 'HR', 'DC4']

data = pd.read_csv('Exampledata.DAT', 
               sep='\s|\t', 
               header=19, 
               names=columns, 
               parse_dates=[['Date', 'Clock']], 
               engine='python')

data['HR'] = savgol_filter(data['HR'], 201, 3) #Smoothing

ax = data.plot(x='Date_Clock', y='HR', label='Test')

预期的结果应该是这样的,只有沿 x 轴的日期:

实际结果是:

可在此处下载完整数据文件的示例: https://filesender.uninett.no/?s=download&token=ae8c71b5-2dcc-4fa9-977d-0fa315fedf45

如何解决这个问题?

【问题讨论】:

    标签: python pandas csv plot


    【解决方案1】:

    通过在加载文件时不使用 parse_dates 解决了这个问题,而是像这样创建日期时间向量:

    import pandas as pd
    from scipy.signal import savgol_filter
    
    columns = ['Timestamp', 'Date', 'Clock', 'DC3', 'HR', 'DC4']
    
    data = pd.read_csv('Exampledata.DAT', 
                   sep='\s|\t', 
                   header=19, 
                   names=columns, 
                   engine='python')
    
    data['Timestamp'] = pd.to_datetime(data['Date'] + data['Clock'], 
    format='%d.%m.%Y%H:%M:%S')
    
    data['HR'] = savgol_filter(data['HR'], 201, 3) #Smoothing
    
    ax = data.plot(x='Timestamp', y='HR', label='Test')
    

    这将创建以下情节:

    这是我想要的情节。

    【讨论】:

      【解决方案2】:

      你会得到一个奇怪的图表,因为 matplotlib 每行绘制一个点。如果您想要一个更易于阅读的图表,您可以使用 resample() 函数将您的条目分组为每天 1 个(或每周 1 个或每月 1 个,如果您愿意)。重采样时有两个主要选项,您可以选择取所有条目的总和,也可以取平均值。我决定随意取平均值。

      这是它的样子:

      #Loading in the csv file
      filename = 'data_test.xlsx'
      df1 = pd.read_excel(filename, sep=',', index_col=False, header =None)
      df1.columns =  ['to_delete', 'Timestamp', 'DC3', 'HR', 'DC4', 'DC5']
      df1.drop(columns = 'to_delete', inplace = True)
      df1['Timestamp'] = [datetime.strptime(x, '%d.%m.%Y %H:%M:%S') for x in df1['Timestamp']]
      
      # We put the timestamp in the index since it's needed by the resample function
      df1 = df1.set_index(["Timestamp"])
      # We resample to have one row per day
      df1 = df1.resample("1d").mean()
      
      #We plot the graph
      x = df1.plot(y='HR', label='Test')
      

      这是重新采样的图表:

      这里比较的是没有重采样的图:

      【讨论】:

      • 好的,谢谢。如果我理解正确,您的解决方案需要将数据集的分辨率从几分钟减少到几天,这在这种情况下是不够的。我会调查一下,看看它会把我带到哪里。
      • 由于您有几天的数据,并且每分钟都发生巨大变化,因此无法避免您在图表中看到的大幅跳跃。如果您仍想保持良好的分辨率,可以将重采样调整为每 10/30 分钟只取一个点
      • 问题已解决。我在上面发布了适合我的解决方案。再次感谢您的建议 :-)
      • 谢谢我没看过!但这也是一种平滑方法,您会在数据上失去一些精度。我对 savgol 过滤器了解不多,但你知道过滤器和重采样中使用的简单移动平均线有什么区别吗?
      • Savgol 过滤器将 n 阶多项式拟合到给定时间窗口内的数据。这具有平滑效果,但时间分辨率或采样频率保持不变。有关此过滤器的更多信息,请参阅:en.wikipedia.org/wiki/… 可在此处找到 scipy 文档:docs.scipy.org/doc/scipy-0.16.1/reference/generated/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      相关资源
      最近更新 更多