【问题标题】:How to color area when x values are pandas time series当x值为熊猫时间序列时如何为区域着色
【发布时间】:2021-05-08 07:54:33
【问题描述】:

我有以下折线图,其中包含两个时间序列值和两条垂直线,我想为“FromGen”大于“ToCons”和两条垂直线外侧的区域着色。

start_date="2019-06-18"
end_date="2019-06-19"

x0='2019-06-18 9:00:00'
x1='2019-06-18 17:00:00'

x1= pd.to_datetime(x1, format="%Y-%m-%d", utc=True)
x2= pd.to_datetime(x2, format="%Y-%m-%d", utc=True)

zeit = (df['DateTime'] > start_date) & (df['DateTime'] <= end_date)
zeit = df.loc[zeit]

zeit.plot(figsize=(15,10),x="DateTime", y=["FromGen", "ToCons"])
plt.xlabel("Zeit") 
plt.ylabel("Wh")
legend = plt.legend(title="comp",
                    loc=1, fontsize='large', fancybox=True,  labels=['FromGen', 'ToCons'])
plt.axvline(x=x0, color='red')
plt.axvline(x=x1, color='red')

kde_x, kde_y = ax.lines[0].get_data()
ax.fill_between(kde_x, kde_y, where=(kde_x<x0) | (kde_x>x1) , 
                interpolate=True, color='#8FF536')
plt.show()

我已经发现最后几行的代码可能会有所帮助 - 但目前我正在努力解决这个错误:

'numpy.ndarray' 和 'str' 的实例之间不支持'

非常感谢!

编辑: 这就是我的代码目前的样子——如果我不将 df 转换为正确的 tz 一切都会完美。但是当我这样做时,绿色区域会移动。我想我在某处错过了时区转换,但找不到在哪里....

从日期时间导入日期时间 从 pytz 导入时区

df= pd.read_csv("filename.csv", error_bad_lines=False, sep=";") df['DateTime'] = pd.to_datetime(df['DateTime'], format="%Y-%m-%d", utc=True)

#df['DateTime'] = df['DateTime'].dt.tz_convert('Europe/Berlin') #没有这条线,效果很好!但是当我使用它时,彩色区域似乎位于错误的时区

start_date = "2019-06-18" end_date = "2019-06-19"

x0 = '2019-06-18 9:00:00' x1 = '2019-06-18 16:00:00'


zeit = df.loc[(df['DateTime'] > start_date) & (df['DateTime'] <= end_date)]

ax = zeit.plot(figsize=(15, 10), x="DateTime", y=["FromGen", "ToCons"])

ax.set_xlabel("Zeit") ax.set_ylabel("Wh") legend = ax.legend(title="comp",
                   loc='upper right', fontsize='large', fancybox=True, labels=['FromGen', 'ToCons']) ax.axvline(x=x0, color='red') ax.axvline(x=x1, color='red')

x0 = datetime_obj.replace(tzinfo=timezone('UTC'))

ax.fill_between(zeit['DateTime'].values, zeit['FromGen'], zeit['ToCons'],
                where=((zeit['FromGen'] > zeit['ToCons']) & ((zeit['DateTime'] <= x0) | (zeit['DateTime'] >=x1))),
                interpolate=False, color='#8FF536') plt.show()

【问题讨论】:

    标签: python pandas matplotlib


    【解决方案1】:

    在最新的 pandas 和 matplotlib 版本中,日期处理有了很大的发展。因此,引用旧帖子可能会产生误导。以下代码已使用 matplotlib 3.4.1 和 pandas 1.2.4 进行测试。

    问题的代码中有些奇怪的是,首先使用了x0x1,然后使用了x1x2,而没有给x2 赋值。

    plt.fill_between() 可以直接使用数字列。要使用 datatime 列,现在可以使用 ...['DateTime'].values。对于where 子句,要比较日期时间列,需要将x0 和x1 转换为pd.to_datetime(...)。由于我的示例中的日期时间值没有utc,因此在使用x0 = pd.to_datetime(..., utc=True) 时比较不起作用。

    另请注意,pandas 绘图 (zeit.plot(...)) 返回 matplotlib ax

    import matplotlib.pyplot as plt
    import pandas as pd
    import numpy as np
    
    start_date = "2019-06-18"
    end_date = "2019-06-19"
    
    x0 = '2019-06-18 9:00:00'
    x1 = '2019-06-18 17:00:00'
    
    N = 200
    df = pd.DataFrame({'DateTime': pd.date_range(start_date, freq='10min', periods=N),
                       'FromGen': 8 * np.exp(-(np.arange(N) - 80) ** 2 / 1000) + np.random.uniform(0, 0.4, N),
                       'ToCons': np.random.uniform(1, 1.5, N)})
    
    x0 = pd.to_datetime(x0, format="%Y-%m-%d")
    x1 = pd.to_datetime(x1, format="%Y-%m-%d")
    
    zeit = df.loc[(df['DateTime'] > start_date) & (df['DateTime'] <= end_date)]
    
    ax = zeit.plot(figsize=(15, 10), x="DateTime", y=["FromGen", "ToCons"])
    
    ax.set_xlabel("Zeit")
    ax.set_ylabel("Wh")
    legend = ax.legend(title="comp",
                       loc='upper right', fontsize='large', fancybox=True, labels=['FromGen', 'ToCons'])
    ax.axvline(x=x0, color='red')
    ax.axvline(x=x1, color='red')
    
    ax.fill_between(zeit['DateTime'].values, zeit['FromGen'], zeit['ToCons'],
                    where=(zeit['FromGen'] > zeit['ToCons']) & ((zeit['DateTime'] <= x0) | (zeit['DateTime'] >= x1)),
                    interpolate=False, color='#8FF536')
    plt.show()
    

    【讨论】:

    • 您能否指定我需要在哪里使用 pd.to_datetime(..., utc=True) ?这可以解决我关于时区的问题吗?
    • 如果你的日期时间有一个时区,你可能需要x0 = pd.to_datetime(x0, format="%Y-%m-%d", utc=True)。您对时区的确切问题是什么?您的数据框是如何创建的?
    • 我的 df 来自一个 csv 文件,我对这些数据做了很多工作,所以日期时间应该没问题。我已经尝试了很多差异。品种如:``` ax.fill_between(zeit['DateTime'].values, zeit['FromGen'], zeit['ToCons'], where=(zeit['FromGen'] > zeit['ToCons']) & ((zeit['DateTime'] = pd.to_datetime(x1 , format="%Y-%m-%d", utc=True))), interpolate=False, color='#8FF536') ``` 在这里你可以查看我的情节现在的样子:imagebanana.com/s/2079/Bn9Eu1Mg.html
    • cmets 并不是用来放置代码块的。最好将add 发送到您的问题帖子中。您的图像表明时代已经改变。如果您使用时区,则应在某处设置正确的时区 ([docs[(pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html)) 并且与读取数据帧时的时区相同。另请注意where=(...) 中的括号是错误的:| 需要组合在一起。
    • 好的,感谢您的建议我编辑了我的原始帖子。我希望现在括号应该没问题:)
    猜你喜欢
    • 1970-01-01
    • 2017-11-07
    • 2012-10-16
    • 2023-04-05
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2014-02-19
    • 2019-09-26
    相关资源
    最近更新 更多