Skip to content

Commit 56fe9b2

Browse files
committed
feat: Add daily wear time calculation
1 parent ffdd8ef commit 56fe9b2

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/stepcount/stepcount.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ def main():
121121
# Update wear time stats after exclusions
122122
info.update(utils.calculate_wear_stats(data))
123123

124+
# Calculate daily wear stats
125+
daily_wear_stats = utils.calculate_daily_wear_stats(data)
126+
124127
# If no data, save Info.json and exit
125128
if len(data) == 0 or data[['x', 'y', 'z']].isna().any(axis=1).all():
126129
# Save Info.json
@@ -366,6 +369,7 @@ def main():
366369
steps_summary['daily_steps'],
367370
cadence_summary['daily'],
368371
enmo_summary['daily'],
372+
daily_wear_stats
369373
], axis=1)
370374
daily.index.name = 'Date'
371375
daily.reset_index(inplace=True)

src/stepcount/utils.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,64 @@ def calculate_wear_stats(data: pd.DataFrame):
188188
}
189189

190190

191+
def calculate_daily_wear_stats(data: pd.DataFrame):
192+
"""
193+
Calculate daily wear time statistics from raw accelerometer data.
194+
195+
Parameters:
196+
- data (pd.DataFrame): A pandas DataFrame of raw accelerometer data with columns 'x', 'y', 'z' and a DatetimeIndex.
197+
198+
Returns:
199+
- pd.DataFrame: A DataFrame with dates as index and daily wear statistics as columns:
200+
- 'WearTime(hours)': Total wear time in hours
201+
202+
Example:
203+
daily_wear_stats = calculate_daily_wear_stats(data)
204+
"""
205+
206+
if len(data) == 0:
207+
return pd.DataFrame()
208+
209+
# Identify non-wear periods (NaN in any of x,y,z columns)
210+
na = data.isna().any(axis=1)
211+
dt = infer_freq(data.index).total_seconds()
212+
213+
# Group by date
214+
date_groups = data.groupby(data.index.date)
215+
216+
results = []
217+
218+
for date, day_data in date_groups:
219+
day_na = na.loc[day_data.index]
220+
n_samples = len(day_data)
221+
222+
if n_samples == 0:
223+
# Skip empty days
224+
continue
225+
226+
# Calculate wear time
227+
nonwear_samples = day_na.sum()
228+
wear_samples = n_samples - nonwear_samples
229+
230+
# Convert to hours
231+
wear_hours = wear_samples * dt / 3600
232+
233+
results.append({
234+
'Date': pd.to_datetime(date),
235+
'WearTime(hours)': round(wear_hours, 2)
236+
})
237+
238+
if not results:
239+
return pd.DataFrame()
240+
241+
# Create DataFrame and set date as index
242+
daily_stats = pd.DataFrame(results)
243+
daily_stats.set_index('Date', inplace=True)
244+
daily_stats.index.name = 'Date'
245+
246+
return daily_stats
247+
248+
191249
def flag_wear_below_days(
192250
x: Union[pd.Series, pd.DataFrame],
193251
min_wear: str = '12H'

0 commit comments

Comments
 (0)