用 Altair mark_line 绘制闭环不重复数据

Drawing a closed loop with Altair mark_line without repeating data

参见 this example and 。我还想在 Altair 中用 mark_line 绘制一个闭环。但是,我目前正在简化我的代码以提高数据效率,这是我遇到的问题。

我有一个 x 和 y 数据集,我将其绘制为散点图。然后我有一个点索引列表,我想将其与一条自身闭合的线连接起来。我之前通过在索引上执行 .loc[] 来创建一个新数据框并使用 mark_lineorder=False 来完成此操作。然而,这增加了我的绘图的大小,因为 returned .loc[] 数据帧作为第二个 data 对象存储在规范中,重复主数据集中的数据。

我认为在不定义新数据框的情况下绘制这条线的“正确”方法是创建一个新列用作 order 参数并使用 transform_filter 减少到仅相关指标。但是,这会使我的行短了一段,因为如果不重复整行我就无法 return 开始(就像我在 .loc[] 解决方案中所做的那样)。

有什么方法可以在不创建新数据对象的情况下关闭这条线吗?我也不希望将重复的行添加到起始数据框中,因为它也被用于呈现完整的散点图(和其他一些绘图对象)。我现在最好的想法是使用第二个 mark_line 但这次 transform_filter 只包含 first/last 索引,但这看起来很笨拙。

以下代码显示了我为此使用的旧方法/新方法示例,在一个小得多的数据集上(效率并不重要)。

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

# create data
df = pd.DataFrame()
np.random.seed(3)
df['x_data'] = np.random.randint(0,100,(20,))
df['y_data'] = np.random.randint(0,100,(20,))
df = df.reset_index()

# example array of indexes (note that 4 is first and last: the line returns to its start)
line_indexes = [4, 10, 3, 14, 11, 4]

# create scatterplot
scatter_base = alt.Chart(df)
scatter = scatter_base.mark_point().encode(x='x_data', y='y_data')
# create line on a .loc of the same data
line_base = alt.Chart(df.loc[line_indexes])
line = line_base.mark_line(order=False).encode(x='x_data', y='y_data')
# layer
plot_v1 = alt.layer(scatter, line)

# add order column
df['line_order'] = 0
for i, idx in enumerate(line_indexes):
    df.loc[idx, 'line_order'] = i
# create scatterplot
scatter_base = alt.Chart(df)
scatter = scatter_base.mark_point().encode(x='x_data', y='y_data')
# create line with a filter transform and order encoding
line = scatter_base.transform_filter(alt.datum.line_order > 0).mark_line().encode(x='x_data', y='y_data', order='line_order')
# layer
plot_v2 = alt.layer(scatter, line)

Plot_v1 输出:

Plot_v2 输出:

您可以在 plot_v2 示例中使用 .mark_line(interpolate='linear-closed') 形成多边形。 More info on different interpolation modes can be found in the docs.