Altair通过binding_range滑块针对日期时间值进行的选择和transform_filter似乎不适用于相等条件或选择器本身

问题描述

我想将范围滑块与日期时间值绑定在一起,以便仅针对特定日期的数据过滤图表。使用库存数据,我要做的是让x轴显示公司,而y轴则让用户通过范围滑块选择的特定日期的股票价格。>

基于this answer和此issue的输入,我有以下代码显示了一些内容 当滑块在一个特定值(带有transform_filter中的不相等条件)之后移动时,其余部分为空。 特有的是,如果我有不等式运算符,那么至少它会显示某些内容,但是当其== 时,所有内容均为空。

import altair as alt
from vega_datasets import data

source = data.stocks()

def timestamp(t):
  return pd.to_datetime(t).timestamp()

slider = alt.binding_range(step=86400,min=timestamp(min(source['date'])),max=timestamp(max(source['date']))) #86400 is the difference b/w consequetive days

select_date = alt.selection_single(fields=['date'],bind=slider,init={'date': timestamp(min(source['date']))})

alt.Chart(source).mark_bar().encode(
    x='symbol',y='price',).add_selection(select_date).transform_filter(alt.datum.date == select_date.date)

由于输出为空,我倾向于断定是transform_filter引起了问题,但是我已经处理了6个多小时,并尝试了使用{{1 }}和其他转换,但我无法正常工作。

还尝试了alt.expr.toDatetransform_filter(select_date.date)以及其他操作,但没有任何效果

预期的输出是,条形的高度随着用户拖动滑块而改变(由于数据已按日期过滤)

任何帮助将不胜感激。

解决方法

这里有几个问题:

  • 在Vega-Lite中,时间戳以毫秒而不是秒为单位
  • 您正在过滤数字时间戳和日期的字符串表示形式之间的相等性。
  • 即使您在过滤器表达式中解析日期,Python日期解析和Javascript日期解析的行为也有所不同,结果通常不会匹配。即使在javascript中,日期解析行为也可能因浏览器而异;所有这些都意味着在过滤Python和Javascript时间戳相等性方面通常存在问题
  • 您使用的数据具有每月时间戳记,因此滑块步骤应说明这一点

牢记所有这些,最好的方法可能是调整滑块值并根据匹配的年份和月份进行过滤,而不是尝试在确切的时间戳中实现均等。结果看起来像这样:

import altair as alt
from vega_datasets import data
import pandas as pd

source = data.stocks()

def timestamp(t):
  return pd.to_datetime(t).timestamp() * 1000

slider = alt.binding_range(
    step=30 * 24 * 60 * 60 * 1000,# 30 days in milliseconds
    min=timestamp(min(source['date'])),max=timestamp(max(source['date'])))

select_date = alt.selection_single(
    fields=['date'],bind=slider,init={'date': timestamp(min(source['date']))},name='slider')

alt.Chart(source).mark_bar().encode(
    x='symbol',y='price',).add_selection(select_date).transform_filter(
    "(year(datum.date) == year(slider.date[0])) && "
    "(month(datum.date) == month(slider.date[0]))"
)

您可以在这里查看结果:vega editor