{"id":23331087,"url":"https://github.com/sassoftware/r-sasctl","last_synced_at":"2025-09-11T09:38:46.271Z","repository":{"id":66179967,"uuid":"593700820","full_name":"sassoftware/r-sasctl","owner":"sassoftware","description":"The R sasctl package enables easy communication between the SAS Viya platform and R. It focuses on interacting with SAS Viya APIs with additional features for SAS Model Manager.","archived":false,"fork":false,"pushed_at":"2025-04-03T20:59:08.000Z","size":22756,"stargazers_count":7,"open_issues_count":3,"forks_count":3,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-09T16:09:18.589Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://sassoftware.github.io/r-sasctl/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sassoftware.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-26T16:42:07.000Z","updated_at":"2025-04-03T20:54:38.000Z","dependencies_parsed_at":"2024-12-20T22:30:57.512Z","dependency_job_id":"5526941c-6351-4493-8b26-5d48dc10e73e","html_url":"https://github.com/sassoftware/r-sasctl","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sassoftware%2Fr-sasctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sassoftware%2Fr-sasctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sassoftware%2Fr-sasctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sassoftware%2Fr-sasctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sassoftware","download_url":"https://codeload.github.com/sassoftware/r-sasctl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065283,"owners_count":21041871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-20T22:30:51.554Z","updated_at":"2025-04-09T16:09:28.936Z","avatar_url":"https://github.com/sassoftware.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(eval = FALSE)\n\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n# R sasctl\n\n\u003c!-- badges: start --\u003e\n\n\u003c!-- badges: end --\u003e\n\n## Table of Contents\n1. [Overview](#overview)\n2. [Installation](#installation)  \n3. [Session](#session)  \n4. [Examples](#examples)  \n    * [PMML to SAS Example](#pmml-to-sas-example)  \n    * [A native R model example](#a-native-r-model-example)  \n    * [vPOST and vGET convenient functions](#vpost-and-vget-convenient-functions)  \n\n5. [Model Management helpers](#model-management-helpers)\n\n## Overview\n\nThe goal of sasctl is to provide tools for easy access of SAS Viya APIs from an R perspective. It has useful tools to make model management easier.\n\n## Installation\n\n\n### Install from R\n\n```{r, eval=FALSE}\n## dev version\nremotes::install_git(\"https://github.com/sassoftware/r-sasctl\")\n\n## released version\n## You first have to install the dependencies\n\ninstall.packages(c(\"jsonlite\", \"httr\", \"uuid\", \"furrr\", \"ROCR\", \"reshape2\", \"base64enc\", \"dplyr\", \"glue\"))\n\n## then the package\ninstall.packages(\"https://github.com/sassoftware/r-sasctl/releases/download/X.X.X/r-sasctl_X.X.X.tar.gz\", type = \"source\", repos = NULL)\n\nlibrary(\"sasctl\")\n```\n\n### Install from terminal\n\nThe SWAT package for R is available from SAS as a tar.gz file. You can download releases from [https://github.com/sassoftware/r-sasctl/releases](https://github.com/sassoftware/r-sasctl/releases).\n\nAfter you download the package, you can install the package with a command that is similar to the following:\n\n\n```{bash}\nR CMD INSTALL r-sasctl-X.X.X.tar.gz\n```\n\n## Session\n\nYou have a few options on how to make a connections to the SAS Viya server. The first example uses password authentication.\n\n```{r reg_connection_real, echo=FALSE, include=FALSE, cache = FALSE}\n\nsource(\"local_auth.R\")\n\n```\n\n```{r reg_connection, eval=FALSE}\nsess \u003c- session(hostname = \"http://myserver.sas.com\",\n                username = \"sasuser\",\n                password = \"s3cr3t\")\n\nsess\n```\n\nYou may also use the .authinfo file.\n\n```{r token_connection, eval=FALSE}\n## authinfo file (recommended)\n\nsess \u003c- session(hostname = \"http://myserver.sas.com\",\n                authinfo = \"./_authinfo\")\n\n# authinfo file structure:\n# default login sasuser password s3cr3t\n\n## or for mutiple hosts in a single file but hostname must match otherwise will fail\n# host http://server1.sas.com login sasuser password s3cr3t\n# host https://server2.sas.com login sasuser password s3cr3t\n\n```\n\nIf you were provided access tokens or client_id and client_secret, you may follow one of the following methods.\n\n```{r token_connection2, eval=FALSE}\n## cient_id and client_secret\nsess \u003c- session(hostname = \"http://myserver.sas.com\",\n                client_id = \"client_id\",\n                client_secret = \"client_s3cr3t\")\n\n## token type\n\nsess2 \u003c- session(hostname = \"https://myserver.sas.com\",\n                 oauth_token = token$access_token \n                  )\n\nsess2\n\n\n## if you want to use authorization code from Viya 4\n## will open a browser, login and then  copy and paste the code in the R prompt terminal\n## set client secret as \"\", only a client_id with authorization_code permission\n\nsess2 \u003c- session(hostname = \"https://myserver.sas.com\",\n                 username = \"username\" # not required, you will be prompt on browser\n                 client_id = \"client_id\", # only if default was removed\n                 auth_code = TRUE \n                )\n\n\n```\n\n\n## Examples\n\nThe following examples offer different options of the model management life cycle. First, the model is created. Then the model is registered and published. Finally, the model is scored. The code samples include expected responses inline as well.\n\n### PMML to SAS Example\n\n```{r full_example_part1, cache = TRUE}\nhmeq \u003c- read.csv(\"https://support.sas.com/documentation/onlinedoc/viya/exampledatasets/hmeq.csv\")\n\n## removing missing data\nhmeq[hmeq == \"\"] \u003c- NA # empty strings to NA\nhmeq \u003c- na.omit(hmeq)\nhmeq$BAD \u003c- as.factor(hmeq$BAD)\nhmeq$REASON \u003c- as.factor(hmeq$REASON)\nhmeq$JOB \u003c- as.factor(hmeq$JOB)\n\n## creating logistic regression\nmodel1 \u003c- glm(BAD ~ ., hmeq, family = binomial(\"logit\"))\nsummary(model1)\n## saving model as pmml\nXML::saveXML(pmml::pmml(model1, model.name = \"General_Regression_Model\",\n             app.name = \"Rattle/PMML\",\n             description = \"Logistic Regression Model\"),\n             \"my_model.pmml\")\n\n\n## registering the model\nmod \u003c- register_model(\n  session = sess,\n  file = \"my_model.pmml\",\n  name = \"R_model_pmml\",\n  type = \"pmml\",\n  project = \"rsasctl_auto\",\n  force = TRUE\n  )\n\nmodule \u003c- publish_model(sess, mod, \"R_model_pmml\") ## defaults to maslocal\n\n## 10 rows\n## see documentation for parallel request\n\nscored \u003c- masScore(sess, module, hmeq[1:10,-1])\n\nscored\n\n## deleteing a project delete all associated models\ndelete_project(sess, \"rsasctl_auto\")\n\n## delete the published model\ndelete_masmodule(sess, \"R_model_pmml\")\n\n```\n\n### A native R model example\n\n```{r example2, cache = TRUE}\n\nhmeq \u003c- read.csv(\"https://support.sas.com/documentation/onlinedoc/viya/exampledatasets/hmeq.csv\")\n\nhmeq[hmeq == \"\"] \u003c- NA\nhmeq \u003c- na.omit(hmeq) ### probably you don't want to do that, by for sake of simplicity\nhmeq$BAD \u003c- as.factor(hmeq$BAD)\nhmeq$REASON \u003c- as.factor(hmeq$REASON)\nhmeq$JOB \u003c- as.factor(hmeq$JOB)\n\n### creating train/test/val\npartition \u003c- sample(c(1,2,3), replace = TRUE, prob = c(0.7, 0.2, 0.1), size = nrow(hmeq))\n\n\n### logistic regression\nmodel1 \u003c- glm(formula = BAD ~ .,\n              family = binomial(link = 'logit'),\n              data = hmeq[partition == 1,]\n              )\n\n### model summary\nsummary(model1)\n\ndir.create(\"myModel\")\npath \u003c- \"myModel/\"\n\n\n## model saved\nsaveRDS(model1, paste0(path, 'rlogistic.rda'), version = 2)\n\n\n## creating the score code \ncode \u003c- codegen(model1, path = paste0(path, \"scoreCode.R\"), rds = \"rlogistic.rda\")\n\n## The following function to creates a sample if you don't want to use the generated code\n# create_scoreSample(path, openFile = FALSE)\n\n## scoring the whole table\n\n## running the generated scoring code for testing\ncodeExpression \u003c- str2expression(code)\neval(codeExpression)\n\nrdsPath \u003c- path\nresult \u003c- scoreFunction(LOAN = hmeq[, 'LOAN'],\n                        MORTDUE = hmeq[, 'MORTDUE'],\n                        VALUE = hmeq[, 'VALUE'],\n                        REASON = hmeq[, 'REASON'],\n                        JOB = hmeq[, 'JOB'],\n                        YOJ = hmeq[, 'YOJ'],\n                        DEROG = hmeq[, 'DEROG'],\n                        DELINQ = hmeq[, 'DELINQ'],\n                        CLAGE = hmeq[, 'CLAGE'],\n                        NINQ = hmeq[, 'NINQ'],\n                        CLNO = hmeq[, 'CLNO'],\n                        DEBTINC = hmeq[, 'DEBTINC'])\n\nscoreddf \u003c- as.data.frame(result)\nscoreddf$Actual \u003c- as.numeric(hmeq$BAD) - 1\nscoreddf$partition \u003c- partition\n\n### diagnostics requires the true Target column name defined in \"targetName\"\n### and the predicted probability column name defined in \"targetPredicted\"\n\ndiags \u003c- diagnosticsJson(validadedf = scoreddf[scoreddf$partition == 3,],\n                         traindf = scoreddf[scoreddf$partition == 1,],\n                         testdf = scoreddf[scoreddf$partition == 2,],\n                         targetEventValue = 1,\n                         targetName = \"Actual\",\n                         targetPredicted = \"EM_EVENTPROBABILITY\",\n                         path = path) ## safely ignore warning, knitr bug\n\n## writing other files\nwrite_in_out_json(hmeq[,-1], input = TRUE, path = path)\n\nwrite_in_out_json(scoreddf[-c(4, 8, 9)], input = FALSE, path = path)\n\nwrite_fileMetadata_json(scoreCodeName = \"scoreCode.R\",\n                        scoreResource = \"rlogistic.rda\",\n                        path = path)\n\nwrite_ModelProperties_json(modelName = \"Rlogistic\",\n                           modelFunction = \"Classification\",\n                           trainTable = \"hmeq\",\n                           algorithm = \"Logistic Regression\",\n                           numTargetCategories = 2,\n                           targetEvent = \"1\",\n                           targetVariable = \"BAD\",\n                           eventProbVar = \"P_BAD1\",\n                           modeler = \"sasctl man\",\n                           path = path)\n\nfiles_to_zip \u003c- list.files(path, \"*.json|*.R|*.rda\", full.names = T)\nzip(paste0(path, \"Rmodel.zip\"), \n    files = files_to_zip)\n\n\nmod \u003c- register_model(\n  session = sess,\n  file = \"myModel/Rmodel.zip\",\n  name = \"RzipModel\",\n  type = \"zip\",\n  project = \"R_sasctl\",\n  force = TRUE\n  )\n\n\n\n## deleteing a project delete all associated models\ndelete_project(sess, \"R_sasctl\")\n\n```\n\n### vPOST and vGET convenient functions\n\n#### MAS call example\n\nYou can make generic calls to endpoints with minimal effort.\n\n```{r convenient_get, cache = TRUE}\nmodels \u003c- vGET(sess, \n                  \"microanalyticScore/modules/\")\n\nmodels$items[c(2:3, 8)]\n```\n\nNext, we need to create the transform table using the correct JSON \npayload for a MAS call, which doesn’t have a standard format.\n\n```{json, cache = TRUE}\n### Payload for Viya MAS\n\n {\"inputs\": [\n             {\"name\": \"\u003cinput1_name\u003e\", \"value\": 123}, \n             {\"name\": \"\u003cinput2_name\u003e\", \"value\": \"string_value\"}, \n             {\"name\": \"\u003cinput3_name\u003e\", \"value\": null} ## if value: NA\n             ] \n }\n\n### Payload for SCR on Viya 2021.1.5 or higher\n\n  {\n    \"metadata\": {\n      \"\u003cmetadata_1\u003e\": 1,\n      \"\u003cmetadata_2\u003e\": \"any metadata string\",\n      \"\u003cmetadata_3\u003e\": 3\n    },\n    \"data\": {\n      \"\u003cinput1_name\u003e\": 5.1,\n      \"\u003cinput2_name\u003e\": 0.2,\n      \"\u003cinput3_name\u003e\": \"string_value\"\n    }\n  }\n```\n\nThere is a helper function that transform all the rows in a vector\nof strings, where each string is a JSON payload, since you cannot send\ndata for batch scoring.\n\n```{r json_transform, cache = TRUE}\nhmeq \u003c- read.csv(\"https://support.sas.com/documentation/onlinedoc/viya/exampledatasets/hmeq.csv\")\n\nhmeq_json \u003c- format_data_json(head(hmeq)) ## use argument scr = TRUE for newer format\n\njsonlite::prettify(hmeq_json[1])\n\n```\n\nThen you can make a call to a Model.\n\n```{r, cache = TRUE}\noutput \u003c- sasctl::vPOST(sess, \n                 path = \"microanalyticScore/modules/dt_hmeq/steps/score\",\n                 payload = hmeq_json[3], ## choose a row\n                 # content_type used to be hard coded, but we would have less flexibility\n                 httr::content_type(\"application/json\") \n                 )\n\noutput\n\n```\n\n### Model Management helpers\n\n```{r, cache = TRUE}\n## to write inputVar.json\n## removing BAD column\nwrite_in_out_json(hmeq[,2:ncol(hmeq)], input = FALSE)\n\n```\n\n```{r, cache = TRUE}\n## to write outputVar.json\n## you should create your own output dataframe since it will be what you\n## put in your score code, which usually means EM_PROBABILITY, EM_CLASSIFICATION,\n## or whaterver names you create P_BAD1, P_BAD0, etc.\n\nout_example \u003c- data.frame(P_BAD0 = 0.78,\n                           P_BAD1 = 0.22,\n                           BAD = '1')\n\nwrite_in_out_json(out_example)\n\n```\n\n```{r, cache = TRUE}\n## to write fileMetadata.json\n## defaults should be fine, unless you use different file names\n\nwrite_fileMetadata_json()\n\n```\n\n```{r, cache = TRUE}\n## to write ModelProperties.json\n## defaults should be fine, unless you use different file names\n\nwrite_ModelProperties_json(modelName = \"My R Model\", \n                           modelDescription = \"Awesome Description\", \n                           modelFunction = \"Classification\",\n                           trainTable = \" \",\n                           algorithm = \"Logistic Regression\",\n                           numTargetCategories = 2,\n                           targetEvent = \"BAD\",\n                           targetVariable = \"P_BAD1\",\n                           eventProbVar = \"P_BAD1\",\n                           modeler = \"John SAS\")\n\n```\n\n\n```{r delete_files, echo=FALSE, include=FALSE}\nunlink(c('inputVar.json', 'outputVar.json', \"ModelProperties.json\", \"fileMetadata.json\", \n         \"my_model.pmml\", \"my_model_converted42.pmml\", \n         \"myModel\"), recursive = TRUE)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsassoftware%2Fr-sasctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsassoftware%2Fr-sasctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsassoftware%2Fr-sasctl/lists"}