You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Altair/Streamlit中汇总数据制作分组条形图

实现Python+Altair版按月分组的分组条形图(对应R ggplot2效果)

问题背景

在R中可通过以下代码实现按月分组的分组条形图:

library(tidyverse)
library(lubridate)
df<-data.frame(mydate=rep(as.Date("2022-01-01")+0:90, each=10),
               mygroup=sample(c("A", "B", "C"), size=910, replace=T))
df %>% 
  mutate(mymonth=round_date(mydate, "month")) %>% 
  ggplot(aes(x=mymonth, fill=mygroup))+
  geom_bar(position = "dodge")

使用Python的Pandas、Altair与Streamlit复刻该图表时,当前代码存在以下问题:

  • 生成的是堆叠条形图,而非分组条形图
  • 尝试使用xOffset属性时出现SchemaValidationError错误
  • 数据未正确汇总,导致条形出现水平条纹且计数数值错误

当前Python代码:

import streamlit as st #version 1.14.0
import pandas as pd    #version 1.5.1
import altair as alt   #version 4.2.0

df=pd.DataFrame({'mydate':pd.date_range(start='1/1/2020', end='4/09/2020').repeat(10),
                 'mygroup':pd.Series(["A", "B", "C"]).sample(n=1000, replace=True)})

c = alt.Chart(df).transform_window(
  sort=[{'field': 'yearmonth(mydate)'}],
  cumulative_count='count(*)', # incorrect count
).mark_bar().encode(
  x='yearmonth(mydate):O',
  y='cumulative_count:Q',
  #xOffset='mygroup:N', #error
  color='mygroup'
)
st.altair_chart(c, use_container_width=True)

解决方案

1. 修正数据生成(可选,避免长度不匹配警告)

确保mygroup的长度与mydate完全一致:

date_range = pd.date_range(start='1/1/2020', end='4/09/2020')
df = pd.DataFrame({
    'mydate': date_range.repeat(10),
    'mygroup': pd.Series(["A", "B", "C"]).sample(n=len(date_range)*10, replace=True)
})

2. 正确汇总数据并实现分组条形图

使用transform_aggregate按月份和分组统计数量,再通过mark_bar(position='dodge')实现分组并排效果:

import streamlit as st
import pandas as pd
import altair as alt

# 生成数据
date_range = pd.date_range(start='1/1/2020', end='4/09/2020')
df = pd.DataFrame({
    'mydate': date_range.repeat(10),
    'mygroup': pd.Series(["A", "B", "C"]).sample(n=len(date_range)*10, replace=True)
})

# 创建分组条形图
chart = alt.Chart(df).transform_aggregate(
    count='count()',
    groupby=['yearmonth(mydate):O', 'mygroup:N']
).mark_bar(position='dodge').encode(
    x=alt.X('yearmonth(mydate):O', title='月份'),
    y=alt.Y('count:Q', title='数量'),
    color=alt.Color('mygroup:N', title='分组'),
    tooltip=['yearmonth(mydate):O', 'mygroup:N', 'count:Q']
).properties(
    title='按月分组的数量统计'
)

st.altair_chart(chart, use_container_width=True)

关键说明

  • 数据汇总:用transform_aggregate替代transform_window,按月份和分组维度准确统计每组数量,解决计数错误和条纹问题
  • 分组条形图实现:通过mark_bar(position='dodge')让同一月份下的不同分组条形并排显示,无需使用xOffset(该属性并非此场景的标准用法,且存在版本兼容性问题)
  • 优化细节:添加标题、坐标轴标签和tooltip,提升图表可读性

内容的提问来源于stack exchange,提问作者M.Viking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:20:37