Engee documentation
Notebook

Engee Graphics Gallery

In this set of examples, we will show how the most different kinds of graphs look like in Engee, and by what means this result is achieved - data and code examples.

The right type of graph allows you to store or convey the right information in a very eloquent, yet concise way. Graphs take information from variables that must exist in the working memory area (must be visible in the Variables window). Their display is usually done from interactive ngscript scripts, immediately after the corresponding code cells. Of course, there are exceptions

  • charts in Unicode format can be displayed on the command line, but with interactive graphical charts, this limited format may be necessary only for special graphic design needs;
  • charts can be saved to file storage and opened as files from a file browser (sometimes it is useful).

The simplest and most frequently used command for graph output is the plot() function from the Plots library for graph output.

The Plots library in Engee is connected automatically.

That said, there are many more libraries in the Engee/Julia ecosystem for displaying beautiful plots, some of which we will explore in this demonstration:

  • StatsPlots to output complex statistical graphs,
  • GMT or General Mapping Tools for geographical maps.

We also advise you not to avoid libraries that allow you to create much richer and professional visualisations, such as:

  • Makie for very high quality visualisation of complex data,
  • Luxor - a language for creating vector two-dimensional graphics.

When the output library has built a graph, it passes it to the graphical environment, and there are options here:

  • gr environment (which is enabled by default) builds fast, frugal and non-interactive graphs (enabled by the command gr()), which can be saved using the context menu
  • plotly or plotlyjs create an interactive canvas where the graph can be scaled, rotated and saved using the interface buttons (switch to them using the commands plotly() and plotlyjs() respectively)

You can also choose raster (png) or vector (svg) format for graph output. By specifying the argument fmt=:svg inside the commands gr/plotly/plotlyjs you will get a very elegant, scalable chart in vector format, but if there are a lot of elements on the chart, especially if it will be interactive, its output will require more resources. Raster charts (fmt=:png) are another matter. They are faster to build and do not require such resources when redrawing.

The rest of the recipe for a perfect graphic can be found below.


And now, welcome - to the graphics gallery!


In [ ]:
Pkg.add(["StatsPlots", "WordCloud", "MeshIO", "ColorSchemes", "Colors", "GMT", "Statistics", "StatsBase", "CSV", "Distributions", "Meshes"])
In [ ]:
gr()
plot([1,2,3], [1,3,7])
Out[0]:

Data analysis

Construct a bar chart from a table of data.

In [ ]:
using DataFrames, HTTP, CSV;

# Открыть данные из файла
data = sort( CSV.File( "data/city.csv" ) |> DataFrame, ["population"], rev=true );

# (или) Загрузить данные с сервера
#url = "https://raw.githubusercontent.com/hflabs/city/master/city.csv"
#data = sort( CSV.File( HTTP.get(url).body) |> DataFrame, ["population"], rev=true );

bar( first(data, 8).population, label="Население, чел.", xrotation = 30 )
xticks!( 1:8, first(data, 8).address )
Out[0]:

Studying the correlation of multivariate data using the library StatsPlots and the function corrplor.

In [ ]:
using StatsPlots, DataFrames, LaTeXStrings

M = randn( 1000, 4 )
M[:,2] .+= 0.8sqrt.(abs.(M[:,1])) .- 0.5M[:,3] .+ 5
M[:,3] .-= 0.7M[:,1].^2 .+ 2
corrplot( M, label = [L"$x_i$" for i=1:4],
          xtickfontsize=4, ytickfontsize=6,
          guidefontcolor=:blue, yguidefontsize=15, yguidefontrotation=-45.0 )
Out[0]:

Function marginalkde from the library StatsPlots

In [ ]:
using StatsPlots

x = randn(1024)
y = randn(1024)
marginalkde(x, x+y)
Out[0]:
In [ ]:
using DataFrames, Statistics

# Создадим данные
df = DataFrame(Возраст=rand(4), Баланс=rand(4), Должность=rand(4), Зарплата=rand(4))
cols = [:Возраст, :Баланс, :Должность]  # Выберем часть данных
M = cor(Matrix(df[!,cols]))       # Ковариационная матрица

# График
(n,m) = size(M)
heatmap( M, fc=cgrad([:white,:dodgerblue4]), xticks=(1:m,cols), xrot=90, yticks=(1:m,cols), yflip=true, leg=false )
annotate!( [(j, i, text(round(M[i,j],digits=3), 10,"Arial",:black)) for i in 1:n for j in 1:m] )
Out[0]:
1.0 -0.033 -0.388 -0.033 1.0 -0.893 -0.388 -0.893 1.0

Normal histogram: function histogram

In [ ]:
using Random
Random.seed!(2018)

x = randn(1000)
y = randn(1000)
z = randn(1000)

histogram(x, bins=20, alpha=0.4, label="A")
histogram!(y, bins=20, alpha=0.6, label="B")
histogram!(z, bins=20, alpha=0.8, label="C")
Out[0]:

Distribution graph of a two-dimensional sample: function histogram2d

In [ ]:
x = randn(10^4)
y = randn(10^4)

histogram2d(x, y)
Out[0]:

Volume plot of a two-dimensional histogram using the wireframe

In [ ]:
using StatsBase

x = randn(10^4)
y = randn(10^4)
h = StatsBase.fit( Histogram, (x, y), nbins=20 )

wireframe( midpoints(h.edges[1]), midpoints(h.edges[2]), h.weights )
Out[0]:

Combining graphs with different design

In [ ]:
using Random

Random.seed!(1)
plot( Plots.fakedata(100, 12),
      layout = 4,
      palette = cgrad.([:grays :blues :heat :lightrainbow]),
      bg_inside = [:orange :pink :darkblue :black],
      seriestype= [:line :scatter :histogram :line] )
Out[0]:

And just graphs of different types:

In [ ]:
x = 1:4:250;
y = sin.( 2pi/250 * x );

p1 = plot( x, y, title= "График 1", seriestype=:stem, linewidth=3, legend=false )
p2 = plot( x, y, title= "График 2", seriestype=:scatter, color=:red )
  plot!( p2, x .- 10, 0.9y, seriestype=:scatter, color=:black, markersize=2 )
p3 = plot( x, y, title= "График 3", seriestype=:line, color=:green, legend=false )
p4 = plot( x, y, title= "График 4", seriestype=:steppre, color=:black, leg=false )

plot( p1, p2, p3, p4, layout=(2,2), titlefont=font(7), legendfont=font(7) )
Out[0]:

Wordcloud:

In [ ]:
import Pkg; Pkg.add(["WordCloud"], io=devnull);
using WordCloud, HTTP

# Загрузить текст из файла
content = read( open("data/Википедия - Математика.txt", "r"), String )

# Или загрузить данные с сервера
#url = "https://ru.wikipedia.org/wiki/Математика"
#resp = HTTP.request("GET", url, redirect=true)
#content = resp.body |> String |> html2text

stopwords = ["XVII", "того", "frac"];
stopwords = vcat(stopwords, string.(collect(1:100)));

wc = wordcloud( processtext( content, maxnum=100, stopwords=stopwords, minlength=4 ),
    mask=shape(ellipse, 600, 400, color=(0.98, 0.97, 0.99), backgroundcolor=1, backgroundsize=(700, 550)),
    masksize=:original, colors=:seaborn_icefire_gradient, angles=[0] ) |> generate!
paint(wc, "$(@__DIR__)/fromweb.svg")
wc
Out[0]:
No description has been provided for this image

Animation

Create a GIF animation using the command @animate, which runs a third-party function in a loop that draws 150 circles of decreasing radius, with increasing transparency. Among others, you can also use the format mp4.

In [ ]:
@userplot CirclePlot
@recipe function f(cp::CirclePlot)
    x, y, i = cp.args
    n = length(x)
    inds = circshift(1:n, 1 - i)
    linewidth --> range(0, 10, length = n)
    seriesalpha --> range(0, 1, length = n)
    aspect_ratio --> 1
    label --> false
    x[inds], y[inds]
end

n = 150
t = range(0, 2π, length = n)
x = sin.(t)
y = cos.(t)

anim = @animate for i  1:n
    circleplot(x, y, i)
end
gif(anim, "$(@__DIR__)/anim_fps15.gif", fps = 15)
Out[0]:
No description has been provided for this image

Rotating object (geometry defined in STL file)

In [ ]:
import Pkg; Pkg.add(["Meshes", "MeshIO"], io=devnull);
using Meshes, MeshIO, FileIO
gr();

obj = load( "$(@__DIR__)/data/lion.stl" );

@gif for az in 0:10:359
    p = plot( camera = (az, -20), axis=nothing, border=:none, aspect_ratio=:equal, size=(400,400) )
    for i in obj
        m = Matrix([i[1] i[2] i[3] i[1]])'
        if m[1,1] > 0 plot!( p, m[:,1], m[:,2], m[:,3], lc=:green, label=:none, lw=.4, aspect=:equal )
        else plot!( p, m[:,1], m[:,2], m[:,3], lc=:gray, label=:none, lw=.4, aspect=:equal )
        end
    end
end
[ Info: Saved animation to /user/start/examples/data_analysis/plots_gallery/tmp.gif
Out[0]:
No description has been provided for this image

Matrix and image output

Function heatmap

In [ ]:
include( "$(@__DIR__)/data/peaks.jl" );

(x, y, z) = peaks()
heatmap(x, y, z)
Out[0]:
In [ ]:
using LaTeXStrings

x = range( -1.3, 1.3, 501 );
y = range( -1.3, 1.3, 501 );

X = repeat( x, outer = [1,501] )
Y = repeat( y', outer = [501,1] )

#C = ones( size(X) ) .* ( 0.360284 + 0.100376*1im );
C = ones( size(X) ) .* ( -0.75 + 0.1im );

Z_max = 1e6; it_max = 50;

Z = Complex.( X, Y );
B = zeros( size(C) );

for k = 1:it_max
    Z = Z.^2 .+ C;
    B = B .+ ( abs.(Z) .< 2 );
end

heatmap( B,
         aspect_ratio = :equal,
         cbar=false,
         axis=([], false),
         color=:jet )
title!( L"Julia Set $(c=0.360284+0.100376i)$" )
Out[0]:

Output illustrations from files: library Images

In [ ]:
using Images

load( "$(@__DIR__)/data/640px-Business_Centre_of_Moscow_2.jpg" )
Out[0]:
No description has been provided for this image

Graphs in Cartesian coordinates

Plot two trigonometric functions given by vectors on the Cartesian coordinate plane.

In [ ]:
x = 0:0.1:2pi
y1 = cos.(x)
y2 = sin.(x)

plot(x, y1, c="blue", linewidth=3, label="cos")
plot!(x, y2, c="red", line=:dash, label="sin")
title!("Тригонометрические функции")
xlabel!("Угол (рад)")
ylabel!("sin(x) и cos(x)")

# Отдельной командой установим границы осей
plot!( xlims=(0,2pi), ylims=(-2, 2) )
Out[0]:

Filling in the area under the graph (argument fillrange)

In [ ]:
using Distributions

x = range(-3, 3, 100 )
y = pdf.( Normal(0,1), x )

ix = abs.(x) .< 1
plot( x[ix], y[ix], fillrange = zero(x[ix]), fc=:blues, leg=false)
plot!( x, y, grid=false, lc=:black, widen=false )
WARNING: using Distributions.shape in module Main conflicts with an existing identifier.
Out[0]:

Fill-in chart (area)

In [ ]:
x = 1:10;
areaData = x .* rand(10,5) .* 5;
cur_colors = theme_palette(:default)

plot()
for i in 1:size(areaData,2)
    plot!( areaData[i,:], fillcolor = cur_colors[i], fillrange = 0, fillalpha=.5 )
end
plot!()
Out[0]:

Cumulative schedule with filling

In [ ]:
x = 1:10;
areaData = x .* rand(10,5);
cur_colors = theme_palette(:default)

plot()
for i in size(areaData,2):-1:1
    plot!( sum(areaData[:,1:i], dims=2), fillcolor = cur_colors[i], fillrange = 0, lw=0 )
end
plot!()
Out[0]:

Graph with confidence intervals (arguments xerr and yerr)

In [ ]:
using Random
Random.seed!(2018)

f(x) = 2 * x + 1
x = 0:0.1:2
n = length(x)
y = f.(x) + randn(n)

plot( x, y,
      xerr = 0.1 * rand(n),
      yerr = rand(n),
      marker = (:circle, :red) )
Out[0]:

Three-dimensional graph

In [ ]:
t = 0:pi/100:10pi;
x1 = sin.(1 * t)
y1 = cos.(1 * t)

x2 = sin.(2 * t)
y2 = cos.(2 * t)

plot(
    plot( x1, y1, t, leg=false, lw=2 ),
    plot( x2, y2, t, leg=false, lw=2 )
)
Out[0]:

Smooth and stepped graphs combined by argument layout

In [ ]:
x = range( 1, 2pi, length=50 )

plot( x, [sin.(x) sin.(x)],
      seriestype=[:line :step],
      layout = (2, 1) )
Out[0]:

Parametric graph in 3D

In [ ]:
t = range(0, stop=10, length=1000)

x = cos.(t)
y = sin.(t)
z = sin.(5t)

plot( x, y, z )
Out[0]:

Graphs in polar coordinates

Arrows to points forming a spiral (graph quiver)

In [ ]:
cur_colors = theme_palette(:roma);
th = range( 0, 3*pi/2, 10 );
r = range( 5, 20, 10 );
c = collect(1:10)

X = r .* cos.(th)
Y = r .* sin.(th)

quiver( r.*0, r.*0, quiver=(th,r), aspect_ratio=:equal, proj=:polar,
        line_z=repeat(c, inner=4), c=:roma, cbar=false, lw=2 )
Out[0]:

function pie

In [ ]:
x = [ "Энтузиасты", "Экспериментаторы", "Ученые" ]
y = [0.4,0.35,0.25]

pie(x, y, title="Кто использует Julia",l = 0.5)
Out[0]:

Function polar

In [ ]:
θ = range(0, 2π, length=50)
r = 1 .+ cos.(θ) .* sin.(θ).^2

plot(θ, r, proj=:polar, lims=(0,1.5))
Out[0]:

Step graph in polar coordinates (graph rose)

In [ ]:
using Random
Random.seed!(2018)

n = 24
R = rand(n+1)
θ = 0:2pi/n:2pi
plot( θ, R, proj=:polar, line=:steppre, lims=(0,1) )
Out[0]:

A graph in polar coordinates given by the function

In [ ]:
θ = range( 0, 8π, length=1000 )
fr(θ) = sin( 5/4 * θ )

plot( θ, fr.(θ), proj=:polar, lims=(0,1) )
Out[0]:

Bubble diagram in polar coordinates

In [ ]:
include( "$(@__DIR__)/data/planetData.jl" );

scatter( angle, distance, ms=diameter, mc = c,
         proj=:polar, legend=false,
         markerstrokewidth=1, markeralpha=.7 )
title!( "Планеты Солнечной системы" )
Out[0]:

Discrete data

Horizontal bar chart (function bar)

In [ ]:
ticklabel = string.( collect('а':'м') )
bar( 1:12, orientation=:h, yticks=(1:12, ticklabel), yflip=true )
Out[0]:

Bar charts bar and groupedbar

In [ ]:
using StatsPlots
include( "$(@__DIR__)/data/BostonTemp.jl" );

plots_id = [1,2,3];

groupedbar( hcat([Temperatures[i,:] for i in plots_id]...),
            xticks=(1:12, Months),
            label = [Years[i] for i in plots_id]',
            color = reshape(palette(:tab10)[1:3], (1,3)) )
Out[0]:

Chart stem (stem-list)

In [ ]:
x1 = range( 0, 2pi, 50 );
x2 = range( pi, 3pi, 50 );

X = [x1, x2];
Y = [cos.(x1), 0.5.*sin.(x2)];

plot( X, Y, line=:stem, marker=:circle )
Out[0]:

Three-dimensional stem-diagram

In [ ]:
X = repeat( range(0,1,10), outer = [1,10] )
Y = repeat( range(0,1,10)', outer = [10,1] )

Z = exp.(X.+Y)

plot( X, Y, Z, line=:stem, color=:skyblue, markercolor=:white, marker=:circle, leg=false )
Out[0]:

Contour plots

Graph of a cylinder streamlined by laminar flow.

The analytical approximation of this function is calculated using Eq:

$$\psi = U sin \theta \left ( r - \frac{R^2}{r} \right )$$

In [ ]:
include( "$(@__DIR__)/data/flowAroundCylinder.jl" );

(r, theta, x, y, streamline, pressure) = flowAroundCylinder();

plot( x, y, streamline, levels=60, seriestype=:contour,
      xlim = [-5,5], ylim=[-5,5], cbar=false, linewidth=2,
      leg=false, color=:haline )

(xx,yy) = circle( 0, 0, 1 );

plot!( xx, yy, lw=2, lc=:black )
Out[0]:

Filled contour plot (static pressure around a cylinder streamlined by laminar flow)

In [ ]:
include( "$(@__DIR__)/data/flowAroundCylinder.jl" );

(r, theta, x, y, streamline, pressure) = flowAroundCylinder();
plot( x, y, pressure, seriestype=:contourf, xlim = [-5,5], ylim=[-5,5], cbar=false, linewidth=1, leg=false )

(xx,yy) = circle( 0, 0, 1 );
plot!( xx, yy, lw=2, lc=:black )
Out[0]:

Contour plot of mathematical functions

In [ ]:
# Подготовим данные
y = x = range( -7, 7, step=0.1 )
z = @. sin(x) + cos(y')

Plots.contour( x, y, z, color=:haline )
Out[0]:

Surfaces and meshes

Parameter seriestype=:surface

In [ ]:
# Подготовим данные
y = x = range( -7, 7, step=0.1 )
z = @. sin(x) + cos(y')

plot( x, y, z, st=:surface, color=:cool )
Out[0]:

Parameter seriestype=:wireframe

In [ ]:
# Подготовим данные
y = x = range( -7, 7, step=0.5 )
z = @. sin(x) + cos(y')

plot( x, y, z, st=:wireframe )
Out[0]:

Graph of two-dimensional function

In [ ]:
include( "$(@__DIR__)/data/peaks.jl" );

(x,y,z) = peaks();

plot( x, y, z; levels=20, st=:surface )
Out[0]:

Let's construct the graph of the function "sombrero". When using gr(), the argument hidesurface is not used. But when using plotly(), the argument hidesurface=false allows you to simultaneously display both the surface and the contour plot on it.

In [ ]:
x = y = range( -8, 8, length=41 )
f(x,y) = sin.(sqrt.(x.*x+y.*y))./sqrt.(x.*x+y.*y)

# в gr() этот способ позволяет увидеть график поверхности позади графика линий
p = plot( x, y, f, st=:surface, fillalpha=0.7, cbar=false ) 
plot!( p, x, y, f, st=:wireframe )

# в plotly() есть более удобный синтаксис
#wireframe( x, y, f, hidesurface=false )
Out[0]:

Dot plots and bubble charts

Bubble chart

In [ ]:
using Random: seed!
seed!(28)

xyz = randn(100, 3)

scatter( xyz[:, 1], xyz[:, 2], marker_z=xyz[:, 3],
         label="Окружности",
         colormap=:plasma, cbar=false,
         markersize=15 * abs.(xyz[:, 3]),
         xlimits=[-3,3], ylimits=[-3,3]
       )
Out[0]:

Three-dimensional dot plot with a separate colour assigned to each point

In [ ]:
using Colors, ColorSchemes
cs = ColorScheme([colorant"yellow", colorant"red"])
Out[0]:
No description has been provided for this image
In [ ]:
using CSV, DataFrames

df = DataFrame(CSV.File( "$(@__DIR__)/data/seamount.csv" ))
C = get( cs, df.z, :extrema )

scatter( df.x, df.y, df.z, c=C, leg=false )
Out[0]:

Three-dimensional dot plot with dummy space for colour histograms

In [ ]:
using CSV, DataFrames

df = DataFrame(CSV.File( "$(@__DIR__)/data/seamount.csv" ))
cs = cgrad(:thermal)
C = get( cs, df.x, :extrema )

l = @layout [a{0.97w} b]
p1 = scatter( df.x, df.y, df.z, c=C, leg=false )
p2 = heatmap(rand(2,2), clims=(0,10), framestyle=:none, c=cgrad(cs), cbar=true, lims=(-1,0))
plot(p1, p2, layout=l)
Out[0]:

Colour and annotations

Let's create a colour palette:

In [ ]:
using Images
scheme = rand(RGB, 10)
Out[0]:
No description has been provided for this image

Use the palette to colour a matrix of random numbers and output as an image:

In [ ]:
matrix = rand(1:10, 20, 20)
img = scheme[ matrix ]
Out[0]:
No description has been provided for this image

Create a graph of random points with lines and annotations:

In [ ]:
x = 1:10
y = rand(10)

# Создадим точечный график
scatter(x, y)

# Нанесем вертивальные и горизонтальные линии на график
vline!( [5], color=:red, linestyle=:dash, label=:none )
hline!( [0.5], color=:blue, linestyle=:dot, label=:none )

# Нанесем аннотации на график (работает только в gr())
annotate!( 8, 0.52, text("Горизонтальная линия", :blue, :right, 8))
annotate!( 4.8, 0.7, text("Вертикальная линия", :red, 8, rotation = 90))
Out[0]: