簡體   English   中英

Plotly 在 x 軸上帶有 datetime.time() 和缺失值

[英]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()

我對它並不太滿意,但它適用於虛擬數據幀和完整數據幀。 在此處輸入圖像描述 在此處輸入圖像描述

  • 首先模擬具有您描述的特征的數據。 從 21:00 到 08:00 在不同的日期和不同的隨機刪除的分鍾
  • 現在整合這些數據。 已采取措施
    1. 通過外連接填充缺失的分鍾數到每個 dataframe 中的所有分鍾數
    2. 按時外連接兩個數據幀

這給出了一個不同的結構數據框:

位置_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_xData_y 已將datetimetime_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"}})

output

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM