質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1227閲覧

【Swift-Charts】X軸に1日ずつずらした日付を埋め込んだグラフを作りたい

miyuki

総合スコア23

Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2023/03/28 08:29

編集2023/03/28 14:24

実現したいこと

折れ線グラフのX軸に日付を埋め込んで、X軸には「最初のデータから1日ずつ増やした日付」、Y軸には「日付に対応した個々の値」(対応する値がない場合はnullを代入)が入るようにしたいです。

イメージといたしましては以下のグラフのようにX軸には1週間ごとの日付をY軸には値を入れて、1週間ごとの記録でページを切り替える構造にしたいと考えています。
イメージ説明
StudyPlusより参照いたしました。

試したこと

初心者ながら考えた方法としましては
① データの中で日付が1番早いものと遅いものを取り出し、経過日数を計算する。
② 1番早い日付のものから遅い日付のものまで1日ずつ日付を加えていき、それをX軸の値として配列で保持
③ 上記の日付に対応する値をY軸の値として配列として保持
(対応する値がない場合はnilを代入)
④ ②③の値を使ってChartsでグラフを描画
⑤ データを1週間ごとに分け、それぞれにページを割り当てる
⑥ ボタンでページを切り替えることで1週間ごとのデータを順に表示させる
という流れで製作できるのではないかと思っているのですが、方法に自信がなく、より良い方法で作成する術があれば教えていただきたく質問させていただきました。

加えて上記①②の処理を下記のように行った際、アプリがとても重くなってしまいました。
下記のコードのどこが間違っているのかわからず、非常に困っています。
下のコードの誤りも重ねて教えていただけますと大変ありがたいです。

Swift

1var calendar = Calendar(identifier: .gregorian) 2var firstPost = points.first?.date 3var lastPost = points.last?.date 4//経過日数 5var dateInterval: Int = Int(lastPost!.timeIntervalSince(firstPost!)) / (24 * 60 * 60) 6//212 7print(dateInterval) 8var i = 0 9repeat{ 10 date.append(Calendar.current.date(byAdding: .day, value: i, to: firstPost!)) 11 i += 1 12} while i < dateInterval

拙い説明だと思いますがご教授いただけますと幸いです。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2023/03/28 09:44

コードが断片的でよく分かりません。その処理だけならそんなに遅くはないのでは。(同じ値をたくさん追加してるだけな気もしますが…)
miyuki

2023/03/28 10:02

コードのこの箇所を変更した際に処理が大きく重くなってしまったのですが、原因は違うところにありそうですね。他の場所を検討してみます!ご教授くださりありがとうございます!「同じ値をたくさん追加してしまっている」と示していただいた箇所は「i」とすべきところを1と誤入力してしまっていたようです。こちらも気付いてくださりありがとうございます。
guest

回答1

0

ベストアンサー

という流れで製作できるのではないかと思っているのですが、方法に自信がなく、より良い方法で作成する術があれば教えていただきたく質問させていただきました。

Charts はあまり使ったことがないのですが、
大まかな方針は良さそうに思いました。

画面構成やデータの性質によっては、
都度1週間分のグラフ用のデータを作る感じにしてみても良いのかなと思いました。
(質問欄のイメージは最初に全部の元データからグラフ用のデータをまとめて作る感じですよね)


加えて上記①②の処理を下記のように行った際、アプリがとても重くなってしまいました。
下記のコードのどこが間違っているのかわからず、非常に困っています。
下のコードの誤りも重ねて教えていただけますと大変ありがたいです。

どのくらいの時間がかかっているのか、
具体的な数値も質問欄にご記載いただくと良いと思いました。
(遅い、遅くない、は多少主観もあると思いますので、数値で表現してあげると、回答する人も判断しやすいかなと思いました)

dateを他で使っていない状態で、
手元で確認したところ、
date.append()
が遅いようでした。
(コメントに「コードのこの箇所を変更した際に処理が大きく重くなってしまった」との記載がありましたので、他の状況はおいておいて、このコードの部分についてだけ見た場合で書いています)

1400回程度のループで3秒もかかりました。
dateの配列が大きい場合、appendするのにさらに時間がかかるようで、
初期の要素に100000件を設定しておいた状態で確認すると、
1要素追加するだけでも体感的に0.5秒程度もかかっている感じでした(200要素追加するとしたら100秒もかかりますね)(遅いので計測はしませんでした)。
(質問欄のコードにdateの初期値やdateのクリア処理が記載されていないので実際のところはわからないですが、クリアしないまま要素を追加し続けると、どんどん遅くなりそうに思いました)

以下、XcodeのPlaygroundで確認したコードです。
(ご自身でもPlaygroundを使って値を変えながら動かしてみると他にもわかることがあるかもしれませんね)

swift

1struct Point { 2 let date: Date 3} 4let dateFormatter = DateFormatter() 5dateFormatter.dateStyle = .medium 6dateFormatter.timeStyle = .none 7dateFormatter.locale = Locale(identifier: "ja_JP") 8let points: [Point] = [ 9 Point(date: dateFormatter.date(from: "2019/03/19")!), 10 Point(date: dateFormatter.date(from: "2023/03/25")!), 11] 12var date: [Date] = (0..<100000).map({ _ in Date() }) 13 14func work() { 15 var calendar = Calendar(identifier: .gregorian) 16 var firstPost = points.first?.date 17 var lastPost = points.last?.date 18 //経過日数 19 var dateInterval: Int = Int(lastPost!.timeIntervalSince(firstPost!)) / (24 * 60 * 60) 20 //212 21 print(dateInterval) 22 var i = 0 23 repeat { 24 date.append(Calendar.current.date(byAdding: .day, value: i, to: firstPost!)!) 25 i += 1 26 } while i < dateInterval 27 28 // 参考:appendせずに配列を生成すると(データ量にもよりますが)少しは速くなると思います 29// let array = (0..<dateInterval).map({ 30// calendar.date(byAdding: .day, value: $0, to: firstPost!)! 31// }) 32} 33 34// 処理時間計測 35let clock = ContinuousClock() 36let elapsed = clock.measure(work) 37print(elapsed)

投稿2023/03/29 01:52

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miyuki

2023/03/29 04:50

ご回答くださりありがとうございます。非常に丁寧に説明してくださり大変助かりました!ベストアンサーにさせていただきます。 1週間ごとのデータを必要に応じて入れ替えて処理する。その際にappendせずに配列を生成し、データのクリア処理を導入することを試してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問