{"id":83339,"date":"2018-11-06T10:00:34","date_gmt":"2018-11-06T08:00:34","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=83339"},"modified":"2018-11-05T18:10:20","modified_gmt":"2018-11-05T16:10:20","slug":"clojure-comparison-gnuplot-plottingdata","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html","title":{"rendered":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data"},"content":{"rendered":"<p>What is the best way to plot memory and CPU usage data (mainly) in Clojure? I will compare gnuplot, Incanter with JFreeChart, and vega-lite (via Oz). (Spoiler: I like Oz\/vega-lite most but still use Incanter to prepare the data.)<\/p>\n<p>The data looks like this:<\/p>\n<pre class=\"brush:java\">;; sec.ns | memory | CPU %\r\n1541052937.882172509 59m 0.0\r\n1541052981.122419892 78m 58.0\r\n1541052981.625876498 199m 85.9\r\n1541053011.489811184 1.2g 101.8<\/pre>\n<p>The data has been produced by <a href=\"https:\/\/gist.github.com\/holyjak\/931a3441982c833f5f8fcdcf54d05c91\">monitor-usage.sh<\/a>.<\/p>\n<h2>The tools<\/h2>\n<p><strong>Gnuplot 5<\/strong><\/p>\n<p>Gnuplot is the simplest, with a lot available out of the box. But it is also somewhat archaic and little flexible.<\/p>\n<p>Here is the code:<\/p>\n<pre class=\"brush:java; wrap-lines:false\">  \r\n#!\/usr\/bin\/env gnuplot --persist -c\r\n# Plot memory and CPU usage over time. Usage:\r\n#  usage-plot.gp &lt;input file&gt; [&lt;output .png file&gt;]\r\n# where the input file has the columns `&lt;unix time&gt; &lt;memory, with m\/g suffix&gt; &lt;% cpu&gt;`\r\n# To create the input file, see https:\/\/gist.github.com\/jakubholynet\/931a3441982c833f5f8fcdcf54d05c91\r\n\r\n# Arguments:\r\ninfile=ARG1\r\noutfile=ARG2\r\nset term x11\r\nset title 'Memory, CPU usage from' . infile\r\nset xdata time\r\nset timefmt \"%s\"\r\nset xlabel \"Time [[hh:]mm:ss]\"\r\nset ylabel \"Memory usage\"\r\nset format y '%.1s%cB'\r\n\r\nset y2label 'CPU usage'\r\nset format y2 '%.0s%%'\r\nset y2tics nomirror\r\nset tics out\r\nset autoscale y\r\nset autoscale y2\r\n\r\n# Credit: Christoph @ https:\/\/stackoverflow.com\/a\/52822256\/204205\r\nresolveUnit(s)=(pos=strstrt(\"kmgtp\",s[strlen(s):*]), real(s)*(1024**pos))\r\n\r\nif (exists(\"outfile\") &amp;&amp; strlen(outfile) &gt; 0) {\r\n    print \"Outputting to the file \", outfile\r\n    set term png # 640,480\r\n    set output outfile\r\n}\r\n\r\n# Styling\r\nset style line 1 linewidth 2 linecolor 'blue'\r\nset style line 2 linecolor 'light-green'\r\n#set xtics font \", 10\"\r\nset tics font \", 10\"\r\nset xtics rotate 60 # put label every 60s, make vertical so they don't clash in .png if too many\r\n\r\nplot infile u 1:3 with lp axes x1y2 title \"cpu\" linestyle 2, \\\r\n    infile using 1:(resolveUnit(stringcolumn(2))) with linespoints title \"memory\" linestyle 1<\/pre>\n<p>And here is an example output:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-gnuplot.png\"><img decoding=\"async\" class=\"aligncenter wp-image-83347 size-full\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-gnuplot.png\" alt=\"plotting usage data\" width=\"640\" height=\"480\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-gnuplot.png 640w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-gnuplot-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Pros: Feature-rich (support bytes axis, two Y axes, reading data).<\/p>\n<p>Cons: Archaic language, less flexible; I couldn\u2019t stop it from drawing X labels over each other when I had data for a longer period.<\/p>\n<p><strong>Incanter (JFreeChart)<\/strong><\/p>\n<p>Incanter is (was?) the go to tool for data analysis in Clojure and it includes the Java library JFreeChart for charting. There has been some development lately (integrating clojure.core.matrix) but otherwise it is quite stagnating. That\u2019s why there have been newer community efforts.<\/p>\n<p>Here is the first part of the code, that prepares the data for charting (also used for Oz):<\/p>\n<pre class=\"brush:java; wrap-lines:false\"> \r\n(ns clj-charting.usage-chart-preparation\r\n  (:require\r\n    [incanter.core :refer :all]\r\n    [incanter.stats :as s]\r\n    [incanter.io :as io]))\r\n\r\n(defn- resolve-unit-suffix \r\n  \"Replace values such as 333k, 800m, 1.2g with the corresponding value in bytes\"\r\n  [val-suffixed]\r\n  (if-let [[_ val unit] (and\r\n                          (string? val-suffixed)\r\n                          (re-find #\"(\\d+)([kmg])\" val-suffixed))]\r\n    (let [order (case unit\r\n                  \"k\" 1\r\n                  \"m\" 2\r\n                  \"g\" 3)\r\n          scale (apply * (take order (repeat 1024)))]\r\n      (* (Integer\/parseInt val) scale))))\r\n\r\n(defn read-usage-data \r\n  \"Read usage data in the form `sec.ns memory_with_scale_suffix CPU_percentage` into a dataset with\r\n   `ms memory_in_bytes CPU_percentage`\"\r\n  [file]\r\n  (let [data (io\/read-dataset\r\n               file\r\n               :delim \\space)]\r\n    (-&gt; data\r\n        ;; Memory: from 300m or 1g to a number:\r\n        (transform-col\r\n          :col1\r\n          resolve-unit-suffix)\r\n        ;; CPU: From &lt;sec&gt;.&lt;nano&gt; to &lt;ms&gt;:\r\n        (transform-col\r\n          :col0\r\n          #(long (* 1000 %))))))\r\n\r\n(defn moving-window-means\r\n  \"Given very scattered data, produce a similar sequence of 'moving window mean' where we\r\n   replace each point by the mean of it and the preceding\/following `radius` points.\r\n   \"\r\n  [radius col]\r\n  (let [x' (concat (repeat radius nil) col)\r\n        parts (drop-last radius (partition (inc (* 2 radius)) 1 x'))\r\n        means (map #(-&gt; (remove nil? %) s\/mean long)\r\n                   parts)]\r\n    means))<\/pre>\n<p>And here is the code to format the chart (the most difficult part was to display kB \/ MB \/ GB values on the axis in a nice way; I really missed Gnuplot\u2019s out-of-the-box support here):<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java; wrap-lines:false\"> \r\n(ns clj-charting.incanter\r\n  (:require\r\n    [incanter.core :refer :all]\r\n    [incanter.charts :refer :all]\r\n    [clj-charting.usage-chart-preparation :refer [read-usage-data moving-window-means]])\r\n  (:import\r\n    [org.jfree.chart JFreeChart]\r\n    [org.jfree.chart.plot XYPlot]\r\n    (org.jfree.chart.axis ValueAxis NumberAxis NumberTickUnit TickUnitSource TickUnit)\r\n    (java.text NumberFormat DecimalFormat FieldPosition)))\r\n\r\n(defn merge-y-axis\r\n  \"Merge the Y axis of two line \/ time series charts. The former chart will have\r\n  the left Y axis, and the latter will have the right. Incanter does not support 2 Y\r\n  axes out of the box.\r\n  Source: https:\/\/matthewdowney.github.io\/clojure-incanter-plot-multiple-y-axis.html\"\r\n  [^JFreeChart chart ^JFreeChart chart-to-merge]\r\n  (let [^XYPlot plot (.getPlot chart-to-merge)]\r\n    (doto ^XYPlot (.getPlot chart)\r\n      (.setRangeAxis 1 (.getRangeAxis plot))\r\n      (.setDataset 1 (.getDataset plot))\r\n      (.mapDatasetToRangeAxis 1 1)\r\n      (.setRenderer 1 (.getRenderer plot)))\r\n    (-&gt; (.getPlot chart)\r\n        (.getLegendItems)\r\n        (.addAll (.getLegendItems plot)))\r\n    chart))\r\n\r\n(defn byte-scale \r\n  \"For the given number [in bytes] return [scale, scale suffix] so that we can divide it \r\n   by the scale and display with the corresponding suffix.\r\n   Example: 2333 -&gt; [1024 \\\"kB\\\"]\"\r\n  [num]\r\n  (let [k 1024\r\n        m (int (Math\/pow 1024 2))\r\n        g (int (Math\/pow 1024 3))]\r\n    (condp &lt;= num\r\n      g [g \"GB\"]\r\n      m [m \"MB\"]\r\n      k [k \"kB\"]\r\n      [1 \"\"])))\r\n\r\n(defn format-bytes \r\n  \"For the given number [in bytes] return [the number scaled down, the scale suffix such as \\\"kB\\\"].\r\n   Example: 2333 -&gt; [2.278 \\\"kB\\\"]\"\r\n  [num]\r\n  (let [[scale unit] (byte-scale num)]\r\n    [(\/ num scale) unit]))\r\n\r\n;; Instance of NumberFormat that displays a byte number scaled down and with the scale suffix\r\n;; Example: 2333 -&gt; \\\"2.3kB\\\"]\"\r\n(def byteFmt (let [dec-fmt (java.text.DecimalFormat. \"#.#\")]\r\n               (proxy [java.text.NumberFormat] []\r\n                 (format [^double number, ^StringBuffer toAppendTo, ^FieldPosition pos]\r\n                   (let [[n u] (format-bytes number)]\r\n                     (.append\r\n                       (.format dec-fmt n toAppendTo pos)\r\n                       u))))))\r\n\r\n(defn nearest-byte-tick\r\n  \"For the given byte number, find out what tick to show on the axis; \r\n   e.g. we would rather see a tick such as '800MB' than '783.5MB' on it.\"\r\n  ([^double size tick-fn]\r\n   (let [[scale] (byte-scale size)]\r\n     (NumberTickUnit.\r\n       (* scale\r\n          ;; FIXME if size = 1000 upgrade to 1024\r\n          (.getSize\r\n            (tick-fn\r\n              (NumberTickUnit. (\/ size scale)))))\r\n       byteFmt))))\r\n\r\n(def byte-tick-source\r\n  \"TickUnitSource suitable for byte values spanning multiple of kB - MB - GB\"\r\n  ;; TODO Instead of reusing IntegerTickUnits, reimplement it to support powers of 2\r\n  (let [int-tick-units (NumberAxis\/createIntegerTickUnits)]\r\n    (reify\r\n      TickUnitSource\r\n      (^TickUnit getLargerTickUnit [_ ^TickUnit unit]\r\n        (nearest-byte-tick\r\n          (.getSize unit)\r\n          #(.getLargerTickUnit int-tick-units %)))\r\n      (^TickUnit getCeilingTickUnit [me ^TickUnit unit]\r\n        (.getCeilingTickUnit me (.getSize unit)))\r\n      (^TickUnit getCeilingTickUnit [_ ^double size]\r\n        (nearest-byte-tick\r\n          size\r\n          #(.getCeilingTickUnit int-tick-units %))))))\r\n\r\n(defn set-bytes-tick-unit [^JFreeChart chart]\r\n  (let [^XYPlot plot (.getPlot chart)\r\n        ^NumberAxis axis (.getRangeAxis plot)]\r\n    (.setStandardTickUnits axis byte-tick-source)\r\n    chart))\r\n\r\n\r\n(defn plot-usage [file]\r\n  (let [data (read-usage-data file)\r\n        time (sel data :cols 0)\r\n        mem (sel data :cols 1)\r\n        cpu (sel data :cols 2)]\r\n    (-&gt;\r\n      (time-series-plot time cpu :title file :y-label \"cpu [%]\"  :legend true)\r\n      (add-lines time (moving-window-means 60 cpu) :series-label \"cpu (mean)\")\r\n      (merge-y-axis\r\n        (set-bytes-tick-unit\r\n          (time-series-plot time mem :series-label \"Memory\")))\r\n      (view))))\r\n\r\n(plot-usage \"siege-c10-all-urls-async-node11.dat\")<\/pre>\n<p>That is quite insane amount of work, huh? And the result:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/cpu-usage-with-async-hooks-node11.png\"><img decoding=\"async\" class=\"aligncenter wp-image-83348 size-full\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/cpu-usage-with-async-hooks-node11.png\" alt=\"plotting usage data\" width=\"500\" height=\"378\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/cpu-usage-with-async-hooks-node11.png 500w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/cpu-usage-with-async-hooks-node11-300x227.png 300w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p><strong>vega-lite via Oz<\/strong><\/p>\n<blockquote>\n<p>Vega and Vega-lite visualization grammars:\u00a0Vega is a declarative format for creating, saving, and sharing visualization designs. With Vega, visualizations are described in JSON, and generate interactive views using either HTML5 Canvas or SVG.<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/vega.github.io\/\">Vega-lite (and Vega<\/a>) is the new kid on the block. It has learned a lot from D3 and R\u2019s ggplot2\u00a0and is intended for data exploration, interactive charts, and making it possible to combine multiple charts on the same page \u2013 while making this as simple as possible. It is based on the Grammar of Graphics so it is presumabely well thought-through.<\/p>\n<p><a href=\"https:\/\/github.com\/metasoarous\/oz\/\">Oz<\/a> is a thin wrapper around vega\/vega-lite that makes it possible to interact with the browser from Clojure REPL, with Clojure data.<\/p>\n<p>(Note: Oz currently uses VL v2.6 while the latest VL is v3rc8, which fixes some limitations in v2.)<\/p>\n<p>As mentioned above, we use the same <a href=\"https:\/\/gist.github.com\/holyjak\/c4a88135bc08703d6351754980537055\">usage-chart-preparation.clj<\/a>\u00a0as the pure-Incanter example to prepare the data for charting. Then, to plot them:<\/p>\n<pre class=\"brush:java; wrap-lines:false\">\r\n(ns clj-charting.oz\r\n  (:require\r\n    [oz.core :as oz]\r\n    [incanter.core :refer :all]\r\n    [clj-charting.usage-chart-preparation :refer [read-usage-data moving-window-means]]))\r\n\r\n(defn dataset-&gt;map-list \r\n  \"Incanter dataset into a list of maps like \r\n   {\\\"0\\\" 1541065398391, \\\"1\\\" 446693376, \\\"2\\\" 99.9, \\\"cpu_mean\\\" 89}\"\r\n  [ds]\r\n  (let [rows (to-list ds)\r\n        means (moving-window-means 60 (sel ds :cols 2))]\r\n    (map\r\n      #(assoc\r\n         (zipmap (map str (range)) %1)\r\n         \"cpu_mean\" %2)\r\n      rows\r\n      means)))\r\n\r\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r\n\r\n(def gb4 (* 3 1024 1024 1024))\r\n\r\n;; TODO Display legend - IMPOSSIBLE :-( until Datum\r\n(def line-plot\r\n  (let [data (dataset-&gt;map-list (read-usage-data \"siege-c10-all-urls-async-node11.dat\"))\r\n        x-enc {:field \"0\"\r\n               :type \"temporal\"\r\n               :timeUnit \"hoursminutesseconds\" ; :aggregate \"mean\" l &lt;- this kills points with same value\r\n               :axis {:title \"Time\"}\r\n               :scale {:zero false}}]\r\n    {:width 700\r\n     :data {:values data}\r\n\r\n     ;;; ?? requires VL v3 until then we have to compute cpu_mean using Incanter\r\n     ;:transform [{:window [{:op \"mean\"\r\n     ;                       :field \"1\"\r\n     ;                       :as \"cpu_mean\"}]\r\n     ;             :frame [-10, 10]}]\r\n     ; TODO VLv3: use this ?? instead of repeating the X on each plot\r\n     ;:encoding {:x x-enc}\r\n     :layer [{:mark {:type \"line\"\r\n                     :clip true\r\n                     :color \"red\"}\r\n              :encoding {:x x-enc\r\n                         :y {:field \"1\"\r\n                             :type \"quantitative\"\r\n                             :axis {:format \".1s\" :title \"Memory\" :labelColor \"red\" #_\"required VL 3\"}\r\n                             :scale {:domain [0 gb4]}}}}\r\n             {:layer [\r\n                      {:mark {:type \"point\"\r\n                              :clip true}\r\n                       :encoding {:x x-enc\r\n                                  :y {:field \"2\"\r\n                                      :type \"quantitative\"\r\n                                      :axis {:title \"CPU [%]\" :labelColor \"blue\"}}}}\r\n                      {:mark {:type \"line\"\r\n                              :clip true\r\n                              :color \"blue\"}\r\n                       :encoding {:x x-enc\r\n                                  :y {:field \"cpu_mean\"\r\n                                      :type \"quantitative\"\r\n                                      :title nil\r\n                                      :axis nil}}}]}]\r\n     :resolve {:scale {:y \"independent\"}}}))\r\n\r\n(oz\/start-plot-server!)\r\n(oz\/v! line-plot)<\/pre>\n<p>It is more work than in Gnuplot but it provides more value and is much more powerful.<\/p>\n<p>Here is the output (generated with VL v3 so the labels have the same color as the lines):<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-vega-lite-v2.png\"><img decoding=\"async\" class=\"aligncenter wp-image-83349 size-full\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-vega-lite-v2.png\" alt=\"plotting usage data\" width=\"804\" height=\"251\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-vega-lite-v2.png 804w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-vega-lite-v2-300x94.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/11\/usage-vega-lite-v2-768x240.png 768w\" sizes=\"(max-width: 804px) 100vw, 804px\" \/><\/a><\/p>\n<p>The awesome thing is that the chart and data can be encoded in an URL so that you can <a>open in in the online Vega Editor and play with it<\/a>.<\/p>\n<p>Pros: Good and powerful design, modern, interactive, promising.<\/p>\n<p>Cons: The community is very small so it is harder to get help, it isn\u2019t so mature yet (e.g. it was impossible to add a legend to my multi-layer chart). You have to transform your data into JSON so it likely isn\u2019t suitable for huge amounts of it.<\/p>\n<p><strong>Other options<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/clojurewerkz\/envision\">Clojurewerkz\/envision<\/a> is \u201ca small, easy to use Clojure library for data processing, cleanup and visualisation. [..] Main idea of this library is to make exploratory analysis more interactive and visual, although in programmer\u2019s way.\u201d ClojureWerkz is known for its commitment to project quality and maintenance so that is good, on the other hand the last code change has been 2 years ago.<\/p>\n<p>Outside of Clojure, I would expect Python to have some very good charting libraries.<\/p>\n<h2>Conclusion<\/h2>\n<p>Nothing is optimal\u00a0 but vega-lite is very promising, I will continue to use it \u2013 and I will also still use Incanter to process and prepare the data.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>Published on Java Code Geeks with permission by Jakub Holy, partner at our <a href=\"\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener\">JCG program<\/a>. See the original article here: <a href=\"https:\/\/theholyjava.wordpress.com\/2018\/11\/04\/clojure-comparison-of-gnuplot-incanter-oz-vega-lite-for-plotting-usage-data\/\" target=\"_blank\" rel=\"noopener\">Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>What is the best way to plot memory and CPU usage data (mainly) in Clojure? I will compare gnuplot, Incanter with JFreeChart, and vega-lite (via Oz). (Spoiler: I like Oz\/vega-lite most but still use Incanter to prepare the data.) The data looks like this: ;; sec.ns | memory | CPU % 1541052937.882172509 59m 0.0 1541052981.122419892 &hellip;<\/p>\n","protected":false},"author":16,"featured_media":93,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-83339","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-clojure"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-11-06T08:00:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jakub Holy\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/twitter.com\/HolyJak\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jakub Holy\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html\"},\"author\":{\"name\":\"Jakub Holy\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/7b7d87e493b5f8388635d4315b062727\"},\"headline\":\"Clojure \u2013 comparison of gnuplot, Incanter, oz\\\/vega-lite for plotting usage data\",\"datePublished\":\"2018-11-06T08:00:34+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html\"},\"wordCount\":680,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"articleSection\":[\"Clojure\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html\",\"name\":\"Clojure \u2013 comparison of gnuplot, Incanter, oz\\\/vega-lite for plotting usage data - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"datePublished\":\"2018-11-06T08:00:34+00:00\",\"description\":\"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/11\\\/clojure-comparison-gnuplot-plottingdata.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JVM Languages\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Clojure\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\\\/clojure\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Clojure \u2013 comparison of gnuplot, Incanter, oz\\\/vega-lite for plotting usage data\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/7b7d87e493b5f8388635d4315b062727\",\"name\":\"Jakub Holy\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g\",\"caption\":\"Jakub Holy\"},\"description\":\"Jakub is an experienced Java[EE] developer working for a lean &amp; agile consultancy in Norway. He is interested in code quality, developer productivity, testing, and in how to make projects succeed.\",\"sameAs\":[\"http:\\\/\\\/theholyjava.wordpress.com\",\"http:\\\/\\\/www.linkedin.com\\\/in\\\/jakubholydotnet\",\"https:\\\/\\\/x.com\\\/http:\\\/\\\/twitter.com\\\/HolyJak\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Jakub-Holy\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data - Java Code Geeks","description":"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html","og_locale":"en_US","og_type":"article","og_title":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data - Java Code Geeks","og_description":"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.","og_url":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2018-11-06T08:00:34+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","type":"image\/jpeg"}],"author":"Jakub Holy","twitter_card":"summary_large_image","twitter_creator":"@http:\/\/twitter.com\/HolyJak","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Jakub Holy","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html"},"author":{"name":"Jakub Holy","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/7b7d87e493b5f8388635d4315b062727"},"headline":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data","datePublished":"2018-11-06T08:00:34+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html"},"wordCount":680,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","articleSection":["Clojure"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html","url":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html","name":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","datePublished":"2018-11-06T08:00:34+00:00","description":"Interested to learn about plotting usage data? Check our article explaining what is the best way to plot memory and CPU usage data in Clojure.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2018\/11\/clojure-comparison-gnuplot-plottingdata.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JVM Languages","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages"},{"@type":"ListItem","position":3,"name":"Clojure","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages\/clojure"},{"@type":"ListItem","position":4,"name":"Clojure \u2013 comparison of gnuplot, Incanter, oz\/vega-lite for plotting usage data"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/7b7d87e493b5f8388635d4315b062727","name":"Jakub Holy","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7ee9569bd027b442ce03e2cc44cbc8791448ab502e0e2c70cbc6186f64d6e1f5?s=96&d=mm&r=g","caption":"Jakub Holy"},"description":"Jakub is an experienced Java[EE] developer working for a lean &amp; agile consultancy in Norway. He is interested in code quality, developer productivity, testing, and in how to make projects succeed.","sameAs":["http:\/\/theholyjava.wordpress.com","http:\/\/www.linkedin.com\/in\/jakubholydotnet","https:\/\/x.com\/http:\/\/twitter.com\/HolyJak"],"url":"https:\/\/www.javacodegeeks.com\/author\/Jakub-Holy"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/83339","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=83339"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/83339\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/93"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=83339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=83339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=83339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}