Sponsor Link
環境&対象
- macOS15.1 Sequoia
- Xcode 16.1 Beta3
- iOS 18.2 beta
- Swift 5.9
Charts
Apple が提供する グラフを表示するためのフレームワークです。
参考
Swift ChartsApple Developer Documentation
以前、概要説明の記事を書きました。
[SwiftUI][Charts] Charts で 折れ線グラフを表示する方法
複数系列のデータを同じチャートに表示する
数値をグラフに表示することだけでも、ずいぶんわかりやすくなりますが、複数の系列のデータを同じグラフ上に表示することで、関係性などがわかり、より 理解しやすいものになります。
この記事では、同じ系列のデータを重ねて表示する方法を確認していきます。
使用データは、人口データ
今回は、日本の人口データを使ってみます。
データは、政府統計の総合窓口(e-Stat)(https://www.e-stat.go.jp/)のものを使用しています。
# 一部、データ処理用に加工しています。
表示するデータは、2000年〜2020年までの総人口 および 男女それぞれの人口を使ってみます。
処理しやすいのように少し加工して、以下のようなファイルを作りました。
public let population = """
全国,62111,64815,62265,65051,62295,65190,62368,65326,62380,65407,62349,65419,62387,65514,62424,65608,62422,65662,62358,65674,62328,65730,62207,65627,62080,65513,61985,65429,61901,65336,61842,65253,60892,64180,60722,64022,60518,63831,60282,63605,60003,63396
北 海 道,2719,2964,2715,2966,2708,2964,2700,2963,2691,2959,2675,2953,2661,2944,2644,2935,2626,2922,2612,2911,2603,2903,2593,2896,2580,2886,2565,2873,2551,2859,2537,2845,2514,2817,2499,2799,2482,2780,2464,2759,2449,2740
青 森 県,703,773,701,772,697,770,692,767,686,762,679,758,672,752,664,745,657,738,651,732,646,727,641,722,635,716,628,708,622,701,615,694,607,684,601,676,595,668,588,659,581,651
岩 手 県,681,735,680,734,676,731,672,729,669,726,664,721,658,717,652,712,646,706,640,700,635,695,628,686,625,680,623,676,620,670,616,664,608,654,602,647,594,639,587,631,580,623
宮 城
... snip ...
"""
データは、各行が
県名, 2000年男性人口, 2000年女性人口,2001年男性人口, 2001年女性人口,…..,2020年男性人口, 2020年女性人口
となっています。
まずは、1系列のデータを表示
以前にも使用した LineMark を使って、男性の人口を表示してみます。
全国の男性の人口推移を 表示してみます。
県ごとのデータもあるのですが、以下のコードで、全国の数字だけを取得しました。
public struct PopulationPair: Identifiable {
public var id: UUID = UUID()
public var year: Int
public var malePop: Int
public var femalePop: Int
}
public func populationJapanData() -> [PopulationPair] {
var year = 2000
var popData: [PopulationPair] = []
population.enumerateLines(invoking: { line, stop in
let tokens = line.split(separator: ",")
var ite = tokens.makeIterator()
_ = ite.next() // skip prefecture name
while let next = ite.next(),
let menValue = Int(next),
let nextNext = ite.next(),
let womenValue = Int(nextNext) {
let yearData = PopulationPair(year: year, malePop: menValue, femalePop: womenValue)
popData.append(yearData)
year += 1
}
stop = true
})
return popData
}
Charts で扱うときには、データが Identifiable であると便利なので、そのような struct を作成しています。
そして、表示します。
import SwiftUI
import Charts
struct ContentView: View {
var body: some View {
VStack {
Chart {
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.malePop))
})
}
.chartXScale(domain: [1998,2023])
.chartYScale(domain: [55_000, 70_000])
}
.padding()
}
}
データのおおよその定義域/値域を知っているので、chartXScale/ chartYScale を設定しています。
以下のような表示になりました。

2系列のデータを表示する
同時に、女性の人口推移も表示しようとして、単純に LineMark を追加してみます。
struct ContentView: View {
var body: some View {
VStack {
Chart {
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.malePop))
LineMark(x: .value("year", popData.year), y: .value("Male", popData.femalePop))
})
}
.chartXScale(domain: [1998,2023])
.chartYScale(domain: [55_000, 70_000])
}
.padding()
}
}
すると、以下のようなグラフが表示されます・・・

1つの ForEach で行うのが良くなかったかと考え、分離してみます。
import SwiftUI
import Charts
struct ContentView: View {
var body: some View {
VStack {
Chart {
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.malePop))
})
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.femalePop))
})
}
.chartXScale(domain: [1998,2023])
.chartYScale(domain: [55_000, 70_000])
}
.padding()
}
}
とすると、以下のようなグラフになります。

表示の考察
2つのグラフを見てみると、Chart は、Builder 内部のデータを一連のデータとみなしているように見えます。
最初の例では、毎年の男性人口、女性人口が交互に、2つ目の例では 男性人口の後に女性人口が連結されたような表示になっています。
いずれも Chart からみると渡された LineMark の順番で連結しています。
考えてみれば、現在の渡し方では どのように分類して表示するかを Chart 側がわかる方法はありません。
series指定する
このようなケースで、データの系列を指定する方法が用意されています。
LineMark に与える引数の1つ series です。
参考
init(x:y:series:)Apple Developer Documentation
LineMark だけではなく、以下の要素に用意されています。
- AreaMark
- LineMark
- AreaPlot
- LinePlot
ということで、LineMark に series 指定してみます。
import SwiftUI
import Charts
struct ContentView: View {
var body: some View {
VStack {
Chart {
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.malePop),
series: .value("MalePopulation", "MalePopulation"))
LineMark(x: .value("year", popData.year), y: .value("Female", popData.femalePop),
series: .value("FemalePopulation", "FemalePopulation"))
})
}
.chartXScale(domain: [1998,2023])
.chartYScale(domain: [55_000, 70_000])
}
.padding()
}
}
以下のようになります。

せっかく、2系統表示できたので、異なる色を割り当ててみます。
そのまま .foregroundStyle を指定してもよかったのですが、せっかく series で指定しているので、同じように “MalePopulation”, “FemalePopulation” 経由で指定してみました。
import SwiftUI
import Charts
struct ContentView: View {
var body: some View {
VStack {
Chart {
ForEach(populationJapanData(), content: { popData in
LineMark(x: .value("year", popData.year), y: .value("Male", popData.malePop),
series: .value("MalePopulation", "MalePopulation"))
.foregroundStyle(by: .value("MaleColor", "MalePopulation"))
LineMark(x: .value("year", popData.year), y: .value("Female", popData.femalePop),
series: .value("FemalePopulation", "FemalePopulation"))
.foregroundStyle(by: .value("FemaleColor", "FemalePopulation"))
})
}
.chartXScale(domain: [1998,2023])
.chartYScale(domain: [55_000, 70_000])
.chartForegroundStyleScale([
"MalePopulation": .green, "FemalePopulation": .yellow
])
}
.padding()
}
}
最終的に、以下のようになりました。

まとめ
Charts で複数系列のデータを表示する/ series 指定する 方法を確認しました。
- LineMark 等は、与えられた順番にグラフにする
- 複数系列のデータは、series 指定することで、異なる系列のデータであることを指定する
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
SwiftUI おすすめ本
SwiftUI を理解するには、以下の本がおすすめです。
SwiftUI ViewMatery
SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。
英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。
View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。
超便利です
販売元のページは、こちらです。
SwiftUI 徹底入門
# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。
Swift学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Sponsor Link