Battery Data
Read data
[1]:
import pandas as pd
import niimpy
import niimpy.preprocessing.battery as battery
from niimpy import config
import warnings
warnings.filterwarnings("ignore")
[2]:
data = niimpy.read_csv(config.MULTIUSER_AWARE_BATTERY_PATH, tz='Europe/Helsinki')
data.shape
[2]:
(505, 8)
Introduction
In this notebook , we will extract battery data from the Aware platform and infer users’ behavioral patterns from their interaction with the phone. The below functions will be described in this notebook:
niimpy.preprocessing.battery.battery_shutdown_info
: returns the timestamp when the device is shutdown or rebootedniimpy.preprocessing.battery.battery_occurrences
: returns the number of battery samples within a time rangeniimpy.preprocessing.battery.battery_gaps
: returns the time gaps between two battery sample
[3]:
data.head()
[3]:
user | device | time | battery_level | battery_status | battery_health | battery_adaptor | datetime | |
---|---|---|---|---|---|---|---|---|
2020-01-09 02:20:02.924999936+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 1.578529e+09 | 74 | 3 | 2 | 0 | 2020-01-09 02:20:02.924999936+02:00 |
2020-01-09 02:21:30.405999872+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 1.578529e+09 | 73 | 3 | 2 | 0 | 2020-01-09 02:21:30.405999872+02:00 |
2020-01-09 02:24:12.805999872+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 1.578529e+09 | 72 | 3 | 2 | 0 | 2020-01-09 02:24:12.805999872+02:00 |
2020-01-09 02:35:38.561000192+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 1.578530e+09 | 72 | 2 | 2 | 0 | 2020-01-09 02:35:38.561000192+02:00 |
2020-01-09 02:35:38.953000192+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 1.578530e+09 | 72 | 2 | 2 | 2 | 2020-01-09 02:35:38.953000192+02:00 |
Feature extraction
By default, Niimpy data should be ordered by the timestamp in ascending order. We start by sorting the data to make sure it’s compatible.
[4]:
data = data.sort_index()
Next, we will use Niimpy to extract features from the data. These are useful for inspecting the data and can be part of a full analysis workflow.
Usin the battery_occurrences
function, we can count the amount the battery samples every 10 minutes. This function requires the index to be sorted.
[5]:
battery.battery_occurrences(data, {"resample_args": {"rule": "10min"}})
[5]:
user | device | occurrences | |
---|---|---|---|
2019-08-05 14:00:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 2 |
2019-08-05 14:10:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 0 |
2019-08-05 14:20:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 0 |
2019-08-05 14:30:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1 |
2019-08-05 14:40:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 0 |
... | ... | ... | ... |
2020-01-09 22:50:00+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 0 |
2020-01-09 23:00:00+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1 |
2020-01-09 23:10:00+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1 |
2020-01-09 23:20:00+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1 |
2020-01-09 23:30:00+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 2 |
673 rows × 3 columns
The above dataframe gives the battery information of all users. You can also get the information for an individual by passing a filtered dataframe.
[6]:
f = niimpy.preprocessing.battery.battery_occurrences
data_filtered = data.query('user == "jd9INuQ5BBlW"')
individual_occurrences = battery.extract_features_battery(data_filtered, features={f: {"resample_args": {"rule": "10min"}}})
individual_occurrences.head()
<function battery_occurrences at 0x7fd7b27f2480> {'resample_args': {'rule': '10T'}}
[6]:
user | device | occurrences | |
---|---|---|---|
2020-01-09 02:20:00+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 3 |
2020-01-09 02:30:00+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 5 |
2020-01-09 02:40:00+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 6 |
2020-01-09 02:50:00+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 6 |
2020-01-09 03:00:00+02:00 | jd9INuQ5BBlW | 3p83yASkOb_B | 5 |
Next, you can extract the gaps between two consecutive battery samples with the battery_gaps
function.
[7]:
f = niimpy.preprocessing.battery.battery_gaps
gaps = battery.battery_gaps(data, {})
gaps
[7]:
user | device | time | battery_level | battery_status | battery_health | battery_adaptor | datetime | |
---|---|---|---|---|---|---|---|---|
2019-08-05 14:00:58.600000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565003e+09 | 47 | 3 | 2 | 0 | 2019-08-05 14:00:58.600000+03:00 |
2019-08-05 14:03:35.800000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565003e+09 | 46 | 3 | 2 | 0 | 2019-08-05 14:03:35.800000+03:00 |
2019-08-05 14:30:54.196000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565005e+09 | 45 | 3 | 2 | 0 | 2019-08-05 14:30:54.196000+03:00 |
2019-08-05 15:22:06.193000192+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565008e+09 | 44 | 3 | 2 | 0 | 2019-08-05 15:22:06.193000192+03:00 |
2019-08-05 16:21:29.716000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565011e+09 | 43 | 3 | 2 | 0 | 2019-08-05 16:21:29.716000+03:00 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
2020-01-09 23:02:13.938999808+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578604e+09 | 73 | 3 | 2 | 0 | 2020-01-09 23:02:13.938999808+02:00 |
2020-01-09 23:10:37.262000128+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578604e+09 | 73 | 3 | 2 | 0 | 2020-01-09 23:10:37.262000128+02:00 |
2020-01-09 23:22:13.966000128+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578605e+09 | 72 | 3 | 2 | 0 | 2020-01-09 23:22:13.966000128+02:00 |
2020-01-09 23:32:13.959000064+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578606e+09 | 71 | 3 | 2 | 0 | 2020-01-09 23:32:13.959000064+02:00 |
2020-01-09 23:39:06.800000+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578606e+09 | 71 | 3 | 2 | 0 | 2020-01-09 23:39:06.800000+02:00 |
505 rows × 8 columns
Knowing when the phone is shutdown is essential if we want to infer the usage behaviour of the subjects. This can be done by calling the shutdown_info
function. The function returns the timestamp when the phone is shut down or rebooted (e.g: battery_status = -1).
[8]:
shutdown = battery.shutdown_info(data, config={'battery_column_name': 'battery_status'})
shutdown
[8]:
user | device | time | battery_level | battery_status | battery_health | battery_adaptor | datetime | |
---|---|---|---|---|---|---|---|---|
2019-08-07 10:37:11.308000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565163e+09 | 2 | -1 | 2 | 0 | 2019-08-07 10:37:11.308000+03:00 |
2019-08-07 10:37:11.323000064+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565163e+09 | 2 | -1 | 2 | 0 | 2019-08-07 10:37:11.323000064+03:00 |
Extracting features with the extract_features call
We have seen above how to extract battery features using niimpy
. Sometimes, we need more than one features and it would be inconvenient to extract everything one by one. niimpy
provides a extract_feature
call to allow you extracting all the features available and combining them into a single data frame. The extractable features must start with the prefix battery_
.
[9]:
# Start by defining the feature name
f0 = niimpy.preprocessing.battery.battery_occurrences
f1 = niimpy.preprocessing.battery.battery_gaps
f2 = niimpy.preprocessing.battery.battery_charge_discharge
# The extract_feature function requires a features parameter.
# This parameter accepts a dictionary where the key is the feature name and value
# is a dictionary containing values passed to the function.
features = battery.extract_features_battery(
data,
features={f0: {'rule': "10min"},
f1: {},
f2: {}
})
features.head()
<function battery_occurrences at 0x7fd7b27f2480> {'rule': '10min'}
<function battery_gaps at 0x7fd7b27f2520> {}
<function battery_charge_discharge at 0x7fd7b27f25c0> {}
[9]:
user | device | occurrences | time | battery_level | battery_status | battery_health | battery_adaptor | datetime | bdelta | charge/discharge | |
---|---|---|---|---|---|---|---|---|---|---|---|
2019-08-05 14:00:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 2.0 | NaN | NaN | NaN | NaN | NaN | NaT | -0.5 | -0.006361 |
2019-08-05 14:30:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.0 | NaN | NaN | NaN | NaN | NaN | NaT | -1.0 | -0.000610 |
2019-08-05 15:00:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.0 | NaN | NaN | NaN | NaN | NaN | NaT | -1.0 | -0.000326 |
2019-08-05 15:30:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 0.0 | NaN | NaN | NaN | NaN | NaN | NaT | NaN | NaN |
2019-08-05 16:00:00+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.0 | NaN | NaN | NaN | NaN | NaN | NaT | -1.0 | -0.000281 |
[11]:
f1(data, {})
[11]:
user | device | time | battery_level | battery_status | battery_health | battery_adaptor | datetime | |
---|---|---|---|---|---|---|---|---|
2019-08-05 14:00:58.600000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565003e+09 | 47 | 3 | 2 | 0 | 2019-08-05 14:00:58.600000+03:00 |
2019-08-05 14:03:35.800000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565003e+09 | 46 | 3 | 2 | 0 | 2019-08-05 14:03:35.800000+03:00 |
2019-08-05 14:30:54.196000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565005e+09 | 45 | 3 | 2 | 0 | 2019-08-05 14:30:54.196000+03:00 |
2019-08-05 15:22:06.193000192+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565008e+09 | 44 | 3 | 2 | 0 | 2019-08-05 15:22:06.193000192+03:00 |
2019-08-05 16:21:29.716000+03:00 | iGyXetHE3S8u | Cq9vueHh3zVs | 1.565011e+09 | 43 | 3 | 2 | 0 | 2019-08-05 16:21:29.716000+03:00 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
2020-01-09 23:02:13.938999808+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578604e+09 | 73 | 3 | 2 | 0 | 2020-01-09 23:02:13.938999808+02:00 |
2020-01-09 23:10:37.262000128+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578604e+09 | 73 | 3 | 2 | 0 | 2020-01-09 23:10:37.262000128+02:00 |
2020-01-09 23:22:13.966000128+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578605e+09 | 72 | 3 | 2 | 0 | 2020-01-09 23:22:13.966000128+02:00 |
2020-01-09 23:32:13.959000064+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578606e+09 | 71 | 3 | 2 | 0 | 2020-01-09 23:32:13.959000064+02:00 |
2020-01-09 23:39:06.800000+02:00 | jd9INuQ5BBlW | OWd1Uau8POix | 1.578606e+09 | 71 | 3 | 2 | 0 | 2020-01-09 23:39:06.800000+02:00 |
505 rows × 8 columns