tallsamurai
tallsamurai

Reputation: 21

Plotly not loading chart correctly where matplotlib does

Hraph

When using plotly I do get this picture with some straight lines on the graph. I do not have the same when using matplotlib.

import pandas as pd
import numpy as np
import cufflinks as cf
from plotly.offline import plot
from datetime import datetime
import io
import requests

df = cf.datagen.lines()

src = "https://iss.moex.com/iss/engines/stock/markets/index/securities/RTSI/candles.csv?iss.only=history&interval=31&iss.reverse=true&from=1995-09-01&till=2019-12-28&iss.json=extended&callback=JSON_CALLBACK&lang=en&limit=100&start=0&sort_order=TRADEDATE&sort_order_desc=desc&_=1563185736134'"

r = requests.get(src)

df = pd.read_csv(io.StringIO(r.content.decode('utf-8')),
                             sep=';',
                             names=[
                                 'Open', 'Close', 'High', 'Low', 'Value',
                                 'Volume', 'Date', 'End'
                             ]).iloc[2:]

frame = {
    'Date': df['Date'].astype(np.datetime64),
    'Open': df['Open'].astype('float64'),
    'Close': df['Close'].astype('float64'),
    'High': df['High'].astype('float64'),
    'Low': df['Low'].astype('float64'),
    'Value': df['Value'].astype('float64'),
    'Volume': df['Volume'].astype('float64'),
}

df = pd.DataFrame(frame)

plot([{
    'x': df['Date'],
    'y': df[col],
    'name': col
}  for col in df.columns[1:]])


df.iplot()

Is this a bug with plotly or am I doinf something wrong?

Upvotes: 0

Views: 90

Answers (2)

rpanai
rpanai

Reputation: 13447

I see several small problems plus data is not sorted as stated by @JohanC. Then you should really use 2 yaxis as suggested by @JohanC Here is my full code with comments

import pandas as pd
import io
import requests
import plotly.graph_objects as go

# get Data
src = "https://iss.moex.com/iss/engines/stock/markets/index/securities/RTSI/candles.csv?iss.only=history&interval=31&iss.reverse=true&from=1995-09-01&till=2019-12-28&iss.json=extended&callback=JSON_CALLBACK&lang=en&limit=100&start=0&sort_order=TRADEDATE&sort_order_desc=desc&_=1563185736134'"

r = requests.get(src)

df = pd.read_csv(io.StringIO(r.content.decode('utf-8')),
                             sep=';',
                             names=[
                                 'Open', 'Close', 'High', 'Low', 'Value',
                                 'Volume', 'Date', 'End'
                             ]).iloc[2:]

# set Date as first column and drop End
df = df.set_index('Date')\
       .drop("End", axis=1)\
       .reset_index()

# change dtypes
df["Date"] = df["Date"].astype("M8[us]")
for col in df.columns[1:]:
    df[col] = df[col].astype(float)

# sort Date
df = df.sort_values("Date")\
       .reset_index(drop=True)

fig = go.Figure()
for col in df.columns[1:]:
    fig.add_trace(
        go.Scatter(x=df["Date"],
                   y=df[col],
                  name=col))
fig.show()

Upvotes: 0

JohanC
JohanC

Reputation: 80409

The principal problem is that the date values don't appear in sorted order. It is necessary to sort them explicitly.

Another problem is that the numbers in the 'Value' column have a complete different range than the others. To display them in the same plot, one could add a secondary y-axis.

As the 'Volume' column isn't filled in (containing only zeros), it can be left out.

Here is some sample code, skipping conversion steps which probably are unnecessary for the latest plotly versions:

import plotly.graph_objects as go
import pandas as pd

src = "https://...."
df = pd.read_csv(src,
                 sep=';',
                 names=[
                     'Open', 'Close', 'High', 'Low', 'Value',
                     'Volume', 'Date', 'End'
                 ]).iloc[2:]
df = df.sort_values(by='Date')

for col in df.columns:
    print(col, df[col].min(), df[col].max())

fig = go.Figure()
for col in ['Open', 'Close', 'High', 'Low', 'Value']:
    fig.add_trace(
        go.Scatter(
            x=df['Date'],
            y=df[col],
            name=col,
            yaxis='y1' if col == 'Value' else 'y2'
        ))
fig.update_layout(
    yaxis=dict(
        title="Price",
    ),
    yaxis2=dict(
        title="Volume",
        anchor="x",
        overlaying="y",
        side="right"
    ))
fig.show()

sample output

Upvotes: 1

Related Questions