我有一个TimeSeries DataFrame,我用它来创建一个热图(显示两个相关值之间最近观察到的差异)和两个折线图--一个显示序列本身,另一个显示序列之间的差异.我能够制作前两个图表,但是我不知道如何动态地计算两个所选系列之间的差额(使用.select_point()).下面是代码片段.

import pandas as pd
import numpy as np
import altair as alt

ex_ts = pd.DataFrame(
    np.random.random((10, 5)),
    columns=['a', 'b', 'c', 'd', 'e'],
    index=(pd.date_range(start=pd.to_datetime('today')-pd.Timedelta(9, unit='D'), end=pd.to_datetime('today')).strftime('%Y-%m-%d'))
)

ex_ts_long = ex_ts.stack().reset_index().set_axis(['date', 'category', 'diff'], axis=1).assign(
    x = lambda a: a['category'],
    y = lambda a: a['category']
)

print(ex_ts_long.head())

#          date category      diff  x  y
# 0  2024-03-03        a  0.910670  a  a
# 1  2024-03-03        b  0.608069  b  b
# 2  2024-03-03        c  0.797001  c  c
# 3  2024-03-03        d  0.139386  d  d
# 4  2024-03-03        e  0.147499  e  e

def get_last_diff(i):
    return ex_ts.sub(ex_ts.iloc[:,i], axis=0).iloc[-1,:]

ex_z = pd.concat([get_last_diff(i) for i in np.arange(0, 5)], axis=1).set_axis(ex_ts.columns, axis=1).stack().reset_index().set_axis(['x', 'y', 'diff'], axis=1).round(2)

print(ex_z.head())

#    x  y  diff
# 0  a  a  0.00
# 1  a  b -0.29
# 2  a  c -0.16
# 3  a  d -0.27
# 4  a  e -0.38

select_x = alt.selection_point(fields=['x'], name='select_x')
select_y = alt.selection_point(fields=['y'], name='select_y')

base = alt.Chart(ex_z).encode(x='x', y='y', color='diff').add_params(select_x).add_params(select_y).properties(width=500, height=500)

hmap = base.mark_rect()
text = base.mark_text(fontWeight='bold').encode(text='diff', color=alt.value('red'))
hmap_chart = (hmap + text)

line_1 = alt.Chart(ex_ts_long).mark_line().encode(x='date', y='diff', color='category').transform_filter(select_x | select_y)

tmp = alt.vconcat(hmap_chart, line_1)

上面的代码创建了一个热图,您可以单击该热图来过滤底部的图表.然而,问题是,我想计算第一个折线图中两个序列之间的差异,并将其绘制出来.

最有希望的try 是通过将两个过滤后的图表添加到一起来创建一个新图表.我在两个过滤后的图表中进行了聚合,以便可以引用新变量来创建我要查找的变量,但这似乎不起作用.下面是更多示例代码.

rhs_line1 = alt.Chart(df_long).mark_line().transform_filter(select_y).transform_aggregate(
    agg_y = 'sum(spread)', groupby=['date']
).encode(x='date:T', y='agg_y:Q')

rhs_line2 = alt.Chart(df_long).mark_line().transform_filter(select_x).transform_aggregate(
    agg_x = 'sum(spread)', groupby=['date']
).encode(x='date:T', y='agg_x:Q')

rhs_line =(rhs_line1 + rhs_line1).transform_calculate(spread = 'datum.agg_y - datum.agg_x').encode(x='date:T', y='spread:Q')

final = alt.vconcat(hmap_chart, alt.hconcat(line_1, rhs_line))

推荐答案

当涉及到转换时,很难对数据发生的情况进行故障排除.我可以很有帮助的使用.transformed_data()的方法在牛郎星的图表上,或点击右上角的三点菜单,然后"在织女星编辑器中打开图表",并在"数据查看器"选项卡中查看数据是如何变化的,因为你做出了 Select .

这样做,我可以看到spread在您的例子中实际上是未定义的,因为分层图表的数据没有合并在一起;相反,有两个数据框,一个包含agg_y,另一个包含agg_x,因此不可能在计算转换中执行agg_x - agg_y.我不确定是否有一种方法可以合并这些数据,但无论是哪种方式,我都不认为您想要这样做,因为您的数据是如何组织的.

由于您想要彼此相减两列,我认为更简单的方法是透视数据框,然后根据 Select 动态确定要相减的列,您可以执行以下操作:

dynamic_title = alt.Title(alt.expr(f'"Difference between " + {select_x.name}.x + " and " + {select_y.name}.y'))
rhs_line = alt.Chart(ex_ts_long, title=dynamic_title).transform_pivot(
    'category', 'diff', groupby=['date']
).transform_calculate(
    spread = f'datum[{select_x.name}.x] - datum[{select_y.name}.y]'
).mark_line(color='grey').encode(
    x='date',
    y=alt.Y('spread:Q').scale(domain=(-1, 1)),
)

alt.vconcat(
    hmap_chart,
    alt.hconcat(line_1, rhs_line).resolve_scale(color='independent')
)

enter image description here

Python相关问答推荐

acme错误-Veritas错误:模块收件箱没有属性linear_util'

从收件箱中的列中删除html格式

为什么带有dropna=False的groupby会阻止后续的MultiIndex.dropna()工作?

如何使用html从excel中提取条件格式规则列表?

无法通过python-jira访问jira工作日志(log)中的 comments

如何在Python中并行化以下搜索?

从groupby执行计算后创建新的子框架

Python—从np.array中 Select 复杂的列子集

Pandas计数符合某些条件的特定列的数量

如何在Python中找到线性依赖mod 2

有没有一种ONE—LINER的方法给一个框架的每一行一个由整数和字符串组成的唯一id?

多处理队列在与Forking http.server一起使用时随机跳过项目

如何使用SentenceTransformers创建矢量嵌入?

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?

如何杀死一个进程,我的Python可执行文件以sudo启动?

jsonschema日期格式

需要帮助使用Python中的Google的People API更新联系人的多个字段'

如何在Python中自动创建数字文件夹和正在进行的文件夹?

如何在Polars中将列表中的新列添加到现有的数据帧中?

Pandas 数据框自定义排序功能