0

我正在可视化具有例如分类字段和时间字段的数据集。我想创建一个条形图,显示不同类别的时间分布,根据它们的基数按“升序”/“降序”顺序排序。这可以通过以下方式简单地实现altair

import pandas as pd
import altair as alt

data = {0:{'Name':'Mary', 'Sport':'Tennis', 'competition':'2018/06/01'},
    1:{'Name':'Cal', 'Sport':'Tennis','competition':'2018/06/05'},
    2:{'Name':'John', 'Sport':'Tennis','competition':'2018/05/28'},
    3:{'Name':'Jane', 'Sport':'Tennis','competition':'2018/05/20'},
    4:{'Name':'Bob', 'Sport':'Golf','competition':'2018/03/01'},
    5:{'Name':'Jerry', 'Sport':'Golf','competition':'2018/03/03'},
    6:{'Name':'Gustavo', 'Sport':'Golf','competition':'2018/02/28'},
    7:{'Name':'Walter', 'Sport':'Swimming','competition':'2018/01/01'},
    8:{'Name':'Jessy', 'Sport':'Swimming','competition':'2018/01/03'},
    9:{'Name':'Patric', 'Sport':'Running','competition':'2018/02/01'},
    10:{'Name':'John', 'Sport':'Shooting','competition':'2018/04/01'}}

df = pd.DataFrame(data).T

alt.Chart(df).mark_tick().encode(
    x='yearmonthdate(competition):T',
    y=alt.Y('Sport:N',
        sort=alt.SortField(field='count(Sport:N)', order='ascending', op='sum')
    ),
)

条形图

现在假设我只对前三个数量最多的类别感兴趣。遵循“ Altair/Vega-Lite bar chart: filter top K bars from aggregated field ”的公认解决方案,这次绘图没有显示:

alt.Chart(df).mark_tick().encode(
    x='yearmonthdate(competition):T',
    y=alt.Y('Sport:N',
        sort=alt.SortField(field='count', order='ascending', op='sum')
    ),
).transform_aggregate(
    count='count()',
    groupby=['Sport']
).transform_window(
    window=[{'op': 'rank', 'as': 'rank'}],
    sort=[{'field': 'count', 'order': 'descending'}]
).transform_filter('datum.rank <= 3')

过滤条形图

请注意,即使是 y-labels 顺序也不如预期。

4

1 回答 1

0

更深入地阅读(和理解)文档,我想我可以说我所问的目前(2018 年 6 月)对于altair/是不可行的Vega-Lite。这是我的解释...

对数据执行聚合转换,相当于GROUP BY在 SQL 查询中添加子句,因此我们不再能够将任何“未聚合”形式的“原始”数据字段关联到编码通道:当我尝试competition在因此,x这是频道undefined

我可以尝试使用查找转换“自我加入”,但即使在这种情况下,最终结果也不是我想要的,因为这相当于 a left join,所以我只为每个聚合类获得一个值。

alt.Chart(df).mark_tick().encode(
    x=alt.X(field='competition',type='temporal', timeUnit='yearmonthdate'),
    y=alt.Y('Sport:N',
        sort=alt.SortField(field='count', order='ascending', op='sum')
    ),
).transform_aggregate(
    countX='count()',
    groupby=['Sport']
).transform_window(
    window=[{'op': 'rank', 'as': 'rank'}],
    sort=[{'field': 'countX', 'order': 'descending'}]
).transform_filter('datum.rank <= 3').transform_lookup(
    lookup='Sport',
    from_=alt.LookupData(data=df, key='Sport',
                         fields=['competition'])
)

加入后的情节

我发现实现我想要的结果所必需的,目前在 nor 中得到支持,Vega但在Vega-Litenor中不支持Altair:它是JoinAggregate转换,它使用一个或多个聚合的结果“扩展”原始数据。

对于以下输入数据:

[
  {"foo": 1, "bar": 1},
  {"foo": 1, "bar": 2},
  {"foo": null, "bar": 3}
]

连接聚合变换:

{
  "type": "joinaggregate",
  "fields": ["foo", "bar", "bar"],
  "ops": ["valid", "sum", "median"],
  "as": ["v", "s", "m"]
}

产生输出:

[
  {"foo": 1, "bar": 1, "v": 2, "s": 6, "m": 2},
  {"foo": 1, "bar": 2, "v": 2, "s": 6, "m": 2},
  {"foo": null, "bar": 3, "v": 2, "s": 6, "m": 2}
]
于 2018-06-20T18:24:50.597 回答