Saya memiliki dua Dataframe berbeda yang berisi berbagai kolom: tanggal mulai & berakhir, Durasi ...

Saya ingin memplot data ke dalam Timelines (Gantt charts) menggunakan plotly express. Saya tahu cara menggunakan subplot namun saya ingin mereka pada grafik yang sama bukan gambar.

Inilah usaha saya:

'''

import plotly.graph_objs as go
import plotly.express as px

fig = px.timeline(chosen_data3, x_start="Start Date", x_end="End Date", y="new" )
fig2 = px.timeline(chosen_data4, x_start="Start Date", x_end="End Date", y="new", ax = fig )
fig2.show()

#Using graph_objs :

fig = go.Figure()

for (start, end, value, value2) in zip(chosen_data3["Start Date"], chosen_data3["End Date"], 
chosen_data3["Duration [Hours]"],chosen_data3["Hs [m]"] ):
   name = f"Towing : {start} to {end}"
   fig.add_trace(go.Scatter(x=[start, end], y=[value, value],mode='lines', name = name , marker = 
   dict(color = 'rgb(0,0,0)'), hoverinfo = 'all'))    

 for (start, end, value, value2) in zip(chosen_data4["Start Date"], chosen_data4["End Date"], chosen_data4["Duration [Hours]"], chosen_data4["Hs [m]"]):
name = f"Hook-Up :{start} to {end}"
fig.add_trace(go.Scatter(x=[start, end], y=[value, value],mode='lines', name = name, marker = dict(color = 'rgb(65,105,225)'), hoverinfo = 'all')) 

fig.show()

'''

Solusi dengan graph_objs benar namun yang menggunakan express tidak

EDIT: Contoh dua kerangka data saya:

enter image description here

Solusi menggunakan Graph objs :

enter image description here

Solusi yang saya coba adalah menggabungkan dua kerangka data & membuat kolom baru untuk membedakan setiap data, saya mendapatkan gambar berikut menggunakan garis waktu plotly express ketika Anda mengarahkan kursor ke setiap bilah Anda melihat semua informasi yang diperlukan:

enter image description here

1
Keyser Soze 29 April 2021, 17:34

1 menjawab

Jawaban Terbaik

Anda memiliki ide yang tepat: untuk mereproduksi gambar yang Anda buat dengan plotly graph_objects menggunakan plotly express, kami perlu membuat kolom baru untuk dua DataFrame Anda untuk menyimpan informasi yang harus Anda teruskan ke metode px.timeline. Kemudian kita dapat menggabungkan dua DataFrames dan meneruskan satu DataFrame gabungan ke px.timeline.

Kita dapat membuat kolom bernama legend_entry untuk menampung string yang ingin Anda tampilkan dalam legenda, dan meneruskannya ke parameter color dari px.timeline. Namun karena parameter warna juga digunakan untuk menetapkan warna ke batang, dan setiap entri_legenda yang Anda miliki akan unik, setiap batang akan memiliki warna yang berbeda — kita dapat menimpanya dengan meneruskan larik warna eksplisit untuk ditetapkan ke setiap batang ke parameter color_discrete_sequence. Untuk melakukan ini, kita dapat membuat kolom tambahan bernama color yang akan kita isi dengan 'black' atau 'blue' tergantung pada tugas penarik atau penyambungan.

Karena batang paling atas dan paling bawah akan berada tepat di tepi plot, kita dapat menambahkan beberapa bantalan dengan memperluas jangkauan sumbu y sebanyak yang Anda suka. Saya memilih 10.

import numpy as np
import pandas as pd
import plotly.express as px

## recreate your data
chosen_data3 = pd.DataFrame({
    "Start Date":['1999-03-06 05:00:00','1999-03-08 22:00:00','1999-03-12 22:00:00','1999-03-22 19:00:00'],
    "End Date":['1999-03-08 00:00:00','1999-03-12 19:00:00','1999-03-21 20:00:00','1999-03-26 03:00:00'],
    "Hs [m]":[1.804182,1.461362,1.825023,1.717531]
})

chosen_data4 = pd.DataFrame({
    "Start Date":['1999-03-09 06:00:00','1999-03-20 05:00:00'],
    "End Date":['1999-03-11 18:00:00','1999-03-21 10:00:00'],
    "Hs [m]":[1.209672,1.121267]
})

chosen_data3[['Start Date','End Date']] = chosen_data3[['Start Date','End Date']].apply(pd.to_datetime)
chosen_data4[['Start Date','End Date']] = chosen_data4[['Start Date','End Date']].apply(pd.to_datetime)

chosen_data3['Duration [Hours]'] = (chosen_data3['End Date'] - chosen_data3['Start Date']) / np.timedelta64(1, 'h')
chosen_data4['Duration [Hours]'] = (chosen_data4['End Date'] - chosen_data4['Start Date']) / np.timedelta64(1, 'h')

## add a new column with a string for the legend
chosen_data3['legend_entry'] = "Towing : " + chosen_data3['Start Date'].apply(str) + " to " + chosen_data3['End Date'].apply(str) 
chosen_data4['legend_entry'] = "Hook up : " + chosen_data4['Start Date'].apply(str) + " to " + chosen_data4['End Date'].apply(str)

## add a new column to specify the color of each bar
chosen_data3['color'] = 'black'
chosen_data4['color'] = 'blue'

## we can concatenate the data into one DataFrame so that we only need to use px.timeline once
df = pd.concat([chosen_data3, chosen_data4])

## pass an explicit array to the color_discrete_sequence 
fig = px.timeline(df, x_start="Start Date", x_end="End Date", y="Duration [Hours]", 
    color="legend_entry", color_discrete_sequence=df.color.values)

## add some padding so that the bottom and topmost bars aren't flush against the edge of the figure
y_axis_range_padding = 10
fig.update_layout(
    title="Towing & Hook up tasks in function of duration", title_x=0.5, 
    legend_title_text='', yaxis_range=[df['Duration [Hours]'].min() - y_axis_range_padding, df['Duration [Hours]'].max() + y_axis_range_padding]
    )
fig.show()

enter image description here

1
Derek O 3 Mei 2021, 07:11