Holoviews: как настроить гистограмму для графиков кривых связанных временных рядов

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

У меня есть ряд временных рядов в текстовых файлах, загруженных как Pandas DataFrames, где:

каждый файл предназначен для определенного местоположения в каждом месте было собрано около 10 временных рядов, каждый из которых имеет около 15000 точек. Я создаю небольшой интерактивный инструмент, в котором можно использовать селектор для выбора местоположения / DataFrame, а затем другой селектор, чтобы выбрать 3 из 10 временных рядов, которые будут построены вместе.

Моя цель - разрешить связанное масштабирование (как по оси x, так и по оси y). Вопросы и код будут сосредоточены на этом аспекте инструмента. К сожалению, я не могу поделиться фактическими данными, которые использую, поскольку они являются собственностью, но я создал 3 случайных прогулки с конкретными диапазонами данных, которые согласуются с фактическими данными.

## preliminaries ##

import pandas as pd
import numpy as np
import holoviews as hv
from holoviews.util.transform import dim
from holoviews.selection import link_selections
from holoviews import opts
from holoviews.operation.datashader import shade, rasterize
import hvplot.pandas
hv.extension('bokeh', width=100)

## create random walks (one location) ##
data_df = pd.DataFrame()
npoints=15000
np.random.seed(71)
x = np.arange(npoints)
y1 = 1300+2.5*np.random.randn(npoints).cumsum()
y2 = 1500+2*np.random.randn(npoints).cumsum()
y3 = 3+np.random.randn(npoints).cumsum()
data_df.loc[:,'x'] = x
data_df.loc[:,'rand1'] = y1
data_df.loc[:,'rand2'] = y2
data_df.loc[:,'rand3'] = y3

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

data_df.hvplot(x='x',y=['rand1','rand2','rand3'],value_label='y',width=800,height=400)

hvplot

В результате, хотя подзаголовки hvplot работают из коробки (для связывания), диапазоны различаются, поэтому масштабирования здесь нет:

data_df.hvplot(x='x',y=['rand1','rand2','rand3'], 
               value_label='y',subplots=True,width=800,height=200).cols(1)

subplots

Итак, моей первой попыткой было адаптировать пример точек на основе Python из Связанной чистки в документации. :

colors = hv.Cycle('Category10').values
dims   = ['rand1', 'rand2', 'rand3']
layout = hv.Layout([
    hv.Points(data_df, dim).opts(color=c)
    for c, dim in zip(colors, [['x', d] for d in dims])
])
link_selections(layout).opts(opts.Points(width=1200, height=300)).cols(1)

Очки

Это уже потрясающий результат за 20 минут усилий!

Однако мне бы очень хотелось построить кривую, а не точки, а также увидеть гистограмму, поэтому я адаптировал синтаксис понимания для работы с Curve (после прочтения страниц документации Применение настроек и Составление элементов):

colors = hv.Cycle('Category10').values
dims   = ['rand1', 'rand2', 'rand3']
layout = hv.Layout([hv.Curve(data_df,'x',dim).opts(height=300,width=1200, 
                                                     color=c).hist(dim) for c, 
                    dim in zip(colors,[d for d in dims])])
link_selections(layout).cols(1)

lines

Это почти именно то, что я хочу. Но я все еще борюсь с разными уровнями синтаксиса opts. Вопрос 1: с учетом последнего блока кода, как мне сделать так, чтобы гистограмма разделяла цвет с кривыми?

Теперь предположим, что я хочу rasterize графики (хотя я не думаю, что это еще необходимо с 15 000 точек, как в этом случае), я попытался адаптировать первый пример с помощью Points:

cmaps = ['Blues', 'Greens', 'Reds']
dims   = ['rand1', 'rand2', 'rand3']
layout = hv.Layout([
    shade(rasterize(hv.Points(data_df, dims), 
                    cmap=c)).opts(width=1200, height = 400).hist(dims[1])
    for c, dims in zip(cmaps, [['x', d] for d in dims])
])
link_selections(layout).cols(1)

rasterized Это неплохое начало, но я снова борюсь с параметрами / настройками.

Вопрос 2: в приведенном выше блоке cod, как мне передать цветовые карты (они не работают, как сейчас), и как сделать, чтобы гистограмма отражала значения данных, как в предыдущем случае (а также иметь право палитра)?

Спасибо!


person MyCarta    schedule 17.12.2020    source источник


Ответы (2)


Чтобы ответить на ваш первый вопрос о том, чтобы гистограмма имела цвет кривой, я добавил .opts(opts.Histogram(color=c)) в ваш код.
Когда у вас есть макет, вы можете указать параметры элемента внутри макета, как это.

colors = hv.Cycle('Category10').values
dims   = ['rand1', 'rand2', 'rand3']
layout = hv.Layout(
    [hv.Curve(data_df,'x',dim)
         .opts(height=300,width=600, color=c)
         .hist(dim)
         .opts(opts.Histogram(color=c)) 
     for c, dim in zip(colors,[d for d in dims])]
)
link_selections(layout).cols(1)
person Sander van den Oord    schedule 18.12.2020
comment
почему .opts(opts.Histogram(color=c)), а не только .opts.Histogram(color=c)? - person MyCarta; 19.12.2020
comment
hv.Curve (). hist () создает AdjointLayout () с двумя типами графиков внутри: кривой и гистограммой. Чтобы изменить цвет одного из двух разных графиков внутри макета, в данном случае гистограммы, вы должны указать его так же, как я: .opts (opts.Histogram (color = c)) - person Sander van den Oord; 19.12.2020
comment
Верно; в противном случае вы могли бы сделать .opts(color=c)), но с несколькими элементами вы должны указать HoloView, к какому из них вы хотите применить цвет. Возможно, мы могли бы также поддерживать .opts.Histogram на одном уровне по вашему запросу; Не думаю, что я об этом подумал! Если это будет яснее, отправьте запрос функции. - person James A. Bednar; 06.01.2021

Сандер ответил, как раскрасить гистограмму, но что касается другого вопроса о раскрашивании графика с измененными данными, Datashader отображает ваши данные с помощью цветовой карты, а не одного цвета, поэтому параметр называется cmap, а не color. Итак, вы правильно использовали cmap в случае с данными, но (a) cmap на самом деле является параметром для shade (который выполняет цветовое отображение вывода rasterize), и (b) вам действительно не нужен shade, поскольку вы можете пусть сейчас Bokeh выполняет цветовое отображение в большинстве случаев, и в этом случае cmap является вариантом, а не аргументом. Пример:

from bokeh.palettes import Blues, Greens, Reds
cmaps = [Blues[256][200:], Greens[256][200:], Reds[256][200:]]
dims   = ['rand1', 'rand2', 'rand3']
layout = hv.Layout([
    rasterize(hv.Points(data_df, ds)).opts(cmap=c,width=1200, height = 400).hist(dims[1])
    for c, ds in zip(cmaps, [['x', d] for d in dims])
])
link_selections(layout).cols(1)

введите описание изображения здесь

person James A. Bednar    schedule 05.01.2021