Last active
April 15, 2020 00:46
-
-
Save cjdinger/c0d942dcbd41140976110022e0a54e34 to your computer and use it in GitHub Desktop.
SnackBot API and time series analysis
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Described in the blog post: | |
The Internet of Snacks: SnackBot data and what it reveals about SAS life | |
https://blogs.sas.com/content/sasdummy/snackbot-api-timeseries/ | |
by Chris Hemedinger | |
*/ | |
/* Use these ODS statements in SAS for Windows or SAS Enterprise Guide */ | |
ods _all_ close; | |
filename results "%sysfunc(getoption(WORK))/snackbot.htm"; | |
ods html5 file=results style=Htmlencore gtitle options(svg_mode="inline"); | |
/* Use this one instead for SAS University Edition or SAS Studio */ | |
/* | |
ods html5 (id=web) style=Htmlencore gtitle options(svg_mode="inline"); | |
*/ | |
%let start = '20MAY2018:0:0:0'dt; | |
/* format the start/end per the API needs */ | |
%let start_time= %sysfunc(putn(&start.,is8601dt26.)); | |
%let end_time= %sysfunc(datetime(),is8601dt26.); | |
/* Call the SnackBot API from snackbot.net */ | |
filename resp temp; | |
proc http | |
method="GET" | |
url="http://snackbot.net/snackdata?start_time=&start_time.%str(&)end_time=&end_time.%str(&)utc_offset_minutes=-240" | |
out=resp; | |
run; | |
/* JSON libname engine to read the result */ | |
/* Simple record layout, all in the ROOT member */ | |
libname mms json fileref=resp; | |
/* raw count data at sampled timestamps */ | |
/* with a few timestamp transformations, */ | |
/* just for exploration */ | |
data mmlevels; | |
set mms.root; | |
drop ordinal_root timestamp; | |
/* Convert the TIMESTAMP field to native value -- it's a character */ | |
datetime = input(timestamp, anydtdtm.); | |
date = datepart(datetime); | |
time = timepart(datetime); | |
dow = date; | |
qhour = round(datetime,'0:15:0'T); | |
format datetime datetime20. | |
qhour datetime20. | |
date date9. | |
time timeampm10. | |
dow downame.; | |
run; | |
/* Empty data set with 15 minute interval slots */ | |
/* Regular intervals for the entire "study" period */ | |
data timeslots; | |
last = datetime(); | |
length qhour 8; | |
format qhour datetime20; | |
drop last i; | |
do i = &start. to last by '0:15:00't; | |
qhour = i; | |
output; | |
end; | |
run; | |
/* Merge the sample data with the timeslots */ | |
data expand; | |
merge mmlevels(keep=pieces qhour) timeslots; | |
by qhour; | |
run; | |
/* for empty timeslots, carry the sample data */ | |
/* forward, so we always have a count of pieces */ | |
/* Variation on a LOCF technique */ | |
data final; | |
set expand; | |
length day $ 3; | |
day=put(datepart(qhour),weekdate3.); | |
retain hold; | |
if not missing(pieces) then | |
hold=pieces; | |
else pieces=hold; | |
drop hold; | |
if not missing(pieces); | |
run; | |
/* Decriptive stats broken down by day of week */ | |
title "SnackBot readings per day-of-week"; | |
proc means data=mmlevels mean stddev max min; | |
var pieces; | |
class dow; | |
run; | |
/* Count of readings per hour of the day */ | |
title "SnackBot readings per hour"; | |
proc freq data=mmlevels ; | |
table time / out=perhour; | |
format time hour2.; | |
run; | |
ods graphics / imagefmt=svg height=400 width=800; | |
title "SnackBot readings per hour"; | |
proc sgplot data=perhour des="Readings per hour of day"; | |
step x=time y=count; | |
xaxis min='0:0:0't max='24:0:0't label="Time of day" grid; | |
yaxis label="Servings"; | |
run; | |
title 'Plain M&M pieces on S1 tracked by SnackBot'; | |
ods graphics / imagefmt=svg height=300 width=1600; | |
proc sgplot data=final des='M&M pieces tracked by SnackBot'; | |
/* plot the data as a series */ | |
series x=qhour y=pieces / lineattrs=(color=navy thickness=3px); | |
/* Yes, these are the "official" M&M colors */ | |
/* Will be applied in data-order, so works best when data */ | |
/* begins on a Sunday */ | |
styleattrs datacolors=(red orange yellow green blue CX593B18 red); | |
/* block areas to indicate days-of-week */ | |
block x=qhour block=day / transparency=0.65 | |
valueattrs=(weight=bold size=10pt color=navy); | |
xaxis minor display=(nolabel); | |
yaxis display=(nolabel) grid max=1600 minor; | |
run; | |
ods html5 close; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment