Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SnackBot API and time series analysis
/*
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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.