HPUNIX Сайт о ОС и не только!

Строим диаграммы при помощи Scala Chart

16 июля 2012 - unix
Строим диаграммы с помощью Scala Chart

Сейчас мы научимся строить графики, гистограммы и радиальные диаграммы в Scala. В этом нам поможет восхитительная библиотека Scala Chart, которая представляет собой обертку над обширно известной в мире Java библиотекой JFreeChart. Также будут объяснены некие достойные внимания способности и особенности Scala, которые ранее не рассматривались в этом блоге.

Нам пригодится приблизительно таковой build.sbt:

name := "scala-chart-examples"

version := "0.1"

scalaVersion := "2.10.1"

libraryDependencies += "com.github.wookietreiber" %%
                       "scala-chart" %
                       "0.2.0"

scalacOptions ++= Seq("-unchecked", "-deprecation")

Если вы желаете использовать самую последнюю версию Scala Chart, то заместо определенной версии "0.2.0" сможете написать "latest.integration". Но если желаете знать мое мировоззрение, это неразумно.

Разглядим построение простого графика:

package me.eax.scalachart

import scalax.chart._
import scalax.chart.Charting._
import java.io._

object Application extends App {
  val defaultChartSize = (512, 384)
  def createSimpleXYLineChart {
    val dataset = Seq((1,2),(2,4),(3,6),(4,8))
    val chart = XYLineChart(
                  dataset.toXYSeriesCollection("f(x)"),
                  title = "XYLineChart Simple Example",
                  domainAxisLabel = "x axis description",
                  rangeAxisLabel = "y axis description"
                )
    chart.saveAsPNG(new File("./simpleXYLineChart.png"),
                    defaultChartSize)
  }

С кортежами мы уже знакомы. Seq — это трейт (трейты в первом приближении можно считать аналогами интерфейсов в Java либо абстрактных классов в C++) для последовательностей. С последовательностями мы тоже уже сталкивались, но не предавали этому особенного значения.

Последовательности похожи на итерируемые контейнеры, только элементы в последовательностях всегда упорядочены.

Вызов Seq(1,2,3) представляет собой всего только вызов способа apply класса-одиночки scala.collection.Seq, который возвращает обычный односвязный перечень из переданных частей:

scala> Seq(1,2,3)
res0: Seq[Int] = List(1, 2, 3)

Как я понимаю, в будущих версиях Scala для представления последовательностей по дефлоту может быть применен и некоторый другой контейнер.

Строим диаграммы с помощью Scala Chart

Направьте внимание на создание экземпляра класса XYLineChart. Здесь были применены именованные характеристики, с чем мы ранее не сталкивались. Эта возможность очень комфортна в случае, если у способа много аргументов, и некие из их имеют значения по дефлоту.

Также появляется вопрос, откуда у класса List взялся способ toXYSeriesCollection? В реальности, здесь употребляется неявное приведение типов. Если в 2-ух словах, ах так это работает:

scala> class MyIterable[T](it: Iterable[T]) { def secret { it foreach println } }
defined class MyIterable
Строим диаграммы с помощью Scala Chart

scala> implicit def iterableToMyIterable[T](x: Iterable[T]) = new MyIterable(x)
iterableToMyIterable: [T](x: Iterable[T])MyIterable[T]

scala> List(1,2,3).secret
1
2
3

Класс List не имеет способа secret, но, при помощи iterableToMyIterable, он может быть неявным образом преобразован в MyIterable, у которого этот способ есть. Компилятор Scala автоматом конвертирует последнюю строчку кода в iterableToMyIterable(List(1,2,3)).secret, в итоге чего у класса List «появляется новый метод». Кстати, в Scala 2.10, благодаря показавшийся поддержке implicit-классов, возможно обойтись без вспомогательной функции.

Дальше при помощи способа saveAsPNG мы сохраняем график в PNG-файл:

Простой график, построенный в Scala Chart

Есть подобные способы для форматов JPEG и PDF. Не считая того, при помощи способа show можно вывести график в окне, сделанном при помощи Swing.

Разглядим чуток более непростой пример:

  def createXYLineChart {
    val dataset = Seq(
                    ("x*x - 2*x", for(x <- -3.0 to 8.0 by 1.0)
                                    yield (x, x*x - Два * x)),
                    ("3 * x", for(x <- 1.0 to 10.0 by 0.1)
                                yield (x, Три * x))
                  )  
    val chart = XYLineChart(
                  dataset.toXYSeriesCollection,
                  title = "XYLineChart Example",
                  domainAxisLabel = "время, с",
                  rangeAxisLabel = "скорость, м/c"
                )  
Строим диаграммы с помощью Scala Chart
    chart.saveAsPNG(new File("./xyLineChart.png"), defaultChartSize)
  }

Для нас тут нет ничего нового. Приобретенные графики:

Графики, построенные в Scala Chart

Время от времени требуется выстроить график не по координатам точек, а, к примеру, по месяцам и количеству переходов на веб-сайт в эти месяцы. Для решения этой задачки в Scala Chart предусмотрен класс LineChart:

  val categoryDatasetExample = Map(
        "январь" -> Map("заработано" -> 2, "потрачено" -> 4),
        "февраль" -> Map("заработано" -> 4, "потрачено" -> 5),
        "март" -> Map("заработано" -> 8, "потрачено" -> 6),
        "апрель" -> Map("заработано" -> 16, "потрачено" -> 7)
      ).toCategoryDataset

  def createLineChart {
    val chart = LineChart(
                  categoryDatasetExample,
                  title = "LineChart Example",
                  domainAxisLabel = "месяц",
                  rangeAxisLabel = "млн рублей"
                )
    chart.saveAsPNG(new File("./lineChart.png"), defaultChartSize)
  }

Тут мы используем контейнер immutable.Map. Можно было использовать его и в прошлом примере, в этом смысле библиотека Scala Chart является очень гибкой. Что любопытно, -> — это не часть синтаксиса Scala, а рядовая функция, возвращающая пару из переданных ей аргументов.

Приобретенные графики:

Использование класса LineChart

Построение радиальный диаграммы:

  def createPieChart {
    val dataset = Map(
        "Erlang" -> 33.3,
        "Scala" -> 33.3,
        "Clojure" -> 13.4,
        "Haskell" -> 10.0,
        "OCaml" -> 10.0
      )
    val chart = PieChart.threeDimensional(
                  dataset.toPieDataset,
                  legend = false,
                  title = """|Результаты опроса
                             |"Ваш возлюбленный язык программирования"
                             |""".stripMargin
                )
    chart.saveAsPNG(new File("./pieChart.png"), defaultChartSize)
  }

Диаграмма:

Круговая диаграмма, построенная в Scala Chart

Построение обычной гистограммы:

  def createSimpleBarChart {
    val dataset = Map("alpha" -> 123.45, "beta" -> 678.9)
    val chart = BarChart(
                  dataset.toCategoryDataset,
                  title = "Simple Bar Chart Example"
                )
    chart.saveAsPNG(new File("./simpleBarChart.png"), defaultChartSize)
  }

Итог:

Простая гистограмма, построенная в Scala Chart

Чуток более непростая гистограмма:

  def createBarChart {
    val chart = BarChart(
                  categoryDatasetExample, // см выше
                  title = "Bar Chart Example"
                )
    chart.saveAsPNG(new File("./barChart.png"), defaultChartSize)
  }

Итог:

Более сложная гистограмма, созданная с помощью Scala Chart

Также Scala Chart умеет строить некие другие виды диаграмм. Подробности вы отыщите в официальной ScalaDoc. Полную версию приведенного выше кода вы отыщите в этом репозитории.

Как обычно, если во время чтения поста у вас появились какие-то вопросы либо просто достойные внимания идеи, я буду рад ознакомиться с ними в комментах.

Дополнение: Работа с Excel-файлами в Scala

Похожие статьи

  • Научился собирать код на Scala при помощи SBT

    В этой заметке мы познакомися с утилитой sbt. Мы научимся собирать с ее помощью проекты на Scala, устанавливать посторонние библиотеки, также узнаем, как собрать jar, который будет работать на люб...

  • Работа с Excel-файлами в Scala

    В сей заметке рассматривается код на Scala, генерирующий электрическую таблицу в формате xlsx, содержащую, кроме данных в ячейках, формулы, графики и украшательства типа выделения текста жирным шри...

  • Моя 1-ая программа8230 в сей раз на Scala

    Перепробовав странноватые и никому на практике ненадобные Haskell, OCaml, Perl 6, Common Lisp, Vala, Go, также малость D, что, вобщем, не было отражено в этом блоге, я решил направить свое внимание на...

  • Работа с постоянными выражениями в Scala

    Не так давно мне захотелось прикрутить к блогу виджет, содержащий перечень самых просматриваемых заметок. Так как WordPress не собирает подобающую статистику, количество просмотров предполагалось...

  • Отладка кода на Haskell при помощи Debug

    Что ни гласи, а отладочный вывод был и остается одним из самых обычных и нередко применяемых методов отладки. Но как прикажите использовать его в Haskell при написании незапятнанных функций? Временно об...

Теги:
Рейтинг: +7 Голосов: 18 979 просмотров
Комментарии (0)

Нет комментариев. Ваш будет первым!

Найти на сайте: параметры поиска

Windows 7

Среда Windows 7 на первых порах кажется весьма непривычной для многих.

Windows 8

Если резюмировать все выступления Microsoft на конференции Build 2013.

Windows XP

Если Windows не может корректно завершить работу, в большинстве случаев это

Windows Vista

Если к вашему компьютеру подключено сразу несколько мониторов, и вы регулярно...