用 Altair mark_line 绘制闭环不重复数据
Drawing a closed loop with Altair mark_line without repeating data
参见 this example and 。我还想在 Altair 中用 mark_line
绘制一个闭环。但是,我目前正在简化我的代码以提高数据效率,这是我遇到的问题。
我有一个 x 和 y 数据集,我将其绘制为散点图。然后我有一个点索引列表,我想将其与一条自身闭合的线连接起来。我之前通过在索引上执行 .loc[]
来创建一个新数据框并使用 mark_line
和 order=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.
参见 this example and mark_line
绘制一个闭环。但是,我目前正在简化我的代码以提高数据效率,这是我遇到的问题。
我有一个 x 和 y 数据集,我将其绘制为散点图。然后我有一个点索引列表,我想将其与一条自身闭合的线连接起来。我之前通过在索引上执行 .loc[]
来创建一个新数据框并使用 mark_line
和 order=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.