Skip to content

Commit

Permalink
Add Table trace (#207)
Browse files Browse the repository at this point in the history
* Add `Table` trace
* update changelog

---------

Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com>
Co-authored-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com>
Co-authored-by: baiguoname <baiguo_nice@163.com>
Co-authored-by: kylemello <kylemello98@gmail.com>
  • Loading branch information
4 people committed Jun 19, 2024
1 parent 4815df7 commit 8713ad2
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [0.9.0] - 2024-xx-xx
### Added
- [[#207](https://github.com/plotly/plotly,rs/pull/207)] Add `Table` trace.
- [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature.
- [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`.
- [[#178](https://github.com/plotly/plotly.rs/pull/178)] Fix setter for `Axis::matches` to take string arg.
- [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles.
- [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`.
- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter.
Expand Down
14 changes: 13 additions & 1 deletion examples/basic_charts/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use plotly::{
},
layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder},
sankey::{Line as SankeyLine, Link, Node},
Bar, Plot, Sankey, Scatter, ScatterPolar,
traces::table::{Cells, Header},
Bar, Plot, Sankey, Scatter, ScatterPolar, Table,
};
use rand_distr::{Distribution, Normal, Uniform};

Expand Down Expand Up @@ -604,6 +605,16 @@ fn basic_sankey_diagram() {
plot.show();
}

fn table_chart() {
let trace = Table::new(
Header::new(vec![String::from("col1"), String::from("col2")]),
Cells::new(vec![vec![1, 2], vec![2, 3]]),
);
let mut plot = Plot::new();
plot.add_trace(trace);
plot.show();
}

fn main() {
// Uncomment any of these lines to display the example.

Expand All @@ -629,6 +640,7 @@ fn main() {
// basic_bar_chart();
// grouped_bar_chart();
// stacked_bar_chart();
// table_chart();

// Sankey Diagrams
// basic_sankey_diagram();
Expand Down
1 change: 1 addition & 0 deletions plotly/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ pub enum PlotType {
Sankey,
Surface,
DensityMapbox,
Table,
}

#[derive(Serialize, Clone, Debug)]
Expand Down
2 changes: 1 addition & 1 deletion plotly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use traces::{
// Bring the different trace types into the top-level scope
pub use traces::{
Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc,
Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface,
Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table,
};

pub trait Restyle: serde::Serialize {}
Expand Down
2 changes: 2 additions & 0 deletions plotly/src/traces/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod scatter3d;
pub mod scatter_mapbox;
mod scatter_polar;
pub mod surface;
pub mod table;

pub use bar::Bar;
pub use box_plot::BoxPlot;
Expand All @@ -32,5 +33,6 @@ pub use scatter3d::Scatter3D;
pub use scatter_mapbox::ScatterMapbox;
pub use scatter_polar::ScatterPolar;
pub use surface::Surface;
pub use table::Table;

pub use self::image::Image;
177 changes: 177 additions & 0 deletions plotly/src/traces/table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
//! Table trace

use plotly_derive::FieldSetter;
use serde::Serialize;

use crate::{
color::Color,
common::{Font, Line, PlotType, Visible},
Trace,
};

#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, FieldSetter)]
#[field_setter(box_self, kind = "trace")]
pub struct Table<T, N>
where
T: Serialize + Clone + 'static,
N: Serialize + Clone + 'static,
{
#[field_setter(default = "PlotType::Table")]
r#type: PlotType,
/// Sets the trace name. The trace name appear as the legend item and on
/// hover.
name: Option<String>,
#[serde(rename = "columnorder")]
/// Determines whether or not this trace is visible. If
/// `Visible::LegendOnly`, the trace is not drawn, but can appear as a
/// legend item (provided that the legend itself is visible).
visible: Option<Visible>,
///Specifies the rendered order of the data columns; for example, a value
/// `2` at position `0`, means that column index `0` in the data will be
/// rendered as the, third column, as columns have an index base of
/// zero.
column_order: Option<Vec<usize>>,
#[serde(rename = "columnwidth")]
///The width of columns expressed as a ratio. Columns fill the available
/// width, in proportion of their specified column widths.
column_width: Option<f64>,
///Header cell values. `values[m][n]` represents the value of the `n`th
/// point in column `m`,, therefore the `values[m]` vector length for
/// all columns must be the same (longer vectors, will be truncated).
/// Each value must be a finite number or a string.
header: Option<Header<T>>,
///Cell values. `values[m][n]` represents the value of the `n`th point in
/// column `m`,, therefore the `values[m]` vector length for all columns
/// must be the same (longer vectors, will be truncated). Each value
/// must be a finite number or a string.
cells: Option<Cells<N>>,
}

impl<T, N> Table<T, N>
where
T: Serialize + Clone + Default + 'static,
N: Serialize + Clone + Default + 'static,
{
pub fn new(header: Header<T>, cells: Cells<N>) -> Box<Self> {
Box::new(Table {
header: Some(header),
cells: Some(cells),
..Default::default()
})
}
}

impl<T, N> Trace for Table<T, N>
where
T: Serialize + Clone + 'static,
N: Serialize + Clone + 'static,
{
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, FieldSetter)]
pub struct Cells<N> {
///Cell values. `values[m][n]` represents the value of the `n`th point in
/// column `m`, therefore the `values[m]` vector length for all columns
/// must be the same (longer vectors, will be truncated). Each value
/// must be a finite number or a string
values: Option<Vec<Vec<N>>>,
///Prefix for cell values.
prefix: Option<String>,
///Suffix for cell values.
suffix: Option<String>,
height: Option<f64>,
align: Option<String>,
line: Option<Line>,
///Sets the cell fill color. It accepts either a specific color,
///or an array of colors or a 2D array of colors
fill: Option<Fill>,
font: Option<Font>,
}

impl<N> Cells<N>
where
N: Serialize + Clone + Default + 'static,
{
pub fn new(values: Vec<Vec<N>>) -> Self {
Cells {
values: Some(values),
..Default::default()
}
}
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, FieldSetter)]
pub struct Header<T> {
///Header cell values. `values[m][n]` represents the value of the `n`th
/// point in column `m`, therefore the `values[m]` vector length for all
/// columns must be the same (longer vectors, will be truncated). Each
/// value must be a finite number or a string.
values: Option<Vec<T>>,
///Prefix for cell values.
prefix: Option<String>,
///Suffix for cell values.
suffix: Option<String>,
height: Option<f64>,
align: Option<String>,
line: Option<Line>,
///Sets the cell fill color. It accepts either a specific color,
///or an array of colors or a 2D array of colors
fill: Option<Fill>,
font: Option<Font>,
}

impl<T> Header<T>
where
T: Serialize + Clone + Default + 'static,
{
pub fn new(values: Vec<T>) -> Self {
Header {
values: Some(values),
..Default::default()
}
}
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, FieldSetter)]
pub struct Fill {
color: Option<Box<dyn Color>>,
}

impl Fill {
pub fn new() -> Self {
Default::default()
}
}

#[cfg(test)]
mod tests {
use serde_json::{json, to_value};

use super::*;

#[test]
fn test_serialize_table() {
let columns = Header::new(vec![String::from("col1"), String::from("col2")]);
let values = Cells::new(vec![vec![1, 2], vec![2, 3]]);
let trace = Table::new(columns, values);

let expected = json!({
"type": "table",
"cells": {
"values": [[1, 2], [2, 3]],
},
"header": {
"values": ["col1", "col2"],
},
});

assert_eq!(to_value(trace).unwrap(), expected);
}
}

0 comments on commit 8713ad2

Please sign in to comment.