Swift Charts折线图实现按月汇总销售数据问题
实现SwiftUI Chart LineMark按月显示销售额总和
要让LineMark按月展示销售额总和,你需要先手动对原始数据按月份分组并计算总和,再基于汇总后的数据绘制图表。BarMark之所以能自动汇总,是因为它在指定unit: .month时会自动合并同月份的数据,但LineMark默认会渲染每一条原始数据点,所以必须提前处理数据。
修改后的完整代码
func dailySales2() -> [(chartDate: Date, year: String, sales: Int)] { var temp: [(chartDate: Date, year: String, sales: Int)] = [] for _ in 1...500 { let dateT = Calendar.current.date(byAdding: .day, value: -Int.random(in: 1...500), to: Date())! temp.append((chartDate: dateT, year: dateT.formatted(.dateTime.year()), sales: Int.random(in: 100...500))) } return temp.sorted(by: { $0.chartDate < $1.chartDate }) } // 按月份汇总销售额的函数 func monthlySalesSummary() -> [(monthDate: Date, year: String, totalSales: Int)] { let dailyData = dailySales2() let calendar = Calendar.current // 按「年份-月份」分组原始数据 let groupedData = Dictionary(grouping: dailyData) { item in let month = calendar.component(.month, from: item.chartDate) return "\(item.year)-\(month)" } // 转换为汇总数据:计算每月销售额总和,生成月份代表日期 return groupedData.map { _, items in let firstItem = items.first! // 取当月第一天作为该月的代表日期,保证x轴刻度对齐 let monthStartDate = calendar.date(from: calendar.dateComponents([.year, .month], from: firstItem.chartDate))! let total = items.reduce(0) { $0 + $1.sales } return (monthDate: monthStartDate, year: firstItem.year, totalSales: total) } .sorted { $0.monthDate < $1.monthDate } } // 使用汇总数据绘制图表 Chart { ForEach(monthlySalesSummary(), id: \.monthDate) { summary in LineMark( x: .value("Month", summary.monthDate, unit: .month), y: .value("Total Sales", summary.totalSales) ) .foregroundStyle(by: .value("Year:", summary.year)) } }
关键说明
- 分组逻辑:用
年份-月份的字符串作为分组键,确保同一月份的数据被归为一组 - 汇总计算:对每组数据求和得到当月总销售额,同时生成当月第一天的日期作为x轴的代表值,保证图表刻度正确对齐
- 数据排序:汇总后的数据按日期排序,确保图表的时间顺序正确
内容的提问来源于stack exchange,提问作者Gizza Gander
相关产品推荐
相关产品推荐

