Документация Engee
Notebook

Галерея графиков Engee

В этом наборе примеров мы покажем, как выглядят самые разные виды графиков в Engee, и какими средствами достигается такой результат – примеры данных и кода.

Правильно подобранный тип графика позволяют сохранить или донести до слушателя нужную информацию в очень красноречивой, при этом лаконичной форме. Графики берут информацию из переменных, которые должны существовать в рабочей области памяти (должны быть видны в окне Переменные). Их отображение, как правило, осуществляется из интерактивных скриптов ngscript, сразу после соответствующих ячеек с кодом. Конечно, есть исключения

  • графики в формате Unicode можно отображать и в командной строке, однако при наличии графических интерактивных графиков, такой ограниченный формат может быть нужен разве что для нужд специального графического дизайна;
  • графики можно сохранять в файловое хранилище и открывать как файлы из файлового браузера (иногда это полезно).

Самая простая и часто используемая команда для выводов графиков – функция plot() из библиотеки Plots для вывода графиков.

Библиотека Plots в Engee подключается автоматически.

При этом в экосистеме Engee/Julia есть еще множество библиотек для вывода красивых графиков, некоторые мы рассмотрим в этой демонстрации:

  • StatsPlots для вывода сложных статистических графиков,
  • GMT или General Mapping Tools для вывода географических карт.

Мы также советуем не избегать библиотек, позволяющих создавать гораздо более насыщенные и профессиональные визуализации, например:

  • Makie для очень качественной визуализации сложных данных,
  • Luxor – язык для создания векторной двухмерной графики.

Когда библиотека вывода построила график, она передает его в графическое окружение, и здесь есть варианты:

  • окружение gr (которое включено по умолчанию) строит быстрые, экономные и не интеравтивные графики (включается командой gr()), которые можно сохранить при помощи контекстного меню
  • plotly или plotlyjs создают интерактивное полотно, на котором график можно масштабировать, вращать и сохранять при помощи кнопок интерфейса (переключиться на них можно, соответственно, командами plotly() и plotlyjs())

А еще для вывода графиков вы можете выбрать растровый (png) или векторный (svg) формат. Указав внутри команд gr/plotly/plotlyjs аргумент fmt=:svg вы получите очень изящный, масштабируемый график в векторном формате, однако при наличии большого количества элементов на графике, особенно если он будет интерактивным, его вывод потребует больше ресурсов. Другое дело – растровые графики (fmt=:png). Они быстрее строятся и не требуют таких ресурсов при перерисовке.

Остальные элементы рецепта идеального графика вы найдете ниже.


А теперь, приглашаем – в галерею графиков!


In [ ]:
gr()
plot([1,2,3], [1,3,7])
Out[0]:

Анализ данных

Построение столбчатой диаграммы по таблице данных.

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]:

Изучение корреляции многомерных данных при помощи библиотеки StatsPlots и функции 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]:

Функция marginalkde из библиотеки 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]:

Обычная гистограмма: функция 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]:

График распределения двухмерной выборки: функция histogram2d

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

histogram2d(x, y)
Out[0]:

Объемный график двухмерной гистограммы при помощи 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]:

Совмещение графиков с различным оформлением

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]:

Облако слов (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 = ["с", "в", "и", "от", "или", "под", "как", "на", "из", "это", "об", "что", "по", "млн", "за", "при", "www", "для", "не", "со", "но", "то"];
stopwords = vcat(stopwords, string.(collect(1:100)));

wc = wordcloud( processtext( content, maxnum=100, stopwords=stopwords ),
    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
Language: rus
Total words: 3038.0. Unique words: 1560. After filtration: 1534.
The top 100 words are kept. 
Language: rus
fonts = ["DejaVu Serif Bold", " Light", " Normal", " Medium"]
▸1. Set spacing = 2; scale = 48.25024972569727
Completed after 81 epochs.
Out[0]:
No description has been provided for this image

Анимация

Создание GIF-анимации при помощи команды @animate, запускающей в цикле стороннюю функцию, которая рисует 150 окружностей уменьшающегося радиуса, с растущим показателем прозрачности. Кроме прочих, можно также использовать формат 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)
[ Info: Saved animation to /user/start/examples/data_analysis/plots_gallery/anim_fps15.gif
Out[0]:
No description has been provided for this image

Вращающийся объект (геометрия задана в STL файле)

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

Вывод матриц и изображений

Функция 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]:

Вывод иллюстраций из файлов: библиотека Images

In [ ]:
using Images

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

Графики в декартовых координатах

Вывод двух тригонометрических функций, заданных векторами, на декартовой координатной плоскости.

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]:

Заполнение площади под графиком (аргумент 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]:

График с заполнением (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]:

Накопляющийся график с заполнением

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]:

График с доверительными интервалами (аргументы xerr и 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]:

Трехмерный график

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]:

Гладкий и ступенчатый графики, объединенные при помощи аргумента layout

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

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

Параметрический график в 3D

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

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

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

Графики в полярных координатах

Стрелки к точкам, формирующим спираль (график 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]:

Функция pie

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

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

Функция polar

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

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

Ступенчатый график в полярных координатах (график 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]:

График в полярных координатах, заданный при помощи функции

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

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

Пузырьковая диаграмма в полярных координатах

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

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

Географические карты

Нанесение обозначений на карту (библиотека GMT, функции coast и scatter)

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

GMT.coast(
    region="0/40/30/60+r",
    proj=(name=:laea, center=[10,50]),
    frame=:ag, res=:low, area=500, shore=:thick, borders=1,
    water=:blue,
    # Выделим несколько стран другими цветами
    DCW=((country="DE", pen=(1,:red)), (country="GB,IT,FR", fill=:green), (country="FI,NO,SE", fill=:yellow)),
    figsize=2.8
)

GMT.scatter!( rand(5:15, 12), rand(47:55, 12), fmt=:png,
    marker=:circle, markeredgecolor=0, size=0.0, markerfacecolor=:orange, show=true )
No description has been provided for this image

Отображение карты с рельефом океанов. При первом запуске, карта будет загружена с сервера.

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

GMT.grdimage( "@earth_relief_20m_g", proj=:Winkel,
          colorbar=true, coast=false, show=true )
No description has been provided for this image

Дискретные данные

Горизонтально расположенная столбчатая диаграмма (функция bar)

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

Столбчатые диаграммы bar и 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]:

Диаграмма stem (ствол-лист)

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]:

Трехмерная stem-диаграмма

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]:

Контурные графики

График обтекания цилиндра ламинарным потоком.

Аналитическая аппроксимация этой функции рассчитывается при помощи уравнения:

$$\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]:

Заполненный контурный график (статическое давление вокруг цилиндра, обтекаемого ламинарным потоком)

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]:

Контурный график математических функций

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

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

Поверхности и сетки

Параметр 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]:

Параметр seriestype=:wireframe

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

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

График двухмерной функции

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

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

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

Построим график функции "сомбреро". При использовании gr() аргумент hidesurface не используется. Но при использовании plotly() аргумент hidesurface=false позволяет одновременно вывести и поверхность, и контурный график на ней.

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]:

Точечные графики и пузырьковые диаграммы

Пузырьковая диаграмма

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]:

Трехмерный точечный график с назначением отдельного цвета каждой точке

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]:

Трехмерный точечный график с фиктивным пространством для цветовой гисторгаммы

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]:

Цвет и аннотации

Создадим цветовую палитру:

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

Используем палитру чтобы раскрасить матрицу из случайных чисел и вывести как изображение:

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

Создадим график из случайных точек с линиями и аннотациями:

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]: