![](/img/trans.png)
[英]how to plot time series where x-axis is datetime.time object in matplotlib?
[英]Plotly with datetime.time() in the x-axis and missing values
我有 2 個 pandas 數據幀,df1 和 df2,它們都包含 21:00 到 8:00 之間 2 個不同日期的數據。 數據應該是每分鍾 1 個數據點,但是有缺失值,例如
location time Data
0 1 21:00:00 8
1 1 21:02:00 6
21:01:00 的數據點不存在。 對於每個數據幀,丟失的數據點發生在不同的時間,所以當我嘗試在同一個 plot 上嘗試 plot 時,會發生這種情況:
如果我單獨 plot 他們都是正確的。 我認為水平紅線是由紅色 dataframe 中存在的時間值引起的,而不是藍色 dataframe 中存在的時間值。
有沒有人遇到過這個? 我想 plot 兩個都在同一軸上,從 21:00 開始,到 08:00 結束。
這是我正在使用的代碼:
import pandas as pd
import plotly.express as px
df1 = pd.DataFrame({'location': 1,
'data': ['3', '4', '5'],
'time': [datetime.datetime(2022,7,16,21,0,0).time(),
datetime.datetime(2022,7,16,21,1,0).time(),
datetime.datetime(2022,7,16,21,3,0).time()]})
df2 = pd.DataFrame({'location': 2,
'data': ['8', '6', '7'],
'time': [datetime.datetime(2022,7,17,21,0,0).time(),
datetime.datetime(2022,7,17,21,2,0).time(),
datetime.datetime(2022,7,17,21,3,0).time()]})
df = pd.concat([df1,df2], axis=0)
fig = px.line(df, x="time", y="data", color='location')
fig.show()
謝謝!
問題在於時間列。 當您將其轉換為time()
時,當您組合數據幀時,它將轉換為 object。 檢查df.info()
。 為避免這種情況,請將數據保留為日期時間格式並使用update_axis()
讓px
設置時間。 下面更新代碼...
import pandas as pd
import plotly.express as px
df1 = pd.DataFrame({'location': 1,
'data': ['3', '4', '5'],
'time': [datetime.datetime(2022,7,16,21,0,0),
datetime.datetime(2022,7,16,21,1,0),
datetime.datetime(2022,7,16,21,3,0)]})
df2 = pd.DataFrame({'location': 2,
'data': ['8', '6', '7'],
'time': [datetime.datetime(2022,7,16,21,0,0),
datetime.datetime(2022,7,16,21,2,0),
datetime.datetime(2022,7,16,21,3,0)]})
df = pd.concat([df1,df2], axis=0)
fig = px.line(df, x="time", y="data", color='location')
fig.update_xaxes(tickformat="%H:%M:%S")
fig.show()
Plot
感謝您的幫助@Redox,它非常有幫助,但不幸的是,在使用完整數據集時,它並沒有像我想要的那樣工作。 這是等效的結果:
## Note that you need to use .time()
df1 = pd.DataFrame({'location': 1, 'data': ['3', '4', '5'],
'time': [datetime.datetime(2022,7,17,21,0,0).time(),
datetime.datetime(2022,7,17,21,1,0).time(),
datetime.datetime(2022,7,17,21,3,0).time()]})
df2 = pd.DataFrame({'location': 2, 'data': ['8', '6', '7'],
'time': [datetime.datetime(2022,7,16,21,0,0).time(),
datetime.datetime(2022,7,16,21,2,0).time(),
datetime.datetime(2022,7,16,21,3,0).time()]})
df = pd.concat([df1,df2], axis=0)
date = str(datetime.datetime.strptime('2022-01-01', '%Y-%m-%d').date()) ##Random dummy date
df['time'] = pd.to_datetime(date + " " + df['time'].astype(str)) ##Convert back to datetime
fig = px.line(df, x="time", y="data", color='location')
fig.update_xaxes(tickformat="%H:%M")
fig.show()
當我嘗試這個時:
dt = datetime.datetime.strptime('2022-01-01', '%Y-%m-%d')
starttime = dt.replace(hour=21, minute=0) ## Start time is 9PM
dt = datetime.datetime.strptime('2022-01-02', '%Y-%m-%d')
endtime = dt.replace(hour=8, minute=0) ## End time is 8AM next day
fig = px.line(df, x="time", y="data", color='location', range_x=[starttime, endtime])
以下是最終對我有用的方法:
df1 = pd.DataFrame({'location': 1, 'data': ['3', '4', '5'],
'time_num': [datetime.datetime(2022,7,17,21,0,0).time().hour + datetime.datetime(2022,7,17,21,0,0).time().minute/60,
datetime.datetime(2022,7,17,21,1,0).time().hour + datetime.datetime(2022,7,17,21,0,0).time().minute/60,
datetime.datetime(2022,7,17,21,3,0).time().hour + datetime.datetime(2022,7,17,21,0,0).time().minute/60, ]})
df2 = pd.DataFrame({'location': 2, 'data': ['8', '6', '7'],
'time_num': [datetime.datetime(2022,7,16,21,0,0).time().hour + datetime.datetime(2022,7,16,21,0,0).time().minute/60,
datetime.datetime(2022,7,16,21,2,0).time().hour + datetime.datetime(2022,7,16,21,2,0).time().minute/60,
datetime.datetime(2022,7,16,21,3,0).time().hour + datetime.datetime(2022,7,16,21,3,0).time().minute/60]})
df_skeleton = pd.DataFrame()
df_skeleton['date'] = pd.date_range(datetime.datetime(2022,7,16,20,0,0), datetime.datetime(2022,7,17,8,0,0), freq = '1min')
df_skeleton['time']=df_test['date'].dt.strftime('%H:%M:%S')
df_skeleton['hour']=df_test['date'].dt.strftime('%H')
df_skeleton['min']=df_test['date'].dt.strftime('%M')
df_skeleton[['hour', 'min']] = df_test[['hour', 'min']].astype(int)
df_skeleton['time_num'] = df_test['hour'] + df_test['min']/60
result_1 = pd.merge(df_skeleton, df1, how="left", on=["time_num", "time_num"])
result_2 = pd.merge(df_skeleton, df2, how="left", on=["time_num", "time_num"])
result_1['location'] = '1'
fig = px.line(result_1, x='time', y='data',color='location')
fig.add_scatter(x=result_2['time'], y=result_2['data'],mode='lines', name='2')
fig.update_traces(connectgaps=True)
fig.show()
這給出了一個不同的結構數據框:
位置_x | 時間_x | 數據_x | 噸 | location_y | time_y | 數據_y | |
---|---|---|---|---|---|---|---|
0 | 1 | 2022-09-01 21:00:00 | 0 | 21:00:00 | 2 | 2022-09-04 21:00:00 | 1 |
1 | 1 | 2022-09-01 21:01:00 | 0.0302984 | 21:01:00 | 2 | 2022-09-04 21:01:00 | 0.999541 |
2 | 1 | 2022-09-01 21:02:00 | 0.060569 | 21:02:00 | 2 | 2022-09-04 21:02:00 | 0.998164 |
3 | 1 | 2022-09-01 21:03:00 | 0.0907839 | 21:03:00 | 2 | 2022-09-04 21:03:00 | 0.995871 |
4 | 1 | 2022-09-01 21:04:00 | 0.120916 | 21:04:00 | 2 | 2022-09-04 21:04:00 | 楠 |
然后很容易從中生成一個px.line()
圖形。 跟蹤是Data_x和Data_y 。 已將datetime列time_x用於xaxis 。 這樣就可以很好地集成日期時間和連續軸。 更新tickformat
,因此軸的日期部分不顯示。
import pandas as pd
import numpy as np
import plotly.express as px
dr = pd.date_range("2022-09-01 21:00", "2022-09-02 08:00", freq="1Min")
# data to match question, two dataframes from 21:00 to 08:00, different dates with some holes
# with different dates
dfs = [
pd.DataFrame(
{
"location": np.full(len(dr), l),
"time": dr + pd.DateOffset(days=o),
"Data": f(np.linspace(0, 20, len(dr))),
}
)
.sample(frac=0.95)
.sort_index()
for l, o, f in zip([1, 2], [0, 3], [np.sin, np.cos])
]
df1 = dfs[0]
df2 = dfs[1]
# let's integrate the dataframes
# 1. fill the holes in each dataframe by doing an outer join to all times
# 2. outer join the two dataframes on just the time
df = pd.merge(
*[
pd.merge(
d,
pd.DataFrame(
{"time": pd.date_range(d["time"].min(), d["time"].max(), freq="1min")}
),
on="time",
how="outer",
)
.fillna({"location": l})
.assign(t=lambda d: d["time"].dt.time)
for d, l in zip([df1, df2], [1, 2])
],
on="t",
how="outer",
)
# finally generate plotly line chart using columns created by merging the data
# it's clearly observed there are gaps in both traces
px.line(
df.sort_values("time_x"), x="time_x", y=["Data_x", "Data_y"], hover_data=["time_y"]
).update_layout({"xaxis": {"tickformat": "%H:%M"}})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.