<jupyter_start><jupyter_text>Using R in SageMaker ProcessingAmazon SageMaker Processing is a capability of Amazon SageMaker that lets you easily run your preprocessing, postprocessing and model evaluation workloads on fully managed infrastructure.  In this example, we'll see how to use SageMaker Processing with the R programming language.The workflow for using R with SageMaker Processing involves the following steps:- Writing a R script.- Building a Docker container.- Creating a SageMaker Processing job.- Retrieving and viewing job results.    The R scriptTo use R with SageMaker Processing, first prepare a R script similar to one you would use outside SageMaker.  Below is the R script we'll be using.  It performs operations on data and also saves a .png of a plot for retrieval and display later after the Processing job is complete.  This enables you to perform any kind of analysis and feature engineering at scale with R, and also create visualizations for display anywhere.<jupyter_code>%%writefile preprocessing.R

library(readr)
library(dplyr)
library(ggplot2)
library(forcats)

input_dir <- "/opt/ml/processing/input/"
filename <- Sys.glob(paste(input_dir, "*.csv", sep=""))
df <- read_csv(filename)

plot_data <- df %>%
  group_by(state) %>%
  count()

write_csv(plot_data, "/opt/ml/processing/csv/plot_data.csv")

plot <- plot_data %>% 
  ggplot()+
  geom_col(aes(fct_reorder(state, n), 
               n, 
               fill = n))+
  coord_flip()+
  labs(
    title = "Number of people by state",
    subtitle = "From US-500 dataset",
    x = "State",
    y = "Number of people"
  )+ 
  theme_bw()

ggsave("/opt/ml/processing/images/census_plot.png", width = 10, height = 8, dpi = 100)<jupyter_output><empty_output><jupyter_text>Building a Docker containerNext, there is a one-time step to create a R container.  For subsequent SageMaker Processing jobs, you can just reuse this container (unless you need to add further dependencies, in which case you can just add them to the Dockerfile and rebuild).  To start, set up a local directory for Docker-related files.<jupyter_code>!mkdir docker<jupyter_output><empty_output><jupyter_text>A simple Dockerfile can be used to build a Docker container for SageMaker Processing.  For this example, we'll use a parent Docker image from the Rocker Project, which provides a set of convenient R Docker images.  There is no need to include your R script in the container itself because SageMaker Processing will ingest it for you.  This gives you the flexibility to modify the script as needed without having to rebuild the Docker image every time you modify it.<jupyter_code>%%writefile docker/Dockerfile

FROM rocker/tidyverse:latest

# tidyverse has all the packages we need, otherwise we could install more as follows
# RUN install2.r --error \
#    jsonlite \
#    tseries

ENTRYPOINT ["Rscript"]<jupyter_output><empty_output><jupyter_text>The Dockerfile is now used to build the Docker image.  We'll also create an Amazon Elastic Container Registry (ECR) repository, and push the image to ECR so it can be accessed by SageMaker.<jupyter_code>import boto3

account_id = boto3.client('sts').get_caller_identity().get('Account')
region = boto3.session.Session().region_name

ecr_repository = 'r-in-sagemaker-processing'
tag = ':latest'

uri_suffix = 'amazonaws.com'
processing_repository_uri = '{}.dkr.ecr.{}.{}/{}'.format(account_id, region, uri_suffix, ecr_repository + tag)

# Create ECR repository and push Docker image
!docker build -t $ecr_repository docker
!$(aws ecr get-login --region $region --registry-ids $account_id --no-include-email)
!aws ecr create-repository --repository-name $ecr_repository
!docker tag {ecr_repository + tag} $processing_repository_uri
!docker push $processing_repository_uri<jupyter_output><empty_output><jupyter_text>Creating a SageMaker Processing jobWith our Docker image in ECR, we now prepare for the SageMaker Processing job by specifying Amazon S3 buckets for output and input, and downloading the raw dataset.<jupyter_code>import sagemaker
from sagemaker import get_execution_role

role = get_execution_role()
session = sagemaker.Session()
s3_output = session.default_bucket()
s3_prefix = 'R-in-Processing'
s3_source = 'sagemaker-workshop-pdx'
session.download_data(path='./data', bucket=s3_source, key_prefix='R-in-Processing/us-500.csv')<jupyter_output><empty_output><jupyter_text>Before setting up the SageMaker Processing job, the raw dataset is uploaded to S3 so it is accessible to SageMaker Processing.<jupyter_code>rawdata_s3_prefix = '{}/data/raw'.format(s3_prefix)
raw_s3 = session.upload_data(path='./data', key_prefix=rawdata_s3_prefix)
print(raw_s3)<jupyter_output><empty_output><jupyter_text>The `ScriptProcessor` class of the SageMaker SDK lets you run a command inside a Docker container.  We'll use this to run our own script using the `Rscript` command.  In the `ScriptProcessor` you also can specify the type and number of instances to be used in the SageMaker Processing job.<jupyter_code>from sagemaker.processing import ScriptProcessor

script_processor = ScriptProcessor(command=['Rscript'],
                image_uri=processing_repository_uri,
                role=role,
                instance_count=1,
                instance_type='ml.c5.xlarge')<jupyter_output><empty_output><jupyter_text>We can now start the SageMaker Processing job.  The main aspects of the code below are specifying the input and output locations, and the name of our R preprocessing script.<jupyter_code>from sagemaker.processing import ProcessingInput, ProcessingOutput
from time import gmtime, strftime 

processing_job_name = "R-in-Processing-{}".format(strftime("%d-%H-%M-%S", gmtime()))
output_destination = 's3://{}/{}/data'.format(s3_output, s3_prefix)

script_processor.run(code='preprocessing.R',
                      job_name=processing_job_name,
                      inputs=[ProcessingInput(
                        source=raw_s3,
                        destination='/opt/ml/processing/input')],
                      outputs=[ProcessingOutput(output_name='csv',
                                                destination='{}/csv'.format(output_destination),
                                                source='/opt/ml/processing/csv'),
                               ProcessingOutput(output_name='images',
                                                destination='{}/images'.format(output_destination),
                                                source='/opt/ml/processing/images')])

preprocessing_job_description = script_processor.jobs[-1].describe()<jupyter_output><empty_output><jupyter_text>Retrieving and viewing job resultsFrom the SageMaker Processing job description, we can look up the S3 URIs of the output, including the output plot .png file.<jupyter_code>output_config = preprocessing_job_description['ProcessingOutputConfig']
for output in output_config['Outputs']:
    if output['OutputName'] == 'csv':
        preprocessed_csv_data = output['S3Output']['S3Uri']
    if output['OutputName'] == 'images':
        preprocessed_images = output['S3Output']['S3Uri']<jupyter_output><empty_output><jupyter_text>Now we can display the plot produced by the SageMaker Processing job.  A similar workflow applies to retrieving and working with any other output from a job, such as the transformed data itself.<jupyter_code>from PIL import Image
from IPython.display import display

plot_key = 'census_plot.png'
plot_in_s3 = '{}/{}'.format(preprocessed_images, plot_key)
!aws s3 cp {plot_in_s3} .
im = Image.open(plot_key)
display(im)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08795687615040758, 'fraction_numerical': 0.005653431501446227, 'mean_word_length': 4.171312032630864, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '550509', 'license': 'Apache-2.0', 'n_tokens_mistral': 2257, 'n_tokens_neox': 2128, 'n_words': 721, 'path': 'r_examples/r_in_sagemaker_processing/r_in_sagemaker_processing.ipynb', 'repo_name': 'P15241328/amazon-sagemaker-examples', 'size': '7606'}