有没有办法创建一个散点图,其中列的子集位于 x 轴上,而不同的子集位于 y 轴上?

Is there a way to create a scatter plot where a subset of a column is on the x-axis and a different subset is on the y-axis?

我正在尝试创建一个复合图表来显示相关矩阵和散点图,显示用于计算每个相关系数的各个数据点。我希望能够根据相关矩阵中的选择过滤散点图 xy 中编码的值(例如,单击对应于 condition a 的正方形 vs condition b in the correlation matrix pulls up the scatter plot where each point are (value in condition a, 条件 b)).

中的值

我让它工作的唯一方法是首先生成一个包含所有可能的数据点对的数据框,然后在 Altair 图表中使用它。

df = pd.DataFrame(
    {
        'id': ['w', 'x', 'y', 'z', 'w', 'x', 'y', 'z', 'w', 'x', 'y', 'z'],
        'condition': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c'],
        'value': np.arange(12)
    }
)

paired_df = pd.concat(
    pd.merge(
        df.loc[df.condition == condition_x],
        df.loc[df.condition == condition_y],
        on='id'
    )
    for condition_x in ['a', 'b', 'c'] for condition_y in ['a', 'b', 'c']
)

corr = pd.DataFrame(
    {
        'condition_x': {0: 'a', 1: 'b', 2: 'c', 3: 'a', 4: 'b', 5: 'c', 6: 'a', 7: 'b', 8: 'c'},
        'condition_y': {0: 'a', 1: 'a', 2: 'a', 3: 'b', 4: 'b', 5: 'b', 6: 'c', 7: 'c', 8: 'c'},
        'r^2': {0: 1.0, 1: 1.0, 2: 1.0, 3: 1.0, 4: 1.0, 5: 1.0, 6: 1.0, 7: 1.0, 8: 1.0}
    }
)

selection = alt.selection_single(fields=['condition_x', 'condition_y'])

heatmap = alt.Chart(corr).mark_rect().encode(
    x='condition_x',
    y='condition_y',
    color='r^2',
).add_selection(selection)
heatmap

scatter = alt.Chart(paired_df).mark_circle().transform_filter(
    selection
).encode(
    x='value_x',
    y='value_y',
)

heatmap | scatter

但是,我正在使用的数据集太大,无法在没有很大性能成本的情况下进行这种成对转换。有没有更惯用的方式通过 Altair 来做到这一点?我希望我可以创建一个枢轴 table 并通过访问 condition_xcondition_y 字段的值来选择 xy 编码的列selection,但我没能找到这方面的任何例子。可能是这样的:

scatter = alt.Chart(paired_df).mark_circle().transform_pivot(
    'condition',
    groupby=['id'],
    value='value'
).encode(
    x=selection['condition_x'],
    y=selection['condition_y'],
)

执行此操作的自然方法可能是使用 transform_lookup 之类的方法,但不幸的是,它仅提供左连接语义,不提供交叉连接语义。但是深入研究 Altair 的可用转换,似乎您可以通过仔细组合 pivot transform and two fold transforms.

来做您想做的事

这是从 df 而不是 paired_df 构建的等效 scatter 图表:

scatter = alt.Chart(df).transform_pivot(
    "condition", value="value", groupby=["id"]
).transform_fold(
    ["a", "b", "c"], as_=["condition_x", "value_x"]
).transform_fold(
    ["a", "b", "c"], as_=["condition_y", "value_y"]
).mark_circle().transform_filter(
    selection
).encode(
    x='value_x:Q',
    y='value_y:Q',
)