0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「値が0」と「データなし」を分けないと、グラフの平均がずれる

0
Posted at

何が起きるか

日ごとのスコアが次のようになっていたとします。

日 結果
月 90
火 データなし
水 60

測定できた日だけで平均すると 75 です。火曜を 0 として計算すると 50 になり、グラフなどに反映させたときにも存在しない「0点」が描かれます。

ただし、本当に「測定した結果が0」だった日は平均に含める必要があります。つまり「0なら除外する」というルールでは解決しません。

「測定できたか」を値と一緒に持つ

データ元が未測定の日にも 0 を返す場合、数値だけでは区別できません。受け取った時点で、未測定を null に変換します。

data class DailyRaw(val value: Int, val measured: Boolean)

fun DailyRaw.toChartValue(): Int? = if (measured) value else null

平均は null を除いて計算する

val raws = listOf(
    DailyRaw(90, measured = true),
    DailyRaw(0, measured = false),
    DailyRaw(60, measured = true),
)
val values = raws.map { it.toChartValue() } // [90, null, 60]

val average = values.filterNotNull()
    .takeIf { it.isNotEmpty() }
    ?.average()

println(average) // 75.0

filterNotNull() で除かれるのは未測定の日だけです。測定済みの 0 は残ります。全日が未測定なら平均も null になるので、「平均0」と誤って表示することもありません。
参考:Kotlin 公式ドキュメント - Null safety

0埋めは表示の直前だけにする

欠測日に何かを表示したい場合は、表示のタイミングで変換します。

val label = value?.toString() ?: "-"

集計の前に null を 0 に変えてしまうと、測定済みの0と区別できなくなります。

// NG
val wrongAverage = values.map { it ?: 0 }.average() // 50.0

まとめ

  • 「データなし」は null、「測定結果が0」は 0 として分ける
  • 集計は null を除いて行い、0埋めは表示時だけにする
  • テストでは「正の値」「測定済みの0」「データなし」の3パターンを確認する

理解できている人には当たり前のことですが、実装しながらだと抜けやすい人もいると思います。
今回はそんな場合の時のために言語化して整理するための記事にしました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?