How to export/save an animated bubble chart made with plotly?

How to export/save an animated bubble chart made with plotly? (For instance, the one was made following the link below) I would like to have it in a gift or some format with better resolution. Thank you in advance.

https://www.kaggle.com/aashita/guide-to-animated-bubble-charts-using-plotly

Upvotes: 7

Views: 17392

Answers (4)

jackomak
jackomak

Reputation: 11

Just thought I would post the solution I found to this problem that I think might be a little easier depending on your circumstances. This Solution worked for me and only uses the Pillow external library.

import PIL.Image
import io
import plotly.express as px

# Generate your animated plot.
plot = px.bar(data_frame=your_data, x=your_x, y=your_y, animation_frame=your_af)

# Save each plot frame to a list that is used to generate the .gif file. 
frames = []
for slider_pos, frame in enumerate(plot.frames):
    plot.update(data=frame.data)
    plot.layout.sliders[0].update(active=slider_pos)
    frames.append(PIL.Image.open(io.BytesIO(plot.to_image(format="png"))))
    
# Create the gif file.
frames[0].save("out_dir",
               save_all=True,
               append_images=frames[1:],
               optimize=True,
               duration=1000,
               loop=0)

The loop state of the gif can be controlled with the loop argument - 0 implies it will repeat infinitely. The duration argument implies the number of milliseconds between frames.

Upvotes: 1

Rob Raymond
Rob Raymond

Reputation: 31166

Building on answers already provided. This generates an animated GIF from an plotly figure that has frames (is animated)

  • start by generating some test data
  • generate an animated figure using plotly express
  • create an image for each frame in plotly figure
  • finally generate animated GIF from list of images
import plotly.express as px
import pandas as pd
import numpy as np
import io
import PIL

r = np.random.RandomState(42)

# sample data
df = pd.DataFrame(
    {
        "step": np.repeat(np.arange(0, 8), 10),
        "x": np.tile(np.linspace(0, 9, 10), 8),
        "y": r.uniform(0, 5, 80),
    }
)

# smaple plotly animated figure
fig = px.bar(df, x="x", y="y", animation_frame="step")

# generate images for each step in animation
frames = []
for s, fr in enumerate(fig.frames):
    # set main traces to appropriate traces within plotly frame
    fig.update(data=fr.data)
    # move slider to correct place
    fig.layout.sliders[0].update(active=s)
    # generate image of current state
    frames.append(PIL.Image.open(io.BytesIO(fig.to_image(format="png"))))
    
# create animated GIF
frames[0].save(
        "test.gif",
        save_all=True,
        append_images=frames[1:],
        optimize=True,
        duration=500,
        loop=0,
    )

enter image description here

Upvotes: 6

Mike_H
Mike_H

Reputation: 1455

There is no possibility to do this in plotly. Please use gifmaker and save every step in the animation as a single picture to later combine them to a gif. Follow this source. Further explanation on how to create animations is provided by plotly here.

The basic way to go would be to integrate this logic into the animation process of your plotly code:

 import ImageSequence
 import Image
 import gifmaker
 sequence = []

 im = Image.open(....)

 # im is your original image
 frames = [frame.copy() for frame in ImageSequence.Iterator(im)]

 # write GIF animation
 fp = open("out.gif", "wb")
 gifmaker.makedelta(fp, frames)
 fp.close()

If you could provide your actual code, it would be possible to provide a more detailled answer to your question. :)

Upvotes: 9

Manuel Montoya
Manuel Montoya

Reputation: 1446

Another possibility is to use the gif library, which works with matplolib, altair and plotly, and is really straight forward. In this case you would not use a plotly animation. Instead, you define a function that returns a plotly fig and construct a list of figs to pass to gif as an argument.

Your code would look something like this:

import random
import plotly.graph_objects as go
import pandas as pd
import gif

# Pandas DataFrame with random data
df = pd.DataFrame({
    't': list(range(10)) * 10,
    'x': [random.randint(0, 100) for _ in range(100)],
    'y': [random.randint(0, 100) for _ in range(100)]
})

# Gif function definition
@gif.frame
def plot(i):
    d = df[df['t'] == i]
    fig = go.Figure()
    fig.add_trace(go.Scatter(
        x=d["x"],
        y=d["y"],
        mode="markers"
    ))
    fig.update_layout(width=500, height=300)
    return fig

# Construct list of frames
frames = []
for i in range(10):
    frame = plot(i)
    frames.append(frame)

# Save gif from frames with a specific duration for each frame in ms
gif.save(frames, 'example.gif', duration=100)

Upvotes: 5

Related Questions