简体   繁体   中英

Converting this Bokeh plot to JavaScript?

I asked this question a few weeks ago about making a graph like this in Python, and got a couple ideas from the answer there. Basically, I'm trying to make a interactive web chart. It's supposed to be a bunch of points connected by line segments (a connected scatterplot, of sorts). Each point has two corresponding axes labels - one that's a box with some text, and one below that which has a number (this number is also what is plotted in that "column" on the chart)

I decided on trying to make my plot using the Python library Bokeh. Here's where I'm at so far:

import bokeh.io
from bokeh.resources import INLINE
from bokeh.embed import components
from bokeh.models.tools import HoverTool
from bokeh.models import CategoricalAxis, FactorRange
from bokeh.plotting import figure, output_file, show, output_notebook

x = ['label1', 'label2', 'label3', 'label4', 'label5', 'label6', 'label7', 'label8']
y = [1.1, 2.2, 1.8, 4.0, 1.0, 2.8, 3.6, 1.7]
p = figure(x_range=[*x], y_range=(0, 5), plot_height=500)
# dotted line graph is constructed of a circle glyph and a line glyph together
dots = p.circle(x=x, y=y, color='black', size=10)
line = p.line(x=x, y=y, color='black')

numbers = ['1.1', '2.2', '1.8', '4.0', '1.0', '2.8', '3.6', '1.7']
p.extra_x_ranges = {"extra_numbers": FactorRange(factors=numbers)}
p.add_layout(CategoricalAxis(x_range_name="extra_numbers"), 'below')
p.toolbar.logo = None
show(p)

在此处输入图像描述

My apologies about the image resolution.

As you can see, the actual plot is a pretty good approximation of what I was aiming for, but the axes don't look good at all. Unfortunately, it seems like multi-line axes support is pretty hard in Bokeh, and the difficulty in adding styling to the two x-axes is making me think I should switch my approach.

I see three possibilities moving forward:

  1. Try to create a template of the graph in JS, and add the plot into that template. In other words, create the bottom two rows of boxes and the y-axis legend in JS, create a connected scatterplot in Bokeh, and place that scatterplot into the JS template.

  2. Recreate this chart in a JS plotting library, like D3.js. This seems like the best long-term solution.

  3. Try to figure it out in Bokeh or some other Python library (I'm a pretty inexperienced dev, but this doesn't seem like it's gonna happen).

I am not super familiar with JS - it'd be great if someone could give me some skeleton code for what this might look like if JavaScript is needed. Any suggestions or ideas would be greatly appreciated.

If you're not familiar with JS, d3.js may be a little overwhelming.

I personally use highcharts: https://www.highcharts.com/demo

You can just find a template and put your data inside, it's also possible to pass the data from python dict to json so that highcharts can render the plot easily, you can forget the front-end and graphical part completely.

Here's a similar graph as yours using basic line chart template: https://jsfiddle.net/gpv93e4j/1/

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<figure class="highcharts-figure">
    <div id="container"></div>
    <p class="highcharts-description">
        Basic line chart showing trends in a dataset. This chart includes the
        <code>series-label</code> module, which adds a label to each line for
        enhanced readability.
    </p>
</figure>

.highcharts-figure, .highcharts-data-table table {
    min-width: 360px; 
    max-width: 800px;
    margin: 1em auto;
}

.highcharts-data-table table {
    font-family: Verdana, sans-serif;
    border-collapse: collapse;
    border: 1px solid #EBEBEB;
    margin: 10px auto;
    text-align: center;
    width: 100%;
    max-width: 500px;
}
.highcharts-data-table caption {
    padding: 1em 0;
    font-size: 1.2em;
    color: #555;
}
.highcharts-data-table th {
    font-weight: 600;
    padding: 0.5em;
}
.highcharts-data-table td, .highcharts-data-table th, .highcharts-data-table caption {
    padding: 0.5em;
}
.highcharts-data-table thead tr, .highcharts-data-table tr:nth-child(even) {
    background: #f8f8f8;
}
.highcharts-data-table tr:hover {
    background: #f1f7ff;
}

Highcharts.chart('container', {

    title: {
        text: 'title'
    },

    subtitle: {
        text: 'dummy'
    },

    yAxis: {
        title: {
            text: 'y'
        }
    },

    xAxis: [{

        'categories': ['label1', 'label2', 'label3', 'label4', 'label5', 'label6', 'label7', 'label8']
    },
       {
        'categories': ['1.1', '2.2', '1.8', '4.0', '1.0', '2.8', '3.6', '1.7'],
        'linkedTo': 0
       }
    ],

    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle'
    },



    series: [{
        data: [1.1, 2.2, 1.8, 4.0, 1.0, 2.8, 3.6, 1.7]
    }],

    responsive: {
        rules: [{
            condition: {
                maxWidth: 500
            },
            chartOptions: {
                legend: {
                    layout: 'horizontal',
                    align: 'center',
                    verticalAlign: 'bottom'
                }
            }
        }]
    }

});

NB: I only needed to change the Highcharts.chart part.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM