ploting a "timetable" with grouped bars for defined hours/timeboxes - python

I want to track my mobile devices at home so I can plot a "at home" and "not at home" diagram.
I collect the data as follows:
ip,device_name,start,end,length,date
192.168.178.123,aaa,2022-04-16 00:33:01.395443,2022-04-16 00:37:06.843443
192.168.178.123,aaa,2022-04-16 08:55:24.911787,2022-04-16 08:56:39.197196
192.168.178.123,aaa,2022-04-20 21:49:25.660712,2022-04-20 21:50:25.660712
192.168.178.123,aaa,2022-04-24 14:42:14.781557,2022-04-24 14:44:56.519343
192.168.178.234,bbb,2022-04-16 08:22:37.763442,2022-04-16 08:23:37.763442
192.168.178.234,bbb,2022-04-16 10:05:09.613899,2022-04-16 10:06:09.613899
Each entry of my csv-File represents the status of a device being not at home.
I want to have a diagram as shown
I can't figure out how to do this in plotly. I tried to find a way using time series (https://plotly.com/python/time-series/) but I think there is nothing that helps me to do what I want.
This code brings me to an output which is quite near to what I want but I can not bring the y-axis to hours and show the gaps.
data_frame = pd.read_csv("awaytimes.csv", parse_dates=['start', 'end'])
data_frame['length'] = (data_frame['end'] - data_frame['start']) / pd.Timedelta(hours=1)
fig = px.bar(data_frame,
x="date",
y="length",
color='device_name',
barmode='group',
height=400)
fig.show()
I hope one of you can give me a hint.

Related

Plotting a map using Geoview and using size/ colour option

I'm trying to visualize a dataset which I've filtered down to just longitude/latitude, country name, year and a count of deaths. I'm trying to plot that using geoviews as I wish to add lot more to my dataset and interactive map would be a great add on
My code is as follows: (for_plot is the dataframe)
# Plotting the graph
Best = gv.Dataset(for_plot)
points = Best.to(gv.Points, ['longitude', 'latitude'], ['deaths', 'country'])
(gts.Wikipedia * points).opts(
opts.Points(width=600, height=350, tools=['hover'],
size='deaths', cmap='viridis'))
This creates a perfect graph put the 'size' function doesn't work. If I change size to color, graph is not generated. I'm okay with either but just need atleast one marker.
Thanks for any help
Tried to switch values for color instead of size, works with year but not deaths

Plotly express animations: Plotting multiple changing traces and background image for each frame

I am currently trying to create a debugging tool for a simulation. For this is am working with the animations of plotly express. What I want to achieve:
An animation with a different background image with different traces (also differing in number) for each frame. Any help would be very much appreciated! (Also if someone knows how to do this using any other library it'd be very much appreciated!)
Thanks!
Adding the background images work perfectly well like this:
fig = px.imshow(img,origin="upper", animation_frame=0, binary_string=True, labels=dict(animation_frame="slice"))
So I only need to figure out how to display the traces.
I tried the following first:
fig = px.imshow(img,origin="upper", animation_frame=0, binary_string=True, labels=dict(animation_frame="slice")) # img consists of |time_step| images (np.array)
## now I'm trying to add the traces
for i in range(len(img)):
time_step = df.iloc[i]
for j in range(len(time_step)):
current = time_step.iloc[j]
x, y = current["x"], current["y"]
if (not current["valid"]):
fig.add_trace(go.Scatter(x=x, y=y, name="{}".format(current["unique_id"]), text="{}".format(current["costs"]), hoverinfo='text+name', line=dict(color="black", dash="dot"), line_shape="spline"))
else:
fig.add_traces(go.Scatter(x=x_list, y=y_list, line=dict(color="black"), line_shape="spline"))
fig.show()
However, I realized that fig.add_trace always adds the trace to all frames of the animation. (When only displaying the first time step it worked though :) )
However, I'd like to add the traces for one time_step only and then the ones for the next time_step.
So I started looking into this approach:
# saving in a list instead of printing immediately
if (not current["feasible"]):
info.append([x_list, y_list, "{}".format(current["unique_id"]),
"{}".format(current["costs"]), dict(color=color, dash="dot")])
else:
info.append([x_list, y_list, "{}".format(current["unique_id"]),
"{}".format(current["costs"]),dict(color=color)])
and added the information to the single frames:
frames.append(
go.Frame(
data=[go.Scatter(
x=information[0],
y=information[1],
name=information[2],
text=information[3],
hoverinfo='text+name',
line=information[4],
line_shape="spline"
)
for information in info],
)
)
figa = go.Figure(data=fig.data, frames=frames, layout=fig.layout)
figa.show()
But it only displays the first background image and once I start the animation it disappears and only shows the first saved Scatter for each time_step.
I'm a little lost as I don't have a set number of traces I can't "hardcode" the Scatters.

Plotting data from dataframe column using matplotlib- specific start index and number of datapoints

https://archive.ics.uci.edu/ml/machine-learning-databases/00374/energydata_complete.csv
I have this data set that shows energy data logged every 10 minutes for 4.5 months in Chievres, Belgium.
I am only interested in displaying the ‘date’, ‘Appliances’, ‘lights’, and ‘T_out’ in a dataframe. The relevant code is below.
df=pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/00374/energydata_complete.csv')
df=df.iloc[:,[0,1,2,21]]
df.head(5)
(I'd show the df but I'm new to SO and don't know how to include output in a question, sorry :) )
I'd like to create a plot using matplotlib that shows only the lights data for 4 days to see if there is a correlation between daytime and nighttime energy usage. I want to start with ‘2016-01-12 06:00:00’ am to have an accurate representation of a day.
I know that the data for one day is equal to 144 data points since each point is recorded every 10 minutes, so for four days it is 576 data points.
fig = plt.figure()
fig.plot(df['lights'])
This is literally the only code I have so far and I know it isn't even remotely correct lol.
How can I graph the relevant data from the 'lights' column in the dataframe and limit the plot to 576 data points?
Update: The following code works although if I am being perfectly honest I am not sure why or how
fig,axes=plt.subplots(1,1)
lights= df[df['date']=='2016-01-12 06:00:00'].index[0]
axes.plot(df.iloc[lights:lights+144*4,0], df.iloc[lights:lights+144*4,2], color='g', alpha=0.5)
xticks=np.arange(0,144*4,36)
I don't really understand the parameters of the df.iloc[] function

Increasing speed on plotly animation

I created a choropleth map using plotly express's function choropleth() Code is below.
fig = px.choropleth(df_countrydate,
locations="Country",
locationmode = "country names",
color="Confirmed",
hover_name="Country",
animation_frame="Date",
color_continuous_scale="Reds"
)
fig.update_layout(
title_text = 'Global Spread of Coronavirus',
title_x = 0.5,
geo=dict(
showframe = False,
showcoastlines = False,
))
iplot(fig)
It's a dynamic map and I was wondering if there was anyway I could speed up the transitions from one date to the next when I hit play.
Change these 2 parameters in your plot:
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 30
fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 5
Time is in milliseconds
I got the answer from the code of this video: https://www.youtube.com/watch?v=RCUrpCpGZ5o&t=1156s&ab_channel=CharmingData
You can find the whole code here: https://github.com/Coding-with-Adam/Dash-by-Plotly/blob/master/Plotly_Graphs/Animated_Scatter/gender_ineq.py
I also found that the resolution of the map (110 vs 50) really impacts the refresh rate of the animation. In my project displaying the evolution of a variable was more relevant than the detail, since my intention was presenting the change over time of said variable. I considered it was less likely for users to try to zoom in the map, so I decided to use the lower resolution map (1:110m vs 1:50m):
fig.update_geos(projection_type="equirectangular", visible=True, resolution=110)
All those options combined resulted in a fast and smooth animation for my map after lowering the frame and animation duration.
With resolution=50, I couldn't see any effect when changing the duration values.

Adding X-Y offsets to data points

I'm looking for a way to specify an X-Y offset to plotted data points. I'm just getting into Altair, so please bear with me.
The situation: I have a dataset recording daily measurements for 30 people. Every person can register several different types of measurements every day.
Example dataset & plot, with 2 people and 2 measurement types:
import pandas as pd
df = pd.DataFrame.from_dict({"date": pd.to_datetime(pd.date_range("2019-12-01", periods=5).repeat(4)),
"person": pd.np.tile(["Bob", "Amy"], 10),
"measurement_type": pd.np.tile(["score_a", "score_a", "score_b", "score_b"], 5),
"value": 20.0*np.random.random(size=20)})
import altair as alt
alt.Chart(df, width=600, height=100) \
.mark_circle(size=150) \
.encode(x = "date",
y = "person",
color = alt.Color("value"))
This gives me this graph:
In the example above, the 2 measurement types are plotted on top of each other. I would like to add an offset to the circles depending on the "measurement_type" column, so that they can all be made visible around the date-person location in the graph.
Here's a mockup of what I want to achieve:
I've been searching the docs but haven't figured out how to do this - been experimenting with the "stack" option, with the dx and dy options, ...
I have a feeling this should just be another encoding channel (offset or alike), but that doesn't exist.
Can anyone point me in the right direction?
There is currently no concept of an offset encoding in Altair, so the best approach to this will be to combine a column encoding with a y encoding, similar to the Grouped Bar Chart example in Altair's documentation:
alt.Chart(df,
width=600, height=100
).mark_circle(
size=150
).encode(
x = "date",
row='person',
y = "measurement_type",
color = alt.Color("value")
)
You can then fine-tune the look of the result using standard chart configuration settings:
alt.Chart(df,
width=600, height=alt.Step(25)
).mark_circle(
size=150
).encode(
x = "date",
row='person',
y = alt.Y("measurement_type", title=None),
color = alt.Color("value")
).configure_facet(
spacing=10
).configure_view(
strokeOpacity=0
)
Well I don't know what result you are getting up until know, but maybe write a function whith parameters likedef chart(DotsOnXAxis, FirstDotsOnYAxis, SecondDotsOnYAxis, OffsetAmount)
and then put those variables on the right place.
If you want an offset with the dots maybe put in a system like: SecondDotsOnYAxis = FirstDotsOnYAxis + OffsetAmount

Categories