Линии — Line

Примитив line соединяет точки данных линией. Он часто показывает траектории и изменения во времени. В отличие от большинства примитивов, где каждому соответствует один элемент данных, одна линия представляет несколько элементов, подобно area и trail.

Для отрезков от (x,y) до (x2,y2) используйте rule. Для непрерывных линий переменной толщины используйте trail.

Свойства линий

Определение line поддерживает любые стандартные свойства, а также свойства интерполяции и наложения точек:

Нажмите, чтобы показать таблицу
СвойствоТипОписание
orientOrientation

Ориентация диаграмм bar без накопления, tick, area и line: horizontal, используемая по умолчанию, либо vertical. Для bar, rule и tick определяет, к x или y применяется размер. Для area задаёт orient результата Vega. Для line и trail определяет порядок сортировки точек, если config.sortLineBy не задан. При накоплении ориентация определяется самим накоплением, и явно заданное значение игнорируется.

interpolateanyOf(Interpolate, ExprRef)

Способ интерполяции линий и областей:

  • "linear" — последовательность прямых отрезков.
  • "linear-closed" — замкнутые отрезки, образующие многоугольник.
  • "step" — чередующиеся горизонтальные и вертикальные отрезки.
  • "step-before" — чередующиеся вертикальные и горизонтальные отрезки.
  • "step-after" — чередующиеся горизонтальные и вертикальные отрезки.
  • "basis" — B-сплайн с дублированием крайних контрольных точек.
  • "basis-open" — открытый B-сплайн, который может не проходить через начало или конец.
  • "basis-closed" — замкнутый B-сплайн.
  • "cardinal" — кардинальный сплайн с дублированием крайних контрольных точек.
  • "cardinal-open" — открытый кардинальный сплайн: может не проходить через начало и конец, но проходит через остальные контрольные точки.
  • "cardinal-closed" — замкнутый кардинальный сплайн.
  • "bundle" — аналог basis, но tension используется для выпрямления сплайна.
  • "monotone" — кубическая интерполяция, сохраняющая монотонность по y.
tensionanyOf(number, ExprRef)

Параметр натяжения для line и area, в зависимости от типа интерполяции.

pointanyOf(boolean, OverlayMarkDef, string)

Флаг добавления точек поверх line или area либо объект свойств этих точек. При "transparent" добавляются прозрачные точки для улучшения подсказок и выбора; при {} или true — заполненные точки со стандартными свойствами; при false точки автоматически не добавляются. По умолчанию: false.

Примеры

Линейная диаграмма

Временное или порядковое поле, обычно по x, и количественное поле, обычно по y, создают простую диаграмму с одной линией:

import altair as alt
from altair import datum
from altair.datasets import data


source = data.stocks()

alt.Chart(source).mark_line().encode(
    x="date",
    y="price",
).transform_filter(datum.symbol == "GOOG")

Несколько линий можно создать группировкой по атрибутам, например color или detail.

Несколько рядов с разным цветом

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

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line().encode(
    x="date",
    y="price",
    color="symbol",
)

Можно добавить выбор, чтобы выделять линию при наведении:

import altair as alt
from altair.datasets import data

source = data.stocks()

highlight = alt.selection_point(
    on="pointerover", fields=["symbol"], nearest=True
)

base = alt.Chart(source).encode(
    x="date:T",
    y="price:Q",
    color="symbol:N"
)

points = base.mark_circle().encode(
    opacity=alt.value(0)
).add_params(
    highlight
).properties(
    width=600
)

lines = base.mark_line().encode(
    size=alt.when(~highlight).then(alt.value(1)).otherwise(alt.value(3))
)

points + lines

Несколько рядов с разными штрихами

Поле в strokeDash также создаёт многорядную диаграмму:

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line().encode(
    x="date",
    y="price",
    strokeDash="symbol",
)

Группировка позволяет создавать линию из нескольких частей с разными стилями:

import altair as alt
import pandas as pd

source = pd.DataFrame({
    "a": ["A", "B", "D", "E", "E", "G", "H"],
    "b": [28, 55, 91, 81, 81, 19, 87],
    "predicted": [False, False, False, False, True, True, True]
})

alt.Chart(source).mark_line().encode(
    x="a:O",
    y="b:Q",
    strokeDash="predicted:N"
)

Несколько рядов через канал Detail

Чтобы сгруппировать линии по полю, не кодируя его визуальным свойством, используйте detail. Получатся несколько линий одного цвета:

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line().encode(
    x="date",
    y="price",
    detail="symbol",
)

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

import altair as alt
from altair.datasets import data

source = data.countries()

base = alt.Chart(source).encode(
    alt.X("life_expect:Q")
        .scale(zero=False)
        .title("Life Expectancy (years)"),
    alt.Y("country:N")
        .axis(offset=5, ticks=False, minExtent=70, domain=False)
        .title("Country")
).transform_filter(
    alt.FieldOneOfPredicate(field="country", oneOf=["China", "India", "United States", "Indonesia", "Brazil"])
)


line = base.mark_line().encode(
    detail="country",
    color=alt.value("#db646f")
).transform_filter(
    alt.FieldOneOfPredicate(field="year", oneOf=[1995, 2000])
)

point = base.mark_point(filled=True).encode(
    alt.Color("year").scale(range=["#e6959c", "#911a24"], domain=[1995, 2000]),
    size=alt.value(100),
    opacity=alt.value(1),
)

line + point

Линия с маркерами точек

Свойство point=True или объект свойств наложенных точек добавляет маркеры поверх линии:

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line(point=True).encode(
    x="year(date)",
    y="mean(price):Q",
    color="symbol:N"
)

Это эквивалентно дополнительному слою заполненных точек. По умолчанию наложенные точки имеют opacity=1, в отличие от полупрозрачных обычных точек.

Здесь создаются точки с обводкой: filled=False и fill="white":

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line(
    point=alt.OverlayMarkDef(filled=False, fill="white")
).encode(
    x="year(date)",
    y="mean(price):Q",
    color="symbol:N"
)

Пользовательский порядок

По умолчанию путь линии определяется значениями временного или порядкового поля. Канал order позволяет задать другой порядок.

Например, покажем изменение связи между ценой бензина и пробегом на душу населения во времени. Через order сортируем точки по году; свойство point отмечает каждую точку на линии. Самая ранняя точка, 1956 год, становится одним концом линии, а последняя, 2010 год, — другим:

import altair as alt
from altair.datasets import data

source = data.driving()

alt.Chart(source).mark_line(point=True).encode(
    alt.X("miles").scale(zero=False),
    alt.Y("gas").scale(zero=False),
    order="year",
    tooltip=["miles", "gas", "year"],
)

Интерполяция линий

Свойство interpolate задаёт способ интерполяции. Например, можно выбрать "monotone":

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line(interpolate="monotone").encode(
    x="date",
    y="price",
).transform_filter(
    alt.datum.symbol == "GOOG"
)

"step-after" создаёт ступенчатую диаграмму:

import altair as alt
from altair.datasets import data

source = data.stocks()

alt.Chart(source).mark_line(interpolate="step-after").encode(
    x="date",
    y="price"
).transform_filter(
    alt.datum.symbol == "GOOG"
)

Географические линии

Сопоставление координат каналам longitude и latitude выбранной проекции позволяет проводить линии через географические точки:

import altair as alt
from altair.datasets import data
import pandas as pd

airports = data.airports.url
flights_airport = data.flights_airport.url

states = alt.topo_feature(data.us_10m.url, feature="states")

lookup_data = alt.LookupData(
    airports, key="iata", fields=["state", "latitude", "longitude"]
)

source = pd.DataFrame({
    "airport": ["SEA", "SFO", "LAX", "LAS", "DFW", "DEN", "ORD", "JFK"],
    "order": [1, 2, 3, 4, 5, 6, 7, 8],
})

background = alt.Chart(states).mark_geoshape(
    fill="lightgray",
    stroke="white"
).properties(
    width=750,
    height=500,
).project("albersUsa")

line = alt.Chart(source).mark_line().encode(
    latitude="latitude:Q",
    longitude="longitude:Q",
    order="order"
).transform_lookup(
    lookup="airport",
    from_=lookup_data
)

background + line