集計データ

Google Health API には、医療記録をグループ化して時間枠にまとめる専用の集計エンドポイントが用意されています。クライアントで個々の未加工レコードを取得して合計するのではなく、集計エンドポイントを使用して、調整されたデータ ストリームの指標(合計、平均、最小、最大など)を計算します。

  • rollUp エンドポイントは、構成可能なウィンドウ期間(秒単位、windowSize)を使用して、UTC の物理的な時間間隔でデータポイントを集計します。
  • dailyRollUp エンドポイントは、ユーザーのローカル時計を基準とした常用時を使用して、1 日以上の暦日(windowSizeDays)にわたるデータポイントを集計します。

どちらのエンドポイントも、接続されたデバイス間で重複するデータポイントを自動的に調整し、手首装着検出をサポートするウェアラブル データタイプの手首から外した期間を除外します。

集計エンドポイントを比較する

アプリケーションで時系列の健康指標をグループ化して表示する方法に一致する集計エンドポイントを選択します。

機能 rollUp エンドポイント dailyRollUp エンドポイント
HTTP リクエスト POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:rollUp POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:dailyRollUp
時刻表現 UTC の物理時間(startTime と endTime、RFC 3339 形式)。 市民時間(start と end を CivilDateTime オブジェクトとして)。
ウィンドウ パラメータ windowSize(必須の文字列。期間(秒単位)。最小値は "1s")。 windowSizeDays(省略可。日数を表す整数。デフォルトは 1)。
レスポンス オブジェクト RollupDataPoint DailyRollupDataPoint
レスポンスの順序 逆時系列(新しいウィンドウが先)。 逆時系列(新しいウィンドウが先)。
最適な用途 イントラデイ チャート、1 時間単位または 1 分単位のヒストグラム、固定期間の UTC 分析。 日次ダッシュボード、複数日の傾向、タイムゾーンの移動や夏時間を考慮した概要。

どちらのエンドポイントも、データ型に基づいて最大クエリ範囲の上限を適用します。

  • calories-in-heart-rate-zone、heart-rate、active-minutes、total-calories には、最大 14 日間のクエリ範囲が適用されます。
  • 他のすべてのサポートされているデータタイプには、最大 90 日間のクエリ範囲が適用されます。

rollup と dailyRollup をサポートするデータタイプを確認するには、Google Health API のデータタイプのリファレンスをご覧ください。

物理的な時間間隔で集計する

rollUp エンドポイントを使用して、物理時間 range(UTC)にわたるデータポイントを、ウィンドウ期間(秒単位、windowSize)でグループ化して集計します。

rollUp エンドポイントを呼び出すときに、半開区間の range(startTime を含み、endTime を含まない)と windowSize を含む JSON リクエスト本文を指定します。windowSize の次の要件に注意してください。

  • windowSize の期間は 1 秒("1s")以上にする必要があります。API は、1 秒未満の期間、ゼロ、または負の期間を 400 Bad Request(INVALID_ROLLUP_WINDOW)エラーで拒否します。
  • サブバケット間で集計データが不均等に分散されないようにするには、データタイプの基盤となるストレージ解像度(1 分間の歩数間隔の場合は "60s" など)以上の windowSize を選択します。詳細については、ロールアップ ウィンドウとストレージの解像度をご覧ください。

たとえば、次のリクエストは、歩数を 1 分間隔(60s)でロールアップします。

リクエスト

POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:rollUp
Authorization: Bearer access-token
Accept: application/json

{
  "range": {
    "startTime": "2026-02-17T17:00:00Z",
    "endTime": "2026-02-17T17:59:59Z"
  },
  "windowSize": "60s"
}

レスポンス

{
  "rollupDataPoints": [
    {
      "startTime": "2026-02-17T17:55:00Z",
      "endTime": "2026-02-17T17:56:00Z",
      "steps": {
        "countSum": "72"
      }
    },
    {
      "startTime": "2026-02-17T17:54:00Z",
      "endTime": "2026-02-17T17:55:00Z",
      "steps": {
        "countSum": "85"
      }
    },
...
  ]
}

暦日で集計する

dailyRollUp エンドポイントを使用して、1 日または複数日(windowSizeDays)のデータを集計します。リクエスト本文に、閉じた開いた市民時間 range(start と end)を指定します。データ型に応じて、エンドポイントは各シビル ウィンドウの合計や平均などの集計値を返します。

dailyRollUp は、各データポイントに記録された UTC オフセットを使用して常用時で動作するため、夏時間の移行やタイムゾーンをまたぐ移動によって生じる 1 日の長さの変動を自動的に調整します。

たとえば、次のリクエストでは、1 日(windowSizeDays: 1)の歩数を集計します。

リクエスト

POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:dailyRollUp
Authorization: Bearer access-token
Accept: application/json

{
  "range": {
    "start": {
      "date": {
        "year": 2026,
        "month": 2,
        "day": 26
      },
      "time": {
        "hours": 0,
        "minutes": 0,
        "seconds": 0,
        "nanos": 0
      }
    },
    "end": {
      "date": {
        "year": 2026,
        "month": 2,
        "day": 26
      },
      "time": {
        "hours": 23,
        "minutes": 59,
        "seconds": 59,
        "nanos": 0
      }
    }
  },
  "windowSizeDays": 1
}

レスポンス

{
  "rollupDataPoints": [
    {
      "civilStartTime": {
        "date": {
          "year": 2026,
          "month": 2,
          "day": 26
        },
        "time": {}
      },
      "civilEndTime": {
        "date": {
          "year": 2026,
          "month": 2,
          "day": 26
        },
        "time": {
          "hours": 23,
          "minutes": 59,
          "seconds": 59
        }
      },
      "steps": {
        "countSum": "3822"
      }
    }
  ]
}

データソース ファミリー別に集計する

rollUp と dailyRollUp の両方で、JSON リクエスト本文のオプションの dataSourceFamily フィールドを使用して、集計を特定のソースグループに制限できます。

  • users/me/dataSourceFamilies/all-sources オプション(デフォルト)は、登録されているすべてのファーストパーティ ソースとサードパーティ ソースで調整されたデータを集計します。
  • users/me/dataSourceFamilies/google-wearables オプションは、Google と Fitbit のウェアラブル トラッカー デバイスによって記録されたデータを集計します。手動で記録されたデータとスマートフォンで推定されたデータは除外されます。
  • users/me/dataSourceFamilies/google-sources オプションは、ウェアラブル トラッカー、ヘルスコネクト、ファーストパーティ製アプリの手動入力など、Google と Fitbit のファーストパーティ ソースからデータを集計します。

パラメータの要件とリクエストとレスポンスの例については、データフィルタ ガイドのデータソース ファミリーでフィルタするをご覧ください。

ロールアップ ウィンドウとストレージの解像度

rollUp エンドポイントは 1 秒("1s")以上の windowSize を受け入れますが、データタイプによって、基盤となるストレージで異なるサンプリング レートまたは間隔で測定値を記録して保持します。たとえば、steps、distance、active-minutes、active-energy-burned などのウェアラブルの身体活動指標は、通常 1 分(60s)間隔で記録されます。

次の表に、一般的なデータ型の基盤となるストレージの解像度と、推奨される最小の windowSize 値を示します。

ストレージの解決 推奨される最小基準 windowSize データ型
1 秒(1s) "1s" heart-rate
1 分(60s) "60s" active-energy-burned、active-minutes、active-zone-minutes、altitude、calories-in-heart-rate-zone、distance、floors、steps、time-in-heart-rate-zone、total-calories

インターバル データ型を集計する場合、rollUp エンドポイントは、記録された各データポイントを、そのデータポイントの startTime を含むバケットに配置します。API は、サブインターバル バケット間でインターバル データをスライス、補間、分散しません。

基盤となるデータ ストレージ間隔よりも小さい windowSize を指定した場合(たとえば、1 分間隔で保存された steps に対して 10 秒のウィンドウをリクエストした場合):

  1. 間隔の startTime(10:00:00~10:00:10 など)に一致する最初のサブバケットは、1 分間の累積カウント(その 1 分間に記録された 100 歩すべてなど)を受け取ります。
  2. 同じ分内の残りのサブバケット(10:00:10~10:00:20、10:00:20~10:00:30 など)は、これらのウィンドウ内で開始される間隔がないため、データポイントを受け取りません。

これにより、図 1 に示すように、間隔全体の値が最初のサブウィンドウに集中する、スパイクのあるデータが生成されます。

サブインターバルのロールアップ バケットとストレージ解像度の比較
図 1: サブインターバル ロールアップ バケット。1 分間隔が startTime によって最初の 10 秒のサブバケットに割り当てられます。

均等に分散された意味のある集計を取得するには、常に windowSize を、ターゲット データタイプの基盤となるストレージ解像度以上の期間に設定します(たとえば、steps の場合は "60s" 以上)。各データタイプのストレージ解像度と推奨される最小ロールアップ ウィンドウについては、Google Health API のデータタイプのリファレンスをご覧ください。

範囲がウィンドウ サイズの倍数でない場合のバケット化

リクエストされた範囲が windowSize(または windowSizeDays)の正確な倍数でない場合、最後の時系列バケットは範囲の上限で切り捨てられ、ウィンドウ サイズよりも短い期間をカバーします。API は、変更なしでリクエストを受け入れ、丸め、タイムシフト、データ補間は行いません。

リクエストされた範囲全体をカバーするために、API は天井除算を使用して集計ウィンドウの合計数を計算します。

Number of windows = ceiling(Range duration / Window size)

各バケットは、範囲の先頭から順番に開始されます。別のフルサイズのウィンドウを追加すると、リクエストされた終了時間を超える場合、最後のウィンドウは範囲の終了時間で切り捨てられます(クランプされます)。

バケット処理の仕組み

分割できない範囲のロールアップをリクエストすると、API は次のルールを適用します。

  • バケット化は、リクエストされた範囲(range.startTime または range.start)の開始時に開始され、ウィンドウ サイズ(windowSize または windowSizeDays)で進みます。
  • 最後の時系列バケットは、リクエストされた範囲(range.endTime または range.end)の終了時にクランプされ、リクエストされたウィンドウ サイズよりも短い期間をカバーします。
  • 返された RollupDataPoint オブジェクトまたは DailyRollupDataPoint オブジェクトには、独自の明示的な開始タイムスタンプと終了タイムスタンプが含まれています。これらを使用して、切り捨てられたバケットの実際の期間を調べることができます。
  • API はロールアップ データを逆の年代順(新しい順)で返すため、最後の年代順バケット(切り捨てられたバケット)が、返されたリストの最初の要素(index 0)として表示されます。

図 2 は、API が range.startTime から割り切れない範囲をバケット化し、最後のバケットを range.endTime でクランプして、結果のバケットを逆時系列で返す方法を示しています。

ロールアップ バケット、切り捨て、レスポンスの順序
図 2: ロールアップ バケット、範囲終了時の切り捨て、逆時系列のレスポンス順序

5 分間のウィンドウを含む 12 分間の範囲の例

クライアントが 5 分の windowSize("300s")で 12 分の範囲のロールアップをリクエストしたとします。

  • range.startTime の値は 10:00:00Z です。
  • range.endTime の値は 10:12:00Z で、合計時間は 12 分です。
  • windowSize の値は "300s"(5 分)です。

12 分は 5 分(12 = 5 * 2 + 2)の正確な倍数ではないため、API はウィンドウ数を ceiling(12 / 5) = 3 として計算します。これにより、次の 3 つの時系列バケットが生成されます。

バケット 間隔 所要時間 期間のステータス
バケット 1 [10:00:00Z, 10:05:00Z) 5 分 フルウィンドウ
バケット 2 [10:05:00Z, 10:10:00Z) 5 分 フルウィンドウ
バケット 3 [10:10:00Z, 10:12:00Z) 2 分 range.endTime で切り捨て

集計値への影響

最後の時系列ウィンドウの期間が短いため、期間が短いことから、切り捨てられたバケットでは加算指標(歩数の合計やカウントなど)が低くなります。

ユーザーがこの 12 分間、1 分あたり 100 歩の一定のペースで歩いた場合、バケットには次の合計が含まれます。

  • バケット 1(10:00:00Z~10:05:00Z)には 500 歩(1 分あたり 100 歩で 5 分間)が記録されます。
  • バケット 2(10:05:00Z~10:10:00Z)は 500 歩(1 分あたり 100 歩で 5 分間)を記録します。
  • バケット 3(10:10:00Z~10:12:00Z)は 200 歩(1 分あたり 100 歩で 2 分間)を記録します。

バケット 3 の歩数が 200 歩と少ないのは、ユーザーのアクティビティが低下したためではなく、切り捨てられたウィンドウの長さが 2 分であるためです。このデータをプロットまたは分析する場合は、各バケットの明示的な期間を使用してカウントを正規化し、ユーザー アクティビティの減少を誤って表示しないようにします。

図 3 は、3 つのバケットにおける未加工の加算ステップの合計(countSum)と、期間で正規化されたレートを比較したものです。

未加工のバケットの歩数の合計と正規化された歩数の比較
図 3: 切り捨てられたロールアップ バケットの未加工の加算合計と期間正規化率の比較

順序付けを示す API レスポンスの例

API は結果を逆時系列で返すため、切り捨てられたバケットは返されたリストの最初の要素として表示されます。

{
  "rollupDataPoints": [
    {
      "startTime": "2026-08-20T10:10:00Z",
      "endTime": "2026-08-20T10:12:00Z",
      "steps": {
        "countSum": "200"
      }
    },
    {
      "startTime": "2026-08-20T10:05:00Z",
      "endTime": "2026-08-20T10:10:00Z",
      "steps": {
        "countSum": "500"
      }
    },
    {
      "startTime": "2026-08-20T10:00:00Z",
      "endTime": "2026-08-20T10:05:00Z",
      "steps": {
        "countSum": "500"
      }
    }
  ]
}