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

Построение блоков

Напомним, что при вызове функции javascript Plotly.newPlot ожидается получить массив объектов trace и (необязательно) объект layout. В этом разделе мы узнаем, как строить такие объекты в Julia.

Линии

Экземпляр Plot будет иметь вектор линий (trace). Каждая из них должна быть подтипом AbstractTrace.

PlotlyJS.jl определяет один такой подтип:

mutable struct GenericTrace{T <: AbstractDict{Symbol,Any}} <: AbstractTrace
    fields::T
end

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

Мы создаем эту оболочку вокруг Dict, чтобы предоставить удобный синтаксис, как описано ниже.

Рассмотрим пример. Предположим, требуется создать следующий объект JSON:

{
  "type": "scatter",
  "x": [1, 2, 3, 4, 5],
  "y": [1, 6, 3, 6, 1],
  "mode": "markers+text",
  "name": "Team A",
  "text": ["A-1", "A-2", "A-3", "A-4", "A-5"],
  "textposition": "top center",
  "textfont": {
    "family":  "Raleway, sans-serif"
  },
  "marker": { "size": 12 }
}

Это можно сделать, как показано ниже:

fields = Dict{Symbol,Any}(:type => "scatter",
                          :x => [1, 2, 3, 4, 5],
                          :y => [1, 6, 3, 6, 1],
                          :mode => "markers+text",
                          :name => "Team A",
                          :text => ["A-1", "A-2", "A-3", "A-4", "A-5"],
                          :textposition => "top center",
                          :textfont => Dict(:family =>  "Raleway, sans-serif"),
                          :marker => Dict(:size => 12))
GenericTrace("scatter", fields)
scatter with fields marker, mode, name, text, textfont, textposition, type, x, and y

Более удобный синтаксис имеет следующий вид:

t1 = scatter(;x=[1, 2, 3, 4, 5],
              y=[1, 6, 3, 6, 1],
              mode="markers+text",
              name="Team A",
              text=["A-1", "A-2", "A-3", "A-4", "A-5"],
              textposition="top center",
              textfont_family="Raleway, sans-serif",
              marker_size=12)
scatter with fields marker, mode, name, text, textfont, textposition, type, x, and y

Обратите внимание на несколько моментов:

  • Линия type стала именем функции. Аналогичный метод существует для всех типов линий plotly.js.

  • Все остальные атрибуты линии были заданы с помощью именованных аргументов. Это позволяет не вводить префикс символа (:) и стрелки (=>), которые были необходимы при построении Dict.

  • Вложенные атрибуты можно задавать, используя символы подчеркивания. Обратите внимание, что JSON "marker": { "size": 12 } был написан как marker_size=12.

Чтобы убедиться, что это действительно эквивалентный JSON, можно вывести его содержимое (обратите внимание, что порядок атрибутов разный, но содержимое идентично):

print(JSON.json(t1, 2))
{
  "textfont": {
    "family": "Raleway, sans-serif"
  },
  "mode": "markers+text",
  "marker": {
    "size": 12
  },
  "textposition": "top center",
  "y": [
    1,
    6,
    3,
    6,
    1
  ],
  "type": "scatter",
  "name": "Team A",
  "text": [
    "A-1",
    "A-2",
    "A-3",
    "A-4",
    "A-5"
  ],
  "x": [
    1,
    2,
    3,
    4,
    5
  ]
}

Доступ к атрибутам

Если нужно извлечь конкретный атрибут, это можно сделать с помощью getindex(t1, :attrname) или синтаксического приема t1[:attrname]. Обратите внимание, что в вызове getindex могут использоваться как символы, так и строки:

julia> t1["marker"]
Dict{Any, Any} with 1 entry:
  :size => 12

julia> t1[:marker]
Dict{Any, Any} with 1 entry:
  :size => 12

Для доступа к вложенному свойству используется parent.child.

julia> t1["textfont.family"]
"Raleway, sans-serif"

Задание дополнительных атрибутов

Можно задать дополнительные атрибуты. Предположим, нужно задать для marker.color красный цвет. Мы можем сделать это с помощью вызова setindex!(t1, "red", :marker_color) или, что эквивалентно, t1["marker_color"] = "red":

julia> t1["marker_color"] = "red"
"red"

julia> println(JSON.json(t1, 2))
{
  "textfont": {
    "family": "Raleway, sans-serif"
  },
  "mode": "markers+text",
  "marker": {
    "color": "red",
    "size": 12
  },
  "textposition": "top center",
  "y": [
    1,
    6,
    3,
    6,
    1
  ],
  "type": "scatter",
  "name": "Team A",
  "text": [
    "A-1",
    "A-2",
    "A-3",
    "A-4",
    "A-5"
  ],
  "x": [
    1,
    2,
    3,
    4,
    5
  ]
}

Обратите внимание, что атрибут color был корректно добавлен внутри существующего атрибута marker (наряду с size), а не заменен атрибутом marker.

Этот синтаксис можно использовать и для добавления совершенно новых вложенных атрибутов:

julia> t1["line_width"] = 5
5

julia> println(JSON.json(t1, 2))
{
  "textfont": {
    "family": "Raleway, sans-serif"
  },
  "mode": "markers+text",
  "marker": {
    "color": "red",
    "size": 12
  },
  "line": {
    "width": 5
  },
  "textposition": "top center",
  "y": [
    1,
    6,
    3,
    6,
    1
  ],
  "type": "scatter",
  "name": "Team A",
  "text": [
    "A-1",
    "A-2",
    "A-3",
    "A-4",
    "A-5"
  ],
  "x": [
    1,
    2,
    3,
    4,
    5
  ]
}

Макеты

Тип Layout определяется следующим образом:

mutable struct Layout{T <: AbstractDict{Symbol,Any}} <: AbstractLayout
    fields::T
    subplots::_Maybe{Subplots}
end

Для построения макета можно использовать тот же удобный синтаксис именованных аргументов, который применялся для линий:

julia> l = Layout(;title="Penguins",
                   xaxis_range=[0, 42.0], xaxis_title="fish",
                   yaxis_title="Weight",
                   xaxis_showgrid=true, yaxis_showgrid=true,
                   legend_y=1.15, legend_x=0.7)
layout with fields legend, margin, template, title, xaxis, and yaxis

julia> println(JSON.json(l, 2))
{
  "xaxis": {
    "showgrid": true,
    "range": [
      0.0,
      42.0
    ],
    "title": {
      "text": "fish"
    }
  },
  "template": {
    "data": {
      "scatterpolargl": [
        {
          "type": "scatterpolargl",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "carpet": [
        {
          "baxis": {
            "gridcolor": "white",
            "endlinecolor": "#2a3f5f",
            "minorgridcolor": "white",
            "startlinecolor": "#2a3f5f",
            "linecolor": "white"
          },
          "type": "carpet",
          "aaxis": {
            "gridcolor": "white",
            "endlinecolor": "#2a3f5f",
            "minorgridcolor": "white",
            "startlinecolor": "#2a3f5f",
            "linecolor": "white"
          }
        }
      ],
      "scatterpolar": [
        {
          "type": "scatterpolar",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "parcoords": [
        {
          "line": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          },
          "type": "parcoords"
        }
      ],
      "scatter": [
        {
          "type": "scatter",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram2dcontour": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "histogram2dcontour",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "contour": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "contour",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scattercarpet": [
        {
          "type": "scattercarpet",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "mesh3d": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "mesh3d"
        }
      ],
      "surface": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "surface",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scattermapbox": [
        {
          "type": "scattermapbox",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "scattergeo": [
        {
          "type": "scattergeo",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram": [
        {
          "type": "histogram",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "pie": [
        {
          "type": "pie",
          "automargin": true
        }
      ],
      "choropleth": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "choropleth"
        }
      ],
      "heatmapgl": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "heatmapgl",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "bar": [
        {
          "type": "bar",
          "error_y": {
            "color": "#2a3f5f"
          },
          "error_x": {
            "color": "#2a3f5f"
          },
          "marker": {
            "line": {
              "color": "#E5ECF6",
              "width": 0.5
            }
          }
        }
      ],
      "heatmap": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "heatmap",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "contourcarpet": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "contourcarpet"
        }
      ],
      "table": [
        {
          "type": "table",
          "header": {
            "line": {
              "color": "white"
            },
            "fill": {
              "color": "#C8D4E3"
            }
          },
          "cells": {
            "line": {
              "color": "white"
            },
            "fill": {
              "color": "#EBF0F8"
            }
          }
        }
      ],
      "scatter3d": [
        {
          "line": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          },
          "type": "scatter3d",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "scattergl": [
        {
          "type": "scattergl",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram2d": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "histogram2d",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scatterternary": [
        {
          "type": "scatterternary",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "barpolar": [
        {
          "type": "barpolar",
          "marker": {
            "line": {
              "color": "#E5ECF6",
              "width": 0.5
            }
          }
        }
      ]
    },
    "layout": {
      "xaxis": {
        "gridcolor": "white",
        "zerolinewidth": 2,
        "title": {
          "standoff": 15
        },
        "ticks": "",
        "zerolinecolor": "white",
        "automargin": true,
        "linecolor": "white"
      },
      "hovermode": "closest",
      "paper_bgcolor": "white",
      "geo": {
        "showlakes": true,
        "showland": true,
        "landcolor": "#E5ECF6",
        "bgcolor": "white",
        "subunitcolor": "white",
        "lakecolor": "white"
      },
      "colorscale": {
        "sequential": [
          [
            0.0,
            "#0d0887"
          ],
          [
            0.1111111111111111,
            "#46039f"
          ],
          [
            0.2222222222222222,
            "#7201a8"
          ],
          [
            0.3333333333333333,
            "#9c179e"
          ],
          [
            0.4444444444444444,
            "#bd3786"
          ],
          [
            0.5555555555555556,
            "#d8576b"
          ],
          [
            0.6666666666666666,
            "#ed7953"
          ],
          [
            0.7777777777777778,
            "#fb9f3a"
          ],
          [
            0.8888888888888888,
            "#fdca26"
          ],
          [
            1.0,
            "#f0f921"
          ]
        ],
        "diverging": [
          [
            0,
            "#8e0152"
          ],
          [
            0.1,
            "#c51b7d"
          ],
          [
            0.2,
            "#de77ae"
          ],
          [
            0.3,
            "#f1b6da"
          ],
          [
            0.4,
            "#fde0ef"
          ],
          [
            0.5,
            "#f7f7f7"
          ],
          [
            0.6,
            "#e6f5d0"
          ],
          [
            0.7,
            "#b8e186"
          ],
          [
            0.8,
            "#7fbc41"
          ],
          [
            0.9,
            "#4d9221"
          ],
          [
            1,
            "#276419"
          ]
        ],
        "sequentialminus": [
          [
            0.0,
            "#0d0887"
          ],
          [
            0.1111111111111111,
            "#46039f"
          ],
          [
            0.2222222222222222,
            "#7201a8"
          ],
          [
            0.3333333333333333,
            "#9c179e"
          ],
          [
            0.4444444444444444,
            "#bd3786"
          ],
          [
            0.5555555555555556,
            "#d8576b"
          ],
          [
            0.6666666666666666,
            "#ed7953"
          ],
          [
            0.7777777777777778,
            "#fb9f3a"
          ],
          [
            0.8888888888888888,
            "#fdca26"
          ],
          [
            1.0,
            "#f0f921"
          ]
        ]
      },
      "yaxis": {
        "gridcolor": "white",
        "zerolinewidth": 2,
        "title": {
          "standoff": 15
        },
        "ticks": "",
        "zerolinecolor": "white",
        "automargin": true,
        "linecolor": "white"
      },
      "shapedefaults": {
        "line": {
          "color": "#2a3f5f"
        }
      },
      "font": {
        "color": "#2a3f5f"
      },
      "annotationdefaults": {
        "arrowhead": 0,
        "arrowwidth": 1,
        "arrowcolor": "#2a3f5f"
      },
      "plot_bgcolor": "#E5ECF6",
      "title": {
        "x": 0.05
      },
      "coloraxis": {
        "colorbar": {
          "ticks": "",
          "outlinewidth": 0
        }
      },
      "hoverlabel": {
        "align": "left"
      },
      "mapbox": {
        "style": "light"
      },
      "polar": {
        "angularaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "bgcolor": "#E5ECF6",
        "radialaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        }
      },
      "autotypenumbers": "strict",
      "ternary": {
        "aaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "bgcolor": "#E5ECF6",
        "caxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "baxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        }
      },
      "scene": {
        "xaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        },
        "zaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        },
        "yaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        }
      },
      "colorway": [
        "#636efa",
        "#EF553B",
        "#00cc96",
        "#ab63fa",
        "#FFA15A",
        "#19d3f3",
        "#FF6692",
        "#B6E880",
        "#FF97FF",
        "#FECB52"
      ]
    }
  },
  "legend": {
    "y": 1.15,
    "x": 0.7
  },
  "margin": {
    "l": 50,
    "b": 50,
    "r": 50,
    "t": 60
  },
  "title": "Penguins",
  "yaxis": {
    "showgrid": true,
    "title": {
      "text": "Weight"
    }
  }
}

attr

Существует специальная функция attr, которая позволяет применять ту же процедуру использования ключевых слов, которую мы видели в функциях trace и layout, но ко вложенным атрибутам. Давайте вернемся к предыдущему примеру, но будем использовать attr для построения xaxis и legend:

julia> l2 = Layout(;title="Penguins",
                    xaxis=attr(range=[0, 42.0], title="fish", showgrid=true),
                    yaxis_title="Weight", yaxis_showgrid=true,
                    legend=attr(x=0.7, y=1.15))
layout with fields legend, margin, template, title, xaxis, and yaxis

julia> println(JSON.json(l2, 2))
{
  "xaxis": {
    "showgrid": true,
    "range": [
      0.0,
      42.0
    ],
    "title": "fish"
  },
  "template": {
    "data": {
      "scatterpolargl": [
        {
          "type": "scatterpolargl",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "carpet": [
        {
          "baxis": {
            "gridcolor": "white",
            "endlinecolor": "#2a3f5f",
            "minorgridcolor": "white",
            "startlinecolor": "#2a3f5f",
            "linecolor": "white"
          },
          "type": "carpet",
          "aaxis": {
            "gridcolor": "white",
            "endlinecolor": "#2a3f5f",
            "minorgridcolor": "white",
            "startlinecolor": "#2a3f5f",
            "linecolor": "white"
          }
        }
      ],
      "scatterpolar": [
        {
          "type": "scatterpolar",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "parcoords": [
        {
          "line": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          },
          "type": "parcoords"
        }
      ],
      "scatter": [
        {
          "type": "scatter",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram2dcontour": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "histogram2dcontour",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "contour": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "contour",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scattercarpet": [
        {
          "type": "scattercarpet",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "mesh3d": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "mesh3d"
        }
      ],
      "surface": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "surface",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scattermapbox": [
        {
          "type": "scattermapbox",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "scattergeo": [
        {
          "type": "scattergeo",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram": [
        {
          "type": "histogram",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "pie": [
        {
          "type": "pie",
          "automargin": true
        }
      ],
      "choropleth": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "choropleth"
        }
      ],
      "heatmapgl": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "heatmapgl",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "bar": [
        {
          "type": "bar",
          "error_y": {
            "color": "#2a3f5f"
          },
          "error_x": {
            "color": "#2a3f5f"
          },
          "marker": {
            "line": {
              "color": "#E5ECF6",
              "width": 0.5
            }
          }
        }
      ],
      "heatmap": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "heatmap",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "contourcarpet": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "contourcarpet"
        }
      ],
      "table": [
        {
          "type": "table",
          "header": {
            "line": {
              "color": "white"
            },
            "fill": {
              "color": "#C8D4E3"
            }
          },
          "cells": {
            "line": {
              "color": "white"
            },
            "fill": {
              "color": "#EBF0F8"
            }
          }
        }
      ],
      "scatter3d": [
        {
          "line": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          },
          "type": "scatter3d",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "scattergl": [
        {
          "type": "scattergl",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "histogram2d": [
        {
          "colorbar": {
            "ticks": "",
            "outlinewidth": 0
          },
          "type": "histogram2d",
          "colorscale": [
            [
              0.0,
              "#0d0887"
            ],
            [
              0.1111111111111111,
              "#46039f"
            ],
            [
              0.2222222222222222,
              "#7201a8"
            ],
            [
              0.3333333333333333,
              "#9c179e"
            ],
            [
              0.4444444444444444,
              "#bd3786"
            ],
            [
              0.5555555555555556,
              "#d8576b"
            ],
            [
              0.6666666666666666,
              "#ed7953"
            ],
            [
              0.7777777777777778,
              "#fb9f3a"
            ],
            [
              0.8888888888888888,
              "#fdca26"
            ],
            [
              1.0,
              "#f0f921"
            ]
          ]
        }
      ],
      "scatterternary": [
        {
          "type": "scatterternary",
          "marker": {
            "colorbar": {
              "ticks": "",
              "outlinewidth": 0
            }
          }
        }
      ],
      "barpolar": [
        {
          "type": "barpolar",
          "marker": {
            "line": {
              "color": "#E5ECF6",
              "width": 0.5
            }
          }
        }
      ]
    },
    "layout": {
      "xaxis": {
        "gridcolor": "white",
        "zerolinewidth": 2,
        "title": {
          "standoff": 15
        },
        "ticks": "",
        "zerolinecolor": "white",
        "automargin": true,
        "linecolor": "white"
      },
      "hovermode": "closest",
      "paper_bgcolor": "white",
      "geo": {
        "showlakes": true,
        "showland": true,
        "landcolor": "#E5ECF6",
        "bgcolor": "white",
        "subunitcolor": "white",
        "lakecolor": "white"
      },
      "colorscale": {
        "sequential": [
          [
            0.0,
            "#0d0887"
          ],
          [
            0.1111111111111111,
            "#46039f"
          ],
          [
            0.2222222222222222,
            "#7201a8"
          ],
          [
            0.3333333333333333,
            "#9c179e"
          ],
          [
            0.4444444444444444,
            "#bd3786"
          ],
          [
            0.5555555555555556,
            "#d8576b"
          ],
          [
            0.6666666666666666,
            "#ed7953"
          ],
          [
            0.7777777777777778,
            "#fb9f3a"
          ],
          [
            0.8888888888888888,
            "#fdca26"
          ],
          [
            1.0,
            "#f0f921"
          ]
        ],
        "diverging": [
          [
            0,
            "#8e0152"
          ],
          [
            0.1,
            "#c51b7d"
          ],
          [
            0.2,
            "#de77ae"
          ],
          [
            0.3,
            "#f1b6da"
          ],
          [
            0.4,
            "#fde0ef"
          ],
          [
            0.5,
            "#f7f7f7"
          ],
          [
            0.6,
            "#e6f5d0"
          ],
          [
            0.7,
            "#b8e186"
          ],
          [
            0.8,
            "#7fbc41"
          ],
          [
            0.9,
            "#4d9221"
          ],
          [
            1,
            "#276419"
          ]
        ],
        "sequentialminus": [
          [
            0.0,
            "#0d0887"
          ],
          [
            0.1111111111111111,
            "#46039f"
          ],
          [
            0.2222222222222222,
            "#7201a8"
          ],
          [
            0.3333333333333333,
            "#9c179e"
          ],
          [
            0.4444444444444444,
            "#bd3786"
          ],
          [
            0.5555555555555556,
            "#d8576b"
          ],
          [
            0.6666666666666666,
            "#ed7953"
          ],
          [
            0.7777777777777778,
            "#fb9f3a"
          ],
          [
            0.8888888888888888,
            "#fdca26"
          ],
          [
            1.0,
            "#f0f921"
          ]
        ]
      },
      "yaxis": {
        "gridcolor": "white",
        "zerolinewidth": 2,
        "title": {
          "standoff": 15
        },
        "ticks": "",
        "zerolinecolor": "white",
        "automargin": true,
        "linecolor": "white"
      },
      "shapedefaults": {
        "line": {
          "color": "#2a3f5f"
        }
      },
      "font": {
        "color": "#2a3f5f"
      },
      "annotationdefaults": {
        "arrowhead": 0,
        "arrowwidth": 1,
        "arrowcolor": "#2a3f5f"
      },
      "plot_bgcolor": "#E5ECF6",
      "title": {
        "x": 0.05
      },
      "coloraxis": {
        "colorbar": {
          "ticks": "",
          "outlinewidth": 0
        }
      },
      "hoverlabel": {
        "align": "left"
      },
      "mapbox": {
        "style": "light"
      },
      "polar": {
        "angularaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "bgcolor": "#E5ECF6",
        "radialaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        }
      },
      "autotypenumbers": "strict",
      "ternary": {
        "aaxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "bgcolor": "#E5ECF6",
        "caxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        },
        "baxis": {
          "gridcolor": "white",
          "ticks": "",
          "linecolor": "white"
        }
      },
      "scene": {
        "xaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        },
        "zaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        },
        "yaxis": {
          "gridcolor": "white",
          "gridwidth": 2,
          "backgroundcolor": "#E5ECF6",
          "ticks": "",
          "showbackground": true,
          "zerolinecolor": "white",
          "linecolor": "white"
        }
      },
      "colorway": [
        "#636efa",
        "#EF553B",
        "#00cc96",
        "#ab63fa",
        "#FFA15A",
        "#19d3f3",
        "#FF6692",
        "#B6E880",
        "#FF97FF",
        "#FECB52"
      ]
    }
  },
  "legend": {
    "y": 1.15,
    "x": 0.7
  },
  "margin": {
    "l": 50,
    "b": 50,
    "r": 50,
    "t": 60
  },
  "title": "Penguins",
  "yaxis": {
    "showgrid": true,
    "title": {
      "text": "Weight"
    }
  }
}

Обратите внимание, что мы получили точно такой же вывод, как и раньше, но нам не пришлось вручную строить Dict или добавлять xaxis_ или legend_ в качестве префиксов к нескольким аргументам.

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

Новая возможность в версии 0.6.0

Вы можете создавать линии, используя столбцы любого подтипа для типа AbstractDataFrame (например, типа DataFrame из DataFrames.jl).

Для демонстрации этой функциональности загрузим известный набор данных ирисов:

julia> using DataFrames, RDatasets

julia> iris = dataset("datasets", "iris");

julia> first(iris, 10)
10×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│     │ Float64     │ Float64    │ Float64     │ Float64    │ Cat…    │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────┤
│ 1   │ 5.1         │ 3.5        │ 1.4         │ 0.2        │ setosa  │
│ 2   │ 4.9         │ 3.0        │ 1.4         │ 0.2        │ setosa  │
│ 3   │ 4.7         │ 3.2        │ 1.3         │ 0.2        │ setosa  │
│ 4   │ 4.6         │ 3.1        │ 1.5         │ 0.2        │ setosa  │
│ 5   │ 5.0         │ 3.6        │ 1.4         │ 0.2        │ setosa  │
│ 6   │ 5.4         │ 3.9        │ 1.7         │ 0.4        │ setosa  │
│ 7   │ 4.6         │ 3.4        │ 1.4         │ 0.3        │ setosa  │
│ 8   │ 5.0         │ 3.4        │ 1.5         │ 0.2        │ setosa  │
│ 9   │ 4.4         │ 2.9        │ 1.4         │ 0.2        │ setosa  │
│ 10  │ 4.9         │ 3.1        │ 1.5         │ 0.1        │ setosa  │

Предположим, что необходимо построить линию рассеяния, в которой столбец SepalLength является переменной x, а столбец SepalWidth — переменной y. Для этого вызывается

julia> my_trace = scatter(iris, x=:SepalLength, y=:SepalWidth, marker_color=:red)
scatter with fields marker, type, x, and y

julia> [my_trace[:x][1:5] my_trace[:y][1:5]]
5×2 Array{Float64,2}:
 5.1  3.5
 4.9  3.0
 4.7  3.2
 4.6  3.1
 5.0  3.6

julia> my_trace[:marker_color]
:red

Как это работает? Основное правило заключается в том, что если значением любого именованного аргумента является символ Julia (т. е. созданный с помощью :something), то функция, создающая линию, проверяет, является ли этот символ одним из имен столбцов в DataFrame. Если это так, она извлекает столбец из DataFrame и задает его в качестве значения для именованного аргумента. В противном случае символ передается напрямую.

В приведенном выше примере при конструировании my_trace в качестве значения именованного аргумента x был задан символ :SepalLength. Он совпал с именем столбца iris, поэтому этот столбец был извлечен и заменен :SepalLength в качестве значения аргумента x. То же самое относится к y и SepalWidth.

Однако при задании marker_color=:red мы обнаружили, что :red не является одним из имен столбцов, поэтому значением именованного аргумента marker_color осталось :red.

Интерфейс DataFrame становится более полезным при построении целых графиков. Дополнительные сведения см. в разделе о вспомогательных методах.

Новая возможность в версии 0.9.0

Начиная с версии 0.9.0 можно создавать группы линий, используя API DataFrame. Лучше всего это можно понять на примере, поэтому давайте посмотрим, как это работает:

julia> iris = dataset("datasets", "iris");

julia> unique(iris[:Species])
3-element Array{String,1}:
 "setosa"
 "versicolor"
 "virginica"

julia> traces = scatter(
           iris, group=:Species, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8
       )
3-element Array{GenericTrace,1}:
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:x => [5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9  …  5.0, 4.5, 4.4, 5.0, 5.1, 4.8, 5.1, 4.6, 5.3, 5.0],:mode => "markers",:y => [3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1  …  3.5, 2.3, 3.2, 3.5, 3.8, 3.0, 3.8, 3.2, 3.7, 3.3],:type => "scatter",:name => CategoricalValue{String,UInt8} "setosa",:marker => Dict{Any,Any}(:size => 8)))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:x => [7.0, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2  …  5.5, 6.1, 5.8, 5.0, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7],:mode => "markers",:y => [3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7  …  2.6, 3.0, 2.6, 2.3, 2.7, 3.0, 2.9, 2.9, 2.5, 2.8],:type => "scatter",:name => CategoricalValue{String,UInt8} "versicolor",:marker => Dict{Any,Any}(:size => 8)))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:x => [6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2  …  6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9],:mode => "markers",:y => [3.3, 2.7, 3.0, 2.9, 3.0, 3.0, 2.5, 2.9, 2.5, 3.6  …  3.1, 3.1, 2.7, 3.2, 3.3, 3.0, 2.5, 3.0, 3.4, 3.0],:type => "scatter",:name => CategoricalValue{String,UInt8} "virginica",:marker => Dict{Any,Any}(:size => 8)))

julia> [t[:name] for t in traces]
3-element CategoricalArray{String,1,UInt8}:
 "setosa"
 "versicolor"
 "virginica"

Обратите внимание, что в DataFrame iris есть три компонента Species, и при передаче group=:Species в scatter мы получили три линии.

Можно передать Vector{Symbol} в качестве группы, чтобы разбить данные о значении на несколько столбцов:

julia> tips = dataset("reshape2", "tips");

julia> unique(tips[:Sex])
2-element Array{String,1}:
 "Female"
 "Male"

julia> unique(tips[:Day])
4-element Array{String,1}:
 "Sun"
 "Sat"
 "Thur"
 "Fri"

julia> traces = violin(tips, group=[:Sex, :Day], x=:TotalBill, orientation="h")
8-element Array{GenericTrace,1}:
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Female, Fri)",:orientation => "h",:x => [5.75, 16.32, 22.75, 11.35, 15.38, 13.42, 15.98, 16.27, 10.09]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Female, Sat)",:orientation => "h",:x => [20.29, 15.77, 19.65, 15.06, 20.69, 16.93, 26.41, 16.45, 3.07, 17.07  …  10.59, 10.63, 12.76, 13.27, 28.17, 12.9, 30.14, 22.12, 35.83, 27.18]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Female, Sun)",:orientation => "h",:x => [16.99, 24.59, 35.26, 14.83, 10.33, 16.97, 10.29, 34.81, 25.71, 17.31, 29.85, 25.0, 13.39, 16.21, 17.51, 9.6, 20.9, 18.15]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Female, Thur)",:orientation => "h",:x => [10.07, 34.83, 10.65, 12.43, 24.08, 13.42, 12.48, 29.8, 14.52, 11.38  …  18.64, 11.87, 19.81, 43.11, 13.0, 12.74, 13.0, 16.4, 16.47, 18.78]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Male, Fri)",:orientation => "h",:x => [28.97, 22.49, 40.17, 27.28, 12.03, 21.01, 12.46, 12.16, 8.58, 13.42]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Male, Sat)",:orientation => "h",:x => [20.65, 17.92, 39.42, 19.82, 17.81, 13.37, 12.69, 21.7, 9.55, 18.35  …  15.69, 11.61, 10.77, 15.53, 10.07, 12.6, 32.83, 29.03, 22.67, 17.82]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Male, Sun)",:orientation => "h",:x => [10.34, 21.01, 23.68, 25.29, 8.77, 26.88, 15.04, 14.78, 10.27, 15.42  …  34.63, 34.65, 23.33, 45.35, 23.17, 40.55, 20.69, 30.46, 23.1, 15.69]))
 GenericTrace{Dict{Symbol,Any}}(Dict{Symbol,Any}(:type => "violin",:name => "(Male, Thur)",:orientation => "h",:x => [27.2, 22.76, 17.29, 19.44, 16.66, 32.68, 15.98, 13.03, 18.28, 24.71  …  9.78, 7.51, 28.44, 15.48, 16.58, 7.56, 10.34, 13.51, 18.71, 20.53]))

julia> [t[:name] for t in traces]
8-element Array{String,1}:
 "(Female, Fri)"
 "(Female, Sat)"
 "(Female, Sun)"
 "(Female, Thur)"
 "(Male, Fri)"
 "(Male, Sat)"
 "(Male, Sun)"
 "(Male, Thur)"

Также в версии 0.9.0 при использовании API DataFrame разрешено передавать функцию в качестве значения именованного аргумента. При построении каждой линии значение будет заменено путем вызова функции для любого используемого DataFrame. При использовании в сочетании с аргументом group это позволяет быстро вычислять специфические для группы атрибуты линии.

Дополнительные сведения см. в docstring для GenericTrace и пример violin_side_by_side на странице примеров Violin.

Грани

Новая возможность в PlotlyBase версии 0.6.5 (PlotlyJS версии 0.16.4)

При построении графика DataFrame (назовем его df) именованные аргументы facet_row и facet_col позволяют создать матрицу подграфиков. Строки этой матрицы соответствуют unique(df[:facet_row]), где :facet_row — это заполнитель для фактического значения, переданного в качестве аргумента facet_row. Аналогично, столбцы матрицы подграфиков поступают из unique(df[:facet_col]).

Каждый подграфик будет иметь одинаковую структуру, определяемую именованными аргументами, переданными plot, но одновременно будет показывать данные только для одного значения facet_row и facet_col.

Ниже приведен соответствующий пример.

julia> using PlotlyJS, CSV, DataFrames


julia> df = dataset(DataFrame, "tips")
244×7 DataFrame
 Row │ total_bill  tip      sex      smoker   day      time     size
     │ Float64     Float64  String7  String3  String7  String7  Int64
─────┼────────────────────────────────────────────────────────────────
   1 │      16.99     1.01  Female   No       Sun      Dinner       2
   2 │      10.34     1.66  Male     No       Sun      Dinner       3
   3 │      21.01     3.5   Male     No       Sun      Dinner       3
   4 │      23.68     3.31  Male     No       Sun      Dinner       2
   5 │      24.59     3.61  Female   No       Sun      Dinner       4
   6 │      25.29     4.71  Male     No       Sun      Dinner       4
   7 │       8.77     2.0   Male     No       Sun      Dinner       2
   8 │      26.88     3.12  Male     No       Sun      Dinner       4
  ⋮  │     ⋮          ⋮        ⋮        ⋮        ⋮        ⋮       ⋮
 238 │      32.83     1.17  Male     Yes      Sat      Dinner       2
 239 │      35.83     4.67  Female   No       Sat      Dinner       3
 240 │      29.03     5.92  Male     No       Sat      Dinner       3
 241 │      27.18     2.0   Female   Yes      Sat      Dinner       2
 242 │      22.67     2.0   Male     Yes      Sat      Dinner       2
 243 │      17.82     1.75  Male     No       Sat      Dinner       2
 244 │      18.78     3.0   Female   No       Thur     Dinner       2
                                                      229 rows omitted

julia> plot(
           df, x=:total_bill, y=:tip, xbingroyp="x", ybingroup="y", kind="histogram2d",
           facet_row=:sex, facet_col=:smoker
       )
data: [
  "histogram2d with fields type, x, xaxis, xbingroyp, y, yaxis, and ybingroup",
  "histogram2d with fields type, x, xaxis, xbingroyp, y, yaxis, and ybingroup",
  "histogram2d with fields type, x, xaxis, xbingroyp, y, yaxis, and ybingroup",
  "histogram2d with fields type, x, xaxis, xbingroyp, y, yaxis, and ybingroup"
]

layout: "layout with fields annotations, legend, margin, template, xaxis, xaxis2, xaxis3, xaxis4, yaxis, yaxis2, yaxis3, and yaxis4"