{"id":16176105,"url":"https://github.com/piotr-kalanski/splot","last_synced_at":"2025-03-19T01:30:37.017Z","repository":{"id":57722110,"uuid":"88076360","full_name":"piotr-kalanski/SPlot","owner":"piotr-kalanski","description":"Scala library for data visualization.","archived":false,"fork":false,"pushed_at":"2017-04-28T23:28:51.000Z","size":1043,"stargazers_count":10,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"development","last_synced_at":"2025-03-17T01:35:03.623Z","etag":null,"topics":["chart","charts","data-visualization","plot","plots","plotting","scala","scala-library","visualization"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piotr-kalanski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-12T17:01:43.000Z","updated_at":"2024-05-15T20:11:09.000Z","dependencies_parsed_at":"2022-08-29T23:00:35.127Z","dependency_job_id":null,"html_url":"https://github.com/piotr-kalanski/SPlot","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-kalanski%2FSPlot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-kalanski%2FSPlot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-kalanski%2FSPlot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-kalanski%2FSPlot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piotr-kalanski","download_url":"https://codeload.github.com/piotr-kalanski/SPlot/tar.gz/refs/heads/development","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244336094,"owners_count":20436766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chart","charts","data-visualization","plot","plots","plotting","scala","scala-library","visualization"],"created_at":"2024-10-10T04:47:40.799Z","updated_at":"2025-03-19T01:30:36.718Z","avatar_url":"https://github.com/piotr-kalanski.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SPlot\n\nSPlot is Scala library for data visualization.\n\n[![Build Status](https://api.travis-ci.org/piotr-kalanski/SPlot.png?branch=development)](https://api.travis-ci.org/piotr-kalanski/SPlot.png?branch=development)\n[![codecov.io](http://codecov.io/github/piotr-kalanski/SPlot/coverage.svg?branch=development)](http://codecov.io/github/piotr-kalanski/SPlot/coverage.svg?branch=development)\n[\u003cimg src=\"https://img.shields.io/maven-central/v/com.github.piotr-kalanski/splot.svg?label=latest%20release\"/\u003e](http://search.maven.org/#search|ga|1|a%3A%22splot%22)\n[![License](http://img.shields.io/:license-Apache%202-red.svg)](http://www.apache.org/licenses/LICENSE-2.0.txt)\n\n# Table of contents\n\n- [Goals](#goals)\n- [Getting started](#getting-started)\n- [API possibilities](#api-possibilities)\n- [Supported charts](#supported-charts)\n- [Multiple charts](#multiple-charts)\n- [Aggregation functions](#aggregation-functions)\n- [Saving plot to file](#saving-plot-to-file)\n- [Customizations](#customizations)\n\n# Goals\n\n- Provide simple API in Scala for data visualization similar to ggplot (http://ggplot2.org/) and Seaborn (https://seaborn.pydata.org/)\n- Support exploratory data analysis\n\nCurrently project is **NOT** focused on:\n\n- Performance\n- Rich possibilities for customization\n\n# Getting started\n\nInclude dependency:\n\n```scala\n\"com.github.piotr-kalanski\" % \"splot\" % \"0.2.0\"\n```\n\nor\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.piotr-kalanski\u003c/groupId\u003e\n    \u003cartifactId\u003esplot\u003c/artifactId\u003e\n    \u003cversion\u003e0.2.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nImport implicits, which adds methods to Scala collection enabling plotting:\n```scala\nimport com.datawizards.splot.api.implicits._\n```\n\n## Basic example\n\nTo plot bar chart using Scala sequence you need to call one method:\n```scala\nimport com.datawizards.splot.api.implicits._\n\nSeq(1.0, 4.0, 9.0).plotBar()\n```\n\n![](images/basic_bar.png)\n\n# API possibilities\n\nSPlot provides two API's for displaying plots:\n\n## Additional methods on collections\n\nFirst API enrich Scala collections providing additional methods for plotting charts.\n\nExamples:\n\n```scala\nval data = Seq((1,1),(2,2))\n\n// Plot bar chart:\ndata.plotBar()\n\n// Plot line chart:\ndata.plotLine()\n\n// Plot scatter chart:\ndata.plotScatter()\n\n// Start building plot:\ndata.buildPlot()\n```\n\n## Providing independently axis values\n\nSecond API provides possibility to independently provide x and y values.\n\nExamples:\n\n```scala\n\n// Plot bar chart:\nSPlot.plotBar(Seq(1,2), Seq(1,4))\n\n// Plot line chart:\nSPlot.plotLine(Seq(1,2), Seq(1,4))\n\n// Plot scatter chart:\nSPlot.plotScatter(Seq(1,2), Seq(1,4))\n\n// Start building plot:\nSPlot.buildPlot(Seq(1,2), Seq(1,4))\n```\n\n# Supported charts\n\n- [Bar](#bar)\n- [Scatter](#scatter)\n- [Line](#line)\n- [Histogram](#histogram)\n- [Bubble](#bubble)\n- [Pie](#pie)\n- [Area](#area)\n\n\u003e Please note that all below examples **require** importing:\n\n```scala\nimport com.datawizards.splot.api.implicits._\n```\n\n\u003e Please also note that most of below examples are based on randomly generated data!\n\n## Bar\n\n### Bar chart for sequence of numbers\n\n```scala\nval data = Seq(1.0, 4.0, 9.0)\ndata.plotBar()\n```\n\n### Bar chart for sequence of case class\n\n```scala\ncase class Person(name: String, age: Int)\n\nval data = Seq(\n    Person(\"p1\", 45),\n    Person(\"p2\", 85),\n    Person(\"p3\", 78)\n)\n\ndata.plotBar(_.age)\n```\n\n![](images/bar_people.png)\n\n### Bar chart for categorical data\n\n```scala\nval populationByCountry = Seq(\n    (\"DE\", 81),\n    (\"TR\", 72),\n    (\"FR\", 63),\n    (\"UK\", 62),\n    (\"IT\", 61),\n    (\"ES\", 46),\n    (\"UA\", 45),\n    (\"PL\", 38),\n    (\"RO\", 19),\n    (\"NL\", 17),\n    (\"GR\", 11),\n    (\"PT\", 11),\n    (\"BE\", 10),\n    (\"CZ\", 10),\n    (\"HU\", 10)\n  )\n\npopulationByCountry\n    .buildPlot()\n    .bar(_._1, _._2)\n    .titles(\"Population by country [millions]\", \"Country\", \"Population\")\n    .size(1200, 300)\n    .legendVisible(false)\n    .display()\n```\n\n![](images/bar_chart_with_string.png)\n\n## Scatter\n\n### Scatter chart for sequence of numbers\n\n```scala\nval data = Seq(\n    (1.0, 1.0),\n    (2.0, 4.0),\n    (3.0, 9.0)\n)\n\ndata.plotScatter()\n```\n\n![](images/scatter_basic.png)\n\n### Scatter chart for sequence of case class\n\n```scala\ncase class AgeIncome(age: Int, income: Double)\n\nval data = Seq(\n    AgeIncome(20, 1000.0),\n    AgeIncome(25, 2000.0),\n    AgeIncome(30, 2500.0),\n    AgeIncome(35, 3000.0),\n    AgeIncome(40, 3500.0),\n    AgeIncome(45, 3000.0),\n    AgeIncome(50, 2500.0)\n)\n\ndata.plotScatter(_.age, _.income)\n```\n\n![](images/scatter_age_income.png)\n\n## Line\n\n### Line chart for sequence of numbers\n\n```scala\nval data = Seq(\n    (1.0, 1.0),\n    (2.0, 4.0),\n    (3.0, 9.0)\n)\n\ndata.plotLine()\n```\n\n![](images/line_basic.png)\n\n### Line chart for sequence of case class\n\n```scala\ncase class AgeIncome(age: Int, income: Double)\n\nval data = Seq(\n    AgeIncome(20, 1000.0),\n    AgeIncome(25, 2000.0),\n    AgeIncome(30, 2500.0),\n    AgeIncome(35, 3000.0),\n    AgeIncome(40, 3500.0),\n    AgeIncome(45, 3000.0),\n    AgeIncome(50, 2500.0)\n)\n\ndata.plotLine(_.age, _.income)\n```\n\n![](images/line_age_income.png)\n\n### Line chart for timeseries data\n\n```scala\ntimeseriesData2017.plotLine()\n```\n\n![](images/line_timeseries.png)\n\n## Histogram\n\n### Histogram for sequence of numbers\n\n```scala\nval rand = new Random()\nval gaussians = for(i \u003c- 1 to 10000) yield rand.nextGaussian()\ngaussians.plotHistogram(100)\n```\n\n![](images/histogram_for_gaussians.png)\n\n### Histogram for categorical data\n\n```scala\npeople\n    .buildPlot()\n    .histogramForCategories(_.education)\n    .size(400, 300)\n    .titles(\"People by education\", \"Education\", \"Count\")\n    .legendVisible(false)\n    .display()\n```\n\n![](images/histogram_for_categories.png)\n\n## Bubble chart\n\n```scala\n  Seq(\n    (1, 1, 9.0),\n    (1, 2, 40.0),\n    (3, 2, 60.0),\n    (2, 2, 90.0),\n    (1, 3, 30.0),\n    (2, 3, 40.0)\n  )\n  .buildPlot()\n  .bubble(_._1, _._2, _._3)\n  .display()\n```\n\n![](images/bubble_chart.png)\n\n## Pie\n\n```scala\nSeq(\n    (\"DE\", 81),\n    (\"TR\", 72),\n    (\"FR\", 63),\n    (\"UK\", 62),\n    (\"IT\", 61)\n  )\n  .plotPie()\n```\n\n![](images/pie_chart.png)\n\n## Area\n\n```scala\nSeq(\n    (1.0, 1.0),\n    (2.0, 4.0),\n    (3.0, 9.0)\n  )\n  .plotArea()\n```\n\n![](images/area_chart.png)\n\n# Multiple series\n\n```scala\npeople\n    .buildPlot()\n    .scatter(_.age, _.income)\n    .seriesBy(_.education)\n    .size(500, 400)\n    .titles(\"Age and income by education\", \"age\", \"income\")\n    .display()\n```\n\n![](images/scatter_chart_with_multiple_series.png)\n\n# Multiple charts\n\n## Grouping by cols\n\n### Scatter plot\n\n```scala\npeople\n    .buildPlot()\n    .scatter(_.age, _.income)\n    .colsBy(_.country)\n    .display()\n```\n\n![](images/people_groupby_country.png)\n\n### Histogram\n\n```scala\npeople\n    .buildPlot()\n    .colsBy(_.education)\n    .histogram(_.age, 50)\n    .size(1200, 400)\n    .display()\n```\n\n![](images/histogram_multiple_columns.png)\n\n## Grouping by rows\n\n```scala\npeople\n    .buildPlot()\n    .scatter(_.age, _.income)\n    .rowsBy(_.education)\n    .display()\n```\n\n![](images/people_groupby_education.png)\n\n## Grouping by cols and/or rows\n\n### Scatter plot\n\n```scala\npeople\n    .buildPlot()\n    .scatter(_.age, _.income)\n    .colsBy(_.country)\n    .rowsBy(_.education)\n    .display()\n```\n\n![](images/people_groupby_country_education.png)\n\n### Bar plot\n\n```scala\nval groupedPeopleByCountryEducation = people\n    .groupBy(p =\u003e (p.country, p.education))\n    .mapValues(pv =\u003e pv.size)\n\ngroupedPeopleByCountryEducation\n    .buildPlot()\n    .colsBy(_._1._1)\n    .bar(x =\u003e x._1._2, x =\u003e x._2)\n    .size(1200, 300)\n    .display()\n```\n\n![](images/bar_chart_grids_with_string.png)\n\n## Multiple columns and series\n\n```scala\npeople\n    .buildPlot()\n    .scatter(_.age, _.income)\n    .size(1200, 300)\n    .colsBy(_.country)\n    .seriesBy(_.education)\n    .display()\n```\n\n![](images/scatter_chart_with_multiple_columns_and_series.png)\n\n# Aggregation functions\n\nSPlot enables aggregating your data before displaying chart.\n\nTo start using functions you need to import:\n```scala\nimport com.datawizards.splot.functions._\n```\n\nCurrently supported aggregation functions:\n\n- count\n- mean\n- sum\n\n## Calculating count\n\n```scala\n  people\n    .buildPlot()\n    .barWithAggregations(_.education, count())\n```\n\n![](images/bar_chart_with_count_aggregation.png)\n\n## Calculating mean\n\n```scala\n  people\n    .buildPlot()\n    .barWithAggregations(_.country, mean(_.income))\n```\n\n![](images/bar_chart_with_mean_aggregation.png)\n\n## Calculating sum\n\n```scala\n  people\n    .buildPlot()\n    .barWithAggregations(_.country, sum(_.income))\n```\n\n# Saving plot to file\n\nTo save plot to file you need to call method *save()* instead of calling *display()*.\n\n```scala\nimport com.datawizards.splot.model.ImageFormats\n\nSeq(1.0, 4.0, 9.0)\n    .buildPlot()\n    .bar()\n    .save(\"chart.png\", ImageFormats.PNG)\n```\n\nCurrently supported image formats:\n\n- BMP\n- PNG\n- JPG\n- GIF\n- EPS\n- PDF\n- SVG\n\n# Customizations\n\n## Change chart title\n\n```scala\nval data = Seq(1.0, 4.0, 9.0)\n\ndata\n    .buildPlot()\n    .bar()\n    .titles(\"Example bar chart\", \"x values\", \"y values\")\n    .display()\n```\n\n## Change chart size (width, height)\n\n```scala\nval data = Seq(1.0, 4.0, 9.0)\n\ndata\n    .buildPlot()\n    .bar()\n    .size(1600, 1200)\n    .display()\n```\n\n## Change series name\n\n```scala\nSeq(1.0, 4.0, 9.0)\n    .buildPlot()\n    .bar()\n    .seriesName(\"custom name\")\n    .display()\n```\n\n![](images/bar_chart_custom_series_name.png)\n\n## Hide legend\n\n```scala\nSeq(1.0, 4.0, 9.0)\n    .buildPlot()\n    .bar()\n    .legendVisible(false)\n    .display()\n```\n\n![](images/bar_chart_hide_legend.png)\n\n## Chart themes\n\nCurrently supported themes:\n\n![](images/ggplot_theme.png) ![](images/matplot_theme.png) ![](images/xchart_theme.png) ![](images/splot_theme.png)\n\nTo change theme you need to call method *theme()*:\n\n```scala\ndata\n    .buildPlot()\n    .bar()\n    .theme(PlotTheme.GGPlot2)\n    .display()\n```\n\n## Annotations\n\n```scala\nSeq(1, 4, 9)\n    .buildPlot()\n    .bar()\n    .showAnnotations(true)\n    .display()\n```\n\n![](images/annotations.png)\n\n# Bugs\n\nPlease report any bugs or submit feature requests to [SPlot Github issue tracker](https://github.com/piotr-kalanski/SPlot/issues).\n\n# Credits\n\n| Library | Category | License |\n| ------- | -------- | ------- |\n| [XChart](https://github.com/timmolter/XChart) | Graphing | [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) |\n\n# Contact\n\npiotr.kalanski@gmail.com","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotr-kalanski%2Fsplot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiotr-kalanski%2Fsplot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotr-kalanski%2Fsplot/lists"}