iPhoneのHealthのデータをエクスポートしてゴニョゴニョしてみる(その2)

この記事の続きです。

deutschina.hatenablog.com

前の記事で、iPhoneのHealthデータをCSVに変換しました。後で本丸であるNokia Health(旧Withings)のデータとマージするんだけど、その前に、もう少しデータの中身を確認しておこうということで、pandasのdataframeの出番ですね。

Healthのデータの中身を見てみよう

>>> import pandas as pd
>>> df1 = pd.read_csv('tmp_files/export20180520211840.csv', low_memory=False)
>>> df1.describe(include='all')

include='all'オプションを付けたのは、数値項目以外の情報も見たかったから。出てきたのがこちら。(※右端切れてます)

f:id:deutschina:20180522073208p:plain

項目ごとに深掘りする必要性があるかを見ていこう。

  • type 保持しているレコードの区分のようなものに見える。最頻値「HKQuantityTypeIdentifierDistanceWalkingRunning」は、字面の通りなら歩いたりランニングした距離ということになる。unique値が8ということは、このデータの塊は8種類のデータから出来ているということになる。
  • sourceName: 項目名と最頻値から推測すると、データの出元ということになる。iPhone7 Plusからの値が最頻値ではあるが、これもUniqueが4なので4種類のデータがありそう。
  • sourceVersion: 何かのバージョンというぐらいしか分からない。全部で42万レコードのうち16万レコードぐらいにしか値が入っていないと読み取れる。Dropしても良いのかな。
  • unit: countという如何にも歩数っぽく見える単位が全体の半分を占めている。
  • creationDate: レコードが登録された日付と読める。最頻値で2000回以上あるので、一括してインポートした日付なのかなと推定。
  • startDate, endDate: 開始・終了の日付。startDateとendDateの最頻値が全く同じに見える。期間値を取ると思っていたので、少し意外。とはいえ、最頻でも6回なので、計測の対象となった時間の情報が入っていると考えるのが正しそう。
  • value: これが実際の計測値と思われる。ただ、最小値0.000108で最大値19059なので、全部が全部歩数データではないと言えそう。
  • 残りの項目は、MetaAttributeから拾ってきたもの。あまり有益な情報がなさそう。"HKWasUserEntered"は自動入力か手入力かというフラグ、"Withings User Identifier"はユーザID情報に見えるので、あまり重要ではないと判断できそう。ただ、deviceは値が入ったり入っていなかったり。

先頭の数行を出してみる。

>>> df1.head()

f:id:deutschina:20180522073617p:plain

カテゴリ値に何があるかを見てみたい。

>>> set(df1.type.values)
{'HKQuantityTypeIdentifierActiveEnergyBurned',
 'HKQuantityTypeIdentifierBodyFatPercentage',
 'HKQuantityTypeIdentifierBodyMass',
 'HKQuantityTypeIdentifierBodyMassIndex',
 'HKQuantityTypeIdentifierDistanceWalkingRunning',
 'HKQuantityTypeIdentifierFlightsClimbed',
 'HKQuantityTypeIdentifierHeight',
 'HKQuantityTypeIdentifierStepCount'}

歩数が欲しいなら、HKQuantityTypeIdentifierStepCountのデータを拾えと言われている気がする。

>>> set(df1.sourceName.values)
{'Health Mate', "Ken's iPhone6", "Ken's iPhone7 Plus", 'UP'}

Health MateはNokiaのアプリの名前、iPhone6, iPhone7 Plusはアプリを経由していない値、UPは自転車乗るときに時々使っていたやつと思われる。

>>> set(df1.unit.values)
{'%', 'cm', 'count', 'kcal', 'kg', 'km'}

小数点付きのcountは、どうやらBodyMassIndexのことを指しているんだな。ん?これってBMIのことか!やばい。自分のBMIを公衆の面前に晒してしまった。

・・・ま、7年前のデータだから良いけどね。

歩数関連のデータを深掘りしてみる

先ほど確認したように、歩数関連のデータはtypeの値が'HKQuantityTypeIdentifierStepCount'のものを拾えば良さそう。

>>> df1[df1.type=='HKQuantityTypeIdentifierStepCount'].describe(include='all')

f:id:deutschina:20180522074547p:plain

良い感じと思ったものの、value値の散らばりが1~19059というのが気になる。75%値で95なので、19059というのは何かずば抜けた外れ値という可能性もありそう。

となると、10000歩以上記録されているレコードを確認してみよう。

>>> df1[(df1.type=='HKQuantityTypeIdentifierStepCount') & (df1.value>10000)]

f:id:deutschina:20180522074820p:plain

その日の午前0時から夕方または夜までの歩数の合計のように見える。上のイメージでは隠れているけど、全部で141件しかないので、常にこのパターンで記録されているという感じではなさそう。逆に歩数が少ないのは何をやっているのか?

>>> df1[(df1.type=='HKQuantityTypeIdentifierStepCount') & (df1.startDate>"2018-01-15") & (df1.startDate<"2018-01-31")]

※歩数が少ないエントリが2018年アタマに多かったように見えたので、日付で絞っている。
f:id:deutschina:20180522075011p:plain

sourceNameがiPhoneになっているのと、startDateとendDateの間が数秒になっている。本来の目的である連携漏れのデータはこちら側に転がっていそうな感じ。

ふむふむ。なんとなく全容が見えた気がするので、Nokia Health側のデータとの突き合わせをやってみよう。

(たぶんつづく)

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理