[{"content":"Motivation I believe the most common discussion on data science teams is R vs Python. I saw myself in some of these discussions a couple of times and my position is always \u0026ldquo;Why not use both?\u0026rdquo;. The idea of this post is not to compare R vs Python but to show how easy it is to integrate both languages using APIs (LIKE A PRO), this way we can use the best of each. Also, the post won\u0026rsquo;t focus on the deployment and structure needed to bring the APIs online, instead, I will demonstrate it locally (to make it simple).\nThis post is divided into 3 sections: Creating a function, Creating an API, and Calling an API. In the first section, you will find a simple function created in R and Python, the second section is about how to transform that functions into APIs, the last one is how we can call/use the APIs.\nCreating a function Imagine that you are working in a data science team and someone needs a piece of code that return the sum of two values (sorry for the stupid example). See, the request is not about R, Python, Julia, Java, or whatever, but to solve the problem! So, let\u0026rsquo;s solve the problem the best way we can, and let\u0026rsquo;s write a function to solve it in R and Python.\nThis post will not cover the guidelines to create useful functions. For that I recommend you to take a look at the Functions section of the Advanced R Book.\nFunction in R A simple function to return the sum of two values in R would look like this:\nsum_two_r \u0026lt;- function(x, y) { result \u0026lt;- x + y return(result) } It is done, now we can call it inside R like this:\nsum_two_r(x = 1, y = 1) ## [1] 2 Function in Python A simple function to return the sum of two values in Python would look like this:\ndef sum_two_python(x, y): result = x + y return result It is done, now we can call it inside Python like this:\nsum_two_python(x = 1, y = 1) ## 2 Creating an API The problem is almost solved, but we still need to find the best way to share our solution with the rest of the team. Well, the part of the team that works in R can use the function we wrote in R, but that function is simply not available to the part of the team that uses Python, the same happens with the code written in Python which is simply not available to anyone using R. So, it is necessary to create a solution independent of the language to make it reachable for everyone on the team.\nI know the reticulate package can help, but it\u0026rsquo;s a one-way solution, and we are interested in a more generic form of integration that can be extended not just to Python, but to any programming language.\nOne good solution would be to create and deploy an API with our piece of code, this way the rest of the team can interact with it independently, in other words, doesn\u0026rsquo;t matter anymore what was the language you used to solve the problem. To do that we are going to use the plumber package for R and the FastAPI package for Python.\nThis post will not cover how to deploy the APIs. However, if you are interested in learning how to bring your APIs online you can use this link for plumber, and this link for FastAPI.\nAPI in R The first step to create an API in R is to install the plumber package:\ninstall.packages(\u0026#34;plumber\u0026#34;) That done, let\u0026rsquo;s get back to our function file and add a couple of things to it.\n#* @param x first number #* @param y second number #* @get /sum_r sum_two_r \u0026lt;- function(x, y) { result \u0026lt;- as.numeric(x) + as.numeric(y) return(result) } Notice that we add some \u0026ldquo;comments\u0026rdquo; at the begging of the code very similar to the ones used in the roxygen2 package. These comments are the key that plumber uses to transform your functions in APIs endpoints. Also, for this example, we defined a GET request, the same could be done, for example, with POST requests by changing the comment to #* @post /sum_r.\nIf you are not familiar with HTTP requests you can take a look at this link.\nYou can see that it was included the as.numeric() transformation, which is necessary because the parameters \u0026ldquo;enter\u0026rdquo; R as strings, and to apply mathematical operations it is necessary to transform the numeric ones into numbers.\nThe next step is to deploy it! To bring it online you just need to provide the file path and the port you want to expose the API. We are going to make it available locally (localhost) at the port 8000 by running:\nlibrary(magrittr) library(plumber) pr(\u0026#39;functions/sum_r.R\u0026#39;) %\u0026gt;% pr_run(port = 8000) Done! Now our API is exposed and you can access the Swagger documentation at http://localhost:8000/docs/, and you can interact with it by pressing GET, followed by the Try it out button, fill in the parameters and press Execute.\nIf you want to learn more about Swagger UI here is the link for you.\nAPI in Python The first step to create an API in Python is to install the FastAPI package. On the terminal run:\n$ pip install fastapi[all] That done, let\u0026rsquo;s get back to our function file and add a couple of things to it.\nfrom fastapi import FastAPI app = FastAPI() @app.get(\u0026#34;/sum_py\u0026#34;) def sum_two_python(x:float, y:float): result = x + y return result Notice that we import the fastapi package and we created an object called app that is a FastAPI instance. Then we defined it as a GET request, the same could be done, for example, with POST requests by changing to @app.post(\u0026quot;/sum_py\u0026quot;).\nYou can see that it was included the :float to force the variable type to be numeric, that is necessary because the default APIs calls \u0026ldquo;enter\u0026rdquo; Python as strings, and to apply mathematical operations it is necessary to transform the numeric ones into numbers.\nThe next step is to deploy it! To bring it online you just need to open the terminal and get inside the folder you saved your Python API script. I named my file as \u0026ldquo;sum_py\u0026rdquo; and I am going to make it available locally (localhost) at the port 8080 by running:\n$ uvicorn sum_py:app --port 8080 --reload The reload option will reload your API every time you save the file. It is a very good feature for development!\nDone! Now our API is exposed and you can access the Swagger documentation at http://localhost:8080/docs#/, and you can interact with it by pressing GET, followed by the Try it out button, fill in the parameters and press Execute.\nOf course, in the real world, the deployment of your APIs shouldn\u0026rsquo;t be local, but the logic will be (almost) the same. Also, there are MUCH MORE FEATURES on the API development, so my advice would be to read the plumber and FastAPI documentation to learn more about it.\nCalling an API From now on, the solution should be available for EVERYONE in the team, whether they use Python, R, etc. Now things will get crazy because we are going to call the Python API in R and the R API in Python!!! 😵\nPS: Keep both APIs running locally!\nCalling an API in R It is very simple to call APIs using R, and for that, we are going to use the httr package. Let\u0026rsquo;s install it:\ninstall.packages(\u0026#34;httr\u0026#34;) Do you remember that our Python API is running locally (localhost) at the port 8080? Well, that and the request type (GET, in this case) are the only information we need to call it through R.\nlibrary(httr) python_request \u0026lt;- GET(\u0026#39;http://localhost:8080/sum_py?x=1\u0026amp;y=1\u0026#39;) python_result \u0026lt;- content(python_request) python_result ## [1] 2 Calling an API in Python Let\u0026rsquo;s do the same, but this time we are going to call the R API through Python! For that, it will be necessary to install the requests package.\n$ pip install requests Our R API is also running on localhost but at the port 8000. Again, that and the request type (GET, in this case) are the only information we need to call it through Python.\nimport requests r_request = requests.get(\u0026#34;http://localhost:8000/sum_r?x=1\u0026amp;y=1\u0026#34;) print(r_request.json()) ## [2] That is all There are MUCH MORE to discuss when we talk about APIs/deploy/calls/requests, but the idea was to make it simple, to demonstrate the possibilities, and to STOP THE FIGHT between R and Python 😆. I believe this post is a good example of how to integrate both languages (LIKE A PRO), because, in the end, we want to SOLVE THE PROBLEM!!! Does it really matter if you solved it in Python or R?\nI hope someone finds this useful. As always your feedback is much appreciated, feel free to get in touch with me over social media! 😄\n","permalink":"https://adsoncostanzifilho.github.io/blog/why-not-both/","summary":"\u003ch2 id=\"motivation\"\u003eMotivation\u003c/h2\u003e\n\u003cp\u003eI believe the most common discussion on data science teams is R vs Python. I saw myself in some of these discussions a couple of times and my position is always \u0026ldquo;\u003cem\u003eWhy not use both?\u003c/em\u003e\u0026rdquo;. The idea of this post is not to compare R vs Python but to show how easy it is to \u003cstrong\u003eintegrate both languages using APIs\u003c/strong\u003e (LIKE A PRO), this way we can use the best of each. Also, the post won\u0026rsquo;t focus on the deployment and structure needed to bring the APIs online, instead, I will demonstrate it locally (to make it simple).\u003c/p\u003e","title":"Why not both?"},{"content":"Motivation Recently I was introduced by some friends to the GitHub Actions and how it could help me execute tasks like: deploy my Shiny Apps, deploy this Blogdown, perform automated tests in packages, refresh data, and more. So, I decided to give it a try, and it was so simple and saved me so many work hours that I decided to write this post explaining how R developers can make good use of this amazing tool.\nFirst the references I used to start on GitHub Actions:\nThe Jim Hester presentation on the RStudio Conference here.\nThe GitHub Actions for the R language repository here.\nThe GitHub Actions Documentation here.\nStart with usethis The easier and faster way to get started with the GitHub Actions in R is, for sure, using the usethis package! So, let\u0026rsquo;s first install it.\ninstall.packages(\u0026#34;usethis\u0026#34;) The first very interesting function about the GitHub Action in the usethis package is the usethis::browse_github_actions() with this function you can see the active actions running in the most diverse R packages. This is a very good start to give you an idea of what are the Actions used in big R packages like \u0026ldquo;shiny\u0026rdquo;, \u0026ldquo;dplyr\u0026rdquo;, etc.\nThe usethis also have the usethis::use_github_action() function, which in my opinion is the easier way to start. It will create for you the necessary files/folders structure necessary for GitHub understands and runs your Actions, in other words, it will create the .github folder \u0026gt; workflows folder \u0026gt; .yaml file inside your current project path. This function also needs as argument a specific workflow name (you can check the available options here), depending on what option you choose it can give you a very good start point (sometimes you don\u0026rsquo;t need to change a thing). For example if you run usethis::use_github_action(\u0026quot;pkgdown\u0026quot;) it will create for you the default folder structure (.github folder \u0026gt; workflows folder \u0026gt; file.yaml) and it will start a .yaml file like this:\non: push: branches: - main - master name: pkgdown jobs: pkgdown: runs-on: macOS-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - uses: r-lib/actions/setup-r@v1 - uses: r-lib/actions/setup-pandoc@v1 - name: Query dependencies run: | install.packages(\u0026#39;remotes\u0026#39;) saveRDS(remotes::dev_package_deps(dependencies = TRUE), \u0026#34;.github/depends.Rds\u0026#34;, version = 2) writeLines(sprintf(\u0026#34;R-%i.%i\u0026#34;, getRversion()$major, getRversion()$minor), \u0026#34;.github/R-version\u0026#34;) shell: Rscript {0} - name: Restore R package cache uses: actions/cache@v2 with: path: ${{ env.R_LIBS_USER }} key: ${{ runner.os }}-${{ hashFiles(\u0026#39;.github/R-version\u0026#39;) }}-1-${{ hashFiles(\u0026#39;.github/depends.Rds\u0026#39;) }} restore-keys: ${{ runner.os }}-${{ hashFiles(\u0026#39;.github/R-version\u0026#39;) }}-1- - name: Install dependencies run: | remotes::install_deps(dependencies = TRUE) install.packages(\u0026#34;pkgdown\u0026#34;, type = \u0026#34;binary\u0026#34;) shell: Rscript {0} - name: Install package run: R CMD INSTALL . - name: Deploy package run: | git config --local user.email \u0026#34;actions@github.com\u0026#34; git config --local user.name \u0026#34;GitHub Actions\u0026#34; Rscript -e \u0026#39;pkgdown::deploy_to_branch(new_process = FALSE)\u0026#39; We will cover the presented steps inside the .yaml file later, as well as present some specific workflows for:\nDeploy your shiny on shinyapps.io automatically\nDeploy your blogdow page on GitHub Pages automatically.\nPerform automatic tests on your R packages.\nSchedule some routines.\nRemember, the GitHub will only execute the .yaml files inside the workflows folder (which is inside the .github folder)!\nAutomatic Shiny Deploy How amazing would it be if every time you \u0026ldquo;push\u0026rdquo; a new feature in your shiny repository on GitHub it automatically performed the deployment procedures to bring the new version of your app online on shinyapps.io? Thanks to GitHub Actions it is now possible!\nBefore we start to make an Action procedure to deploy your shiny apps on shinyapps.io we must create the folder structure GitHub needs. So, let\u0026rsquo;s create the .github folder and inside it we should create the workflows folder and only then we can start our .yaml file.\nNow that we have the structure we can start developing our deployment procedure. The first thing to do is to define which trigger we want to use to \u0026ldquo;activate\u0026rdquo; the GitHub Action. Let\u0026rsquo;s say we want GitHub to execute this every time we push on the master branch. So, our file should start like this:\n# Triggered on push branch master on: push: branches: [ master ] The second step is to define the name of the workflow and the operational system you want. GitHub actions has several OS options to choose including the 3 most popular ones ubuntu, macos and windows. I am going to name our procedure as \u0026ldquo;Shiny-Deploy\u0026rdquo; and we are going to use the macos-10.15.\nYou can associate your actions to badges with the usethis package. For example, if the name of your workflow is \u0026ldquo;Shiny-Deploy\u0026rdquo; you can add this badge in your README file runing usethis::use_github_actions_badge(\u0026quot;Shiny-Deploy\u0026quot;).\n# Name of the workflow - usethis::use_github_actions_badge(\u0026#34;Shiny-Deploy\u0026#34;) name: Shiny-Deploy # Set the job, the machine and the R version jobs: Shiny-Deploy: runs-on: macos-10.15 strategy: matrix: r-version: [4.0.2] Now that we already have our GitHub Actions machine we can start developing the steps! Let\u0026rsquo;s first clone the repository from the respective branch that has triggered the action.\nPS: from now on all the actions will be \u0026ldquo;inside\u0026rdquo; the steps structure.\nsteps: # Cloning your repository from the respective branch that has triggered it - uses: actions/checkout@v2 Nice! We already made a copy of our files, now we need to set-up the R installation in our GitHub Actions machine to be able to run our R scripts. We will also set-up the pandoc to compile our shiny or Rmarkdown scripts.\n# set-up an R installation in our GHA machine to run our scripts - name: Set up R ${{ matrix.r-version }} uses: r-lib/actions/setup-R@v1 # for macos with: r-version: ${{ matrix.r-version }} # We will also need pandoc to compile our Shiny or RMarkdown report - name: Setting up pandoc uses: r-lib/actions/setup-pandoc@v1 From now on we can execute some R scripts directly in the shell of our GitHub Actions machine. Therefore, our next step will be to install all the packages your shiny app needs. Obviously, this step will change depending on what packages you used to build your app.\nDon\u0026rsquo;t forget to include the rsconnect package! We are going to use this package to connect our GitHub machine to the shinyapps server.\n# Install R packages - name: Install dependencies run: | install.packages(c( \u0026#34;rsconnect\u0026#34;, \u0026#34;dplyr\u0026#34;, \u0026#34;shiny\u0026#34;, \u0026#34;shinyjs\u0026#34;, \u0026#34;shinyWidgets\u0026#34;, \u0026#34;shinyalert\u0026#34;, \u0026#34;shinycssloaders\u0026#34;, \u0026#34;evaluate\u0026#34;, \u0026#34;highr\u0026#34;, \u0026#34;knitr\u0026#34;, \u0026#34;markdown\u0026#34;, \u0026#34;rmarkdown\u0026#34;, \u0026#34;stringi\u0026#34;, \u0026#34;stringr\u0026#34;, \u0026#34;tinytex\u0026#34;, \u0026#34;xfun\u0026#34; )) shell: Rscript {0} Now comes the tricky part! In order to make the connection between your GitHub Actions machine and your shiny apps account we need to set your shiny apps token and key. Evidently, for security reasons you don\u0026rsquo;t want to publish you shinyapps credentials for everyone accessing your GitHub repository. However, we also need your token and keys to be able to deploy your app automatically, that is why we are going to use the GitHub Secrets feature!\nFirst you need to go to your shiny apps account click in your profile name and enter in the tokes option.\nIf you don\u0026rsquo;t have created your shinyapps tokens yet, or if you want to use a new one, you can click on the + Add Token button. Once you did that a new line will appear and you should be able to see your Token but not your Secret. You need to press the Show button followed by the Show Secret to be bale to copy your Secret credential.\nNow we need to include this credentials on GitHub Secrets! To do that you need to enter in your GitHub repository page and go to Settings.\nOn the left menu you should be able to see the Secrets option. Once you enter in the Secrets tab you will see the title \u0026ldquo;Actions secrets\u0026rdquo;, and just on its side you will see the \u0026ldquo;New repository secret\u0026rdquo; button. You need to click this button to create your encrypted environment variables (in this case your shinyapps credentials).\nWe are going to create 2 different environment variables, the first named \u0026ldquo;SHINYAPP_TOKEN\u0026rdquo; and the second named \u0026ldquo;SHINYAPP_SECRET\u0026rdquo; (of course you can set any name you want). Once you clicked on the \u0026ldquo;New repository secret\u0026rdquo; button you will need to provide the name of your variable and the value of it and press \u0026ldquo;Add Secret\u0026rdquo;, as you can see below.\nYour Secret and Token don\u0026rsquo;t need to be in quotes (\u0026ldquo;my token\u0026rdquo;)!\nOk, now we can use these two variables inside our .yaml file, and we should be able to deploy our app on the shinyapps server! You also must provide your shinyapps account name, your app name, and the directory of your app scripts. Sure you can set all this using the GitHub Secrets if you want.\n# Connect on shinyapps server - name: Connect to ShinyApps env: # set the shinyapps keys as environment variables SHINY_TOKEN: ${{ secrets.SHINYAPP_TOKEN }} SHINY_SECRET: ${{ secrets.SHINYAPP_SECRET }} run: | shiny_token = Sys.getenv(\u0026#34;SHINY_TOKEN\u0026#34;) shiny_secret = Sys.getenv(\u0026#34;SHINY_SECRET\u0026#34;) rsconnect::setAccountInfo(name = \u0026#39;adsoncostanzi\u0026#39;, token = shiny_token, secret = shiny_secret) shell: Rscript {0} # deploy the app on shinyapps server - name: Deploy to shinyapps.io run: | rsconnect::deployApp(appName = \u0026#34;soothsayeR\u0026#34;, appDir = \u0026#34;app\u0026#34;) shell: Rscript {0} That\u0026rsquo;s it, now the GitHub will deploy your shiny on shinyapps any time you \u0026ldquo;push\u0026rdquo; on the master branch!\nFor reasons of copy and paste, here is the full .yaml file!\nFollow the indentation, it is an essential part of the code!\n# Triggered on push branch master on: push: branches: [ master ] # Name of the workflow - usethis::use_github_actions_badge(\u0026#34;Shiny-Deploy\u0026#34;) name: Shiny-Deploy # Set the job, the machine and the R version jobs: Shiny-Deploy: #runs-on: ubuntu-latest runs-on: macos-10.15 strategy: matrix: r-version: [4.0.2] steps: # Cloning your repository from the respective branch that has triggered it - uses: actions/checkout@v2 # set-up an R installation in our GHA machine to run our scripts - name: Set up R ${{ matrix.r-version }} uses: r-lib/actions/setup-R@v1 # for macos with: r-version: ${{ matrix.r-version }} # We will also need pandoc to compile our Shiny or RMarkdown report - name: Setting up pandoc uses: r-lib/actions/setup-pandoc@v1 # Install R packages - name: Install dependencies run: | install.packages(c( \u0026#34;rsconnect\u0026#34;, \u0026#34;dplyr\u0026#34;, \u0026#34;shiny\u0026#34;, \u0026#34;shinyjs\u0026#34;, \u0026#34;shinyWidgets\u0026#34;, \u0026#34;shinyalert\u0026#34;, \u0026#34;shinycssloaders\u0026#34;, \u0026#34;evaluate\u0026#34;, \u0026#34;highr\u0026#34;, \u0026#34;knitr\u0026#34;, \u0026#34;markdown\u0026#34;, \u0026#34;rmarkdown\u0026#34;, \u0026#34;stringi\u0026#34;, \u0026#34;stringr\u0026#34;, \u0026#34;tinytex\u0026#34;, \u0026#34;xfun\u0026#34; )) shell: Rscript {0} # Connect in shinyapps server - name: Connect to ShinyApps env: # set the shinyapps keys as environment variables SHINY_TOKEN: ${{ secrets.SHINYAPP_TOKEN }} SHINY_SECRET: ${{ secrets.SHINYAPP_SECRET }} run: | shiny_token = Sys.getenv(\u0026#34;SHINY_TOKEN\u0026#34;) shiny_secret = Sys.getenv(\u0026#34;SHINY_SECRET\u0026#34;) rsconnect::setAccountInfo(name = \u0026#39;adsoncostanzi\u0026#39;, token = shiny_token, secret = shiny_secret) shell: Rscript {0} # deploy the app on shinyapps server - name: Deploy to shinyapps.io run: | rsconnect::deployApp(appName = \u0026#34;soothsayeR\u0026#34;, appDir = \u0026#34;app\u0026#34;) shell: Rscript {0} Automatic Blogdown Deploy What about make your blogdown deploy automatic on GitHub Pages? Every time you write a new post you will only need to \u0026ldquo;push\u0026rdquo; and the GitHub Actions will take care of the rest! This procedure works very similar to the shiny one, so let\u0026rsquo;s start our .yaml file!\nFor the blogdwon deploy purpose we are going to use two different branches: The first one named \u0026ldquo;source\u0026rdquo; that will contain the development side of our blogdown. And the \u0026ldquo;master\u0026rdquo; branch that will expose the built page (the master branch will receive the result of blogdown::build_site(local = FALSE)).\nThe master branch MUST be the one with the build_site() content!\nThis way we will set our trigger as a \u0026ldquo;push\u0026rdquo; on the \u0026ldquo;source\u0026rdquo; branch:\n# Triggered on push branch source on: push: branches: - source In the next step, we will define the workflow name and the OS we want to use. For this example, we are going to name our workflow as \u0026ldquo;deployblog\u0026rdquo; and the OS will be an Ubuntu 18.04.\n# Name of the workflow - usethis::use_github_actions_badge(\u0026#34;deployblog\u0026#34;) name: deployblog # Set the job, the machine jobs: deployblog: name: Render and deploy blogdown runs-on: ubuntu-18.04 The easier part is done, now let\u0026rsquo;s start the steps! So, we are going to clone the repository (on the \u0026ldquo;source\u0026rdquo; branch), and set up R and pandoc, as we did on the shiny deploy session.\nPS: from now on all the actions will be \u0026ldquo;inside\u0026rdquo; the steps structure.\nsteps: # Cloning your repository from the respective branch that has triggered it - uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 # set-up an R installation in our GHA machine to run our scripts - uses: r-lib/actions/setup-r@v1 # We will also need pandoc to compile our Shiny or RMarkdown report - uses: r-lib/actions/setup-pandoc@v1 Now that we have our scripts and the R settled up we can proceed with the package installation, as well as install HUGO, as follows:\n# Install R packages - name: Install r packages run: | Rscript -e \u0026#39;install.packages(c(\u0026#34;remotes\u0026#34;, \u0026#34;rmarkdown\u0026#34;))\u0026#39; \\ -e \u0026#39;remotes::install_github(\u0026#34;rstudio/blogdown\u0026#34;)\u0026#39; - name: install hugo # Install Hugo run: Rscript -e \u0026#39;blogdown::install_hugo(extended = TRUE, version = \u0026#34;0.78.2\u0026#34;)\u0026#39; - name: Get themes run: git submodule update --remote That finished we must be able to render/build our blogdown in a specific folder (in this case will be the \u0026ldquo;public\u0026rdquo; folder) using the blogdown::build_site(local = FALSE) function. That done we just need to push the content of the \u0026ldquo;public\u0026rdquo; folder to the master branch and your blogdown will be online on GitHub Pages!\n- name: Look at files run: ls ./public - name: Render blog run: Rscript -e \u0026#39;blogdown::build_site(local = FALSE)\u0026#39; - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: master I STOLE THIS SCRIPT FROM MY GOOD FRIEND LUCAS GODOY (he also taught me how to make it work)!\nFor reasons of copy and paste, here is the full .yaml file!\n# Triggered on push branch source on: push: branches: - source # Name of the workflow - usethis::use_github_actions_badge(\u0026#34;deployblog\u0026#34;) name: deployblog # Set the job, the machine jobs: deployblog: name: Render and deploy blogdown runs-on: ubuntu-18.04 steps: # Cloning your repository from the respective branch that has triggered it - uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 # set-up an R installation in our GHA machine to run our scripts - uses: r-lib/actions/setup-r@v1 # We will also need pandoc to compile our Shiny or RMarkdown report - uses: r-lib/actions/setup-pandoc@v1 # Install R packages - name: Install r packages run: | Rscript -e \u0026#39;install.packages(c(\u0026#34;remotes\u0026#34;, \u0026#34;rmarkdown\u0026#34;))\u0026#39; \\ -e \u0026#39;remotes::install_github(\u0026#34;rstudio/blogdown\u0026#34;)\u0026#39; - name: install hugo # Install Hugo run: Rscript -e \u0026#39;blogdown::install_hugo(extended = TRUE, version = \u0026#34;0.78.2\u0026#34;)\u0026#39; - name: Get themes run: git submodule update --remote - name: Look at files run: ls ./public - name: Render blog run: Rscript -e \u0026#39;blogdown::build_site(local = FALSE)\u0026#39; - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: master publish_dir: ./public Automatic Tests I would say that execute tests manually can be the most time-consuming job presented in this post, and that is why performing automatic tests can save you lots of work hours! I know that automatic tests are very specific, in other words, it will depend on what kind of tests you want to perform. However, we can have a very good start point with the usethis package!\nFor example, by running the usethis::use_github_action_check_full() function it will create the default R-CMD-check procedure for you in a GitHub Actions structure. The R-CMD-check will stimulate the usage of your codes on the most diverse environments, such as on windows, ubuntu and, macos, all the three running different R versions as well. My advise is use as a start point the .yaml provided by the usethis::use_github_action_check_full() function to perform your own automatic tests.\nYou can find below the .yaml file generated by the usethis::use_github_action_check_full() function:\non: push: branches: - main - master pull_request: branches: - main - master name: R-CMD-check jobs: R-CMD-check: runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.r }}) strategy: fail-fast: false matrix: config: - {os: macOS-latest, r: \u0026#39;release\u0026#39;} - {os: windows-latest, r: \u0026#39;release\u0026#39;} - {os: windows-latest, r: \u0026#39;3.6\u0026#39;} - {os: ubuntu-18.04, r: \u0026#39;devel\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;, http-user-agent: \u0026#34;R/4.0.0 (ubuntu-18.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions\u0026#34; } - {os: ubuntu-18.04, r: \u0026#39;release\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;} - {os: ubuntu-18.04, r: \u0026#39;oldrel\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;} - {os: ubuntu-18.04, r: \u0026#39;3.5\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;} - {os: ubuntu-18.04, r: \u0026#39;3.4\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;} - {os: ubuntu-18.04, r: \u0026#39;3.3\u0026#39;, rspm: \u0026#34;https://packagemanager.rstudio.com/cran/__linux__/bionic/latest\u0026#34;} env: RSPM: ${{ matrix.config.rspm }} GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - uses: r-lib/actions/setup-r@v1 id: install-r with: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} - uses: r-lib/actions/setup-pandoc@v1 - name: Install pak and query dependencies run: | install.packages(\u0026#34;pak\u0026#34;, repos = \u0026#34;https://r-lib.github.io/p/pak/dev/\u0026#34;) saveRDS(pak::pkg_deps(\u0026#34;local::.\u0026#34;, dependencies = TRUE), \u0026#34;.github/r-depends.rds\u0026#34;) shell: Rscript {0} - name: Restore R package cache uses: actions/cache@v2 with: path: | ${{ env.R_LIBS_USER }} !${{ env.R_LIBS_USER }}/pak key: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-${{ hashFiles(\u0026#39;.github/r-depends.rds\u0026#39;) }} restore-keys: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1- - name: Install system dependencies if: runner.os == \u0026#39;Linux\u0026#39; run: | pak::local_system_requirements(execute = TRUE) pak::pkg_system_requirements(\u0026#34;rcmdcheck\u0026#34;, execute = TRUE) shell: Rscript {0} - name: Install dependencies run: | pak::local_install_dev_deps(upgrade = TRUE) pak::pkg_install(\u0026#34;rcmdcheck\u0026#34;) shell: Rscript {0} - name: Session info run: | options(width = 100) pkgs \u0026lt;- installed.packages()[, \u0026#34;Package\u0026#34;] sessioninfo::session_info(pkgs, include_base = TRUE) shell: Rscript {0} - name: Check env: _R_CHECK_CRAN_INCOMING_: false run: | options(crayon.enabled = TRUE) rcmdcheck::rcmdcheck(args = c(\u0026#34;--no-manual\u0026#34;, \u0026#34;--as-cran\u0026#34;), error_on = \u0026#34;warning\u0026#34;, check_dir = \u0026#34;check\u0026#34;) shell: Rscript {0} - name: Show testthat output if: always() run: find check -name \u0026#39;testthat.Rout*\u0026#39; -exec cat \u0026#39;{}\u0026#39; \\; || true shell: bash - name: Upload check results if: failure() uses: actions/upload-artifact@main with: name: ${{ matrix.config.os }}-r${{ matrix.config.r }}-results path: check Scheduled Routines GitHub Actions also provides the option of schedule routines, in other words, you can define as triggers any specific time you want. To do that GitHub Actions uses the cron syntax, that is the hard part (at least for me who had never used it). First, let\u0026rsquo;s understand the syntax GitHub Actions uses to run the scheduled routines!\nThe cron syntax is divided in 5 pieces (*****):\nThe first peace is to define the minute (0 - 59)\nThe second peace is to define the hour (0 - 23)\nThe third peace is to define the day of the month (1 - 31)\nThe fourth peace is to define month (1 - 12)\nThe fifth peace is to define the day of the week (0 - 6)\nObviously, you don\u0026rsquo;t want to run your routine just once! So, you need some way to abstract some of the pieces, in the con syntax, it is by using an asterisk (*). For example, the ***** means run the routine every minute every day!\nKip in mind that the GitHub times are based on UTC!\nHere there are some helpful examples I took from this post:\n# Every Monday at 1PM UTC (9AM EST) 0 13 * * 1 # At the end of every day 0 0 * * * # Every 10 minutes */10 * * * * What about the .yaml syntax? It is very simple, instead of using the \u0026ldquo;on\u0026rdquo; followed by \u0026ldquo;push\u0026rdquo;, \u0026ldquo;merge\u0026rdquo;, \u0026ldquo;pull_request\u0026rdquo;, etc., you should write \u0026ldquo;schedule\u0026rdquo; and it is done!\non: schedule: - cron: \u0026#39;0 0 * * *\u0026#39; That is all I hope someone finds this tutorial useful. As always your feedback is much appreciated, feel free to get in touch with me over social media! 😄\n","permalink":"https://adsoncostanzifilho.github.io/blog/github-actions-for-r-users/","summary":"\u003ch2 id=\"motivation\"\u003eMotivation\u003c/h2\u003e\n\u003cp\u003eRecently I was introduced by some friends to the \u003cstrong\u003eGitHub Actions\u003c/strong\u003e and how it could help me execute tasks like: deploy my \u003cem\u003eShiny Apps\u003c/em\u003e, deploy this \u003cem\u003eBlogdown\u003c/em\u003e, perform automated tests in packages, refresh data, and more. So, I decided to give it a try, and it was so simple and saved me so many work hours that I decided to write this post explaining how R developers can make good use of this amazing tool.\u003c/p\u003e","title":"GitHub Actions for R Users"},{"content":" Overview GitHub: adsoncostanzifilho/CSGo\nThe CSGo package is an R client for accessing Steam\u0026rsquo;s REST API specifically for the Counter-Strike Global Offensive Game (CS Go) data. Check out the Steam documentation website and the Package Page for more information.\nInstallation To get the current released version from CRAN:\ninstall.packages(\u0026#34;CSGo\u0026#34;) To get the current development version from GitHub:\n# install.packages(\u0026#34;devtools\u0026#34;) devtools::install_github(\u0026#34;adsoncostanzifilho/CSGo\u0026#34;) Example The first step to use the CSGo package is to have your own credentials (API key) to pull the CSGo data from the Steam API. For more information about how to get your own API Key run in your R vignette(\u0026quot;auth\u0026quot;, package = \u0026quot;CSGo\u0026quot;), or click here.\nNow that you already have your API Key you should be able to collect your own CSGo data as well as your friends\u0026rsquo; data. I hope my friend Rodrigo doesn\u0026rsquo;t mind us playing with his data (he is the \u0026lsquo;76561198263364899\u0026rsquo;)!\nFirst let\u0026rsquo;s collect his CSGo statistics:\nlibrary(CSGo) # to get the statistics of the user 76561198263364899 rodrigo_stats \u0026lt;- get_stats_user(api_key = \u0026#39;your_key\u0026#39;, user_id = \u0026#39;76561198263364899\u0026#39;) Let\u0026rsquo;s just filter the obtained data frame by \u0026ldquo;kills\u0026rdquo; and \u0026ldquo;weapon\u0026rdquo; to create an analysis of kills by type of weapon.\nlibrary(dplyr) library(stringr) rodrigo_weapon_kill \u0026lt;- rodrigo_stats %\u0026gt;% filter( str_detect(name, \u0026#39;kill\u0026#39;), type == \u0026#39; weapon info\u0026#39; ) %\u0026gt;% arrange(desc(value)) Now let\u0026rsquo;s take a look at the graphic!\nPS: To make the graphic even more beautiful I recommend getting the \u0026ldquo;Quantico\u0026rdquo; font from Google fonts using the showtext package!\nlibrary(ggplot2) library(showtext) ## Loading Google fonts (https://fonts.google.com/) font_add_google(\u0026#34;Quantico\u0026#34;, \u0026#34;quantico\u0026#34;) rodrigo_weapon_kill %\u0026gt;% top_n(n = 10, wt = value) %\u0026gt;% ggplot(aes(x = name_match, y = value, fill = name_match)) + geom_col() + ggtitle(\u0026#34;KILLS BY WEAPON\u0026#34;) + ylab(\u0026#34;Number of Kills\u0026#34;) + xlab(\u0026#34;\u0026#34;) + labs(fill = \u0026#34;Weapon Name\u0026#34;) + theme_csgo(text = element_text(family = \u0026#34;quantico\u0026#34;)) + scale_fill_csgo() So, these are the top 10 weapons by kills, but.. What about the efficiency? Is the ak47 the Rodrigo\u0026rsquo;s more efficient weapon? First, let\u0026rsquo;s define \u0026ldquo;efficiency\u0026rdquo;:\nkills_efficiency means how many shots he did to kill (ex: 32% shots will kill)\nhits_efficiency means how many shots to have a hit, this is more related to Rodrigo\u0026rsquo;s ability with each weapon (ex: 35% of the shots will hit).\nhits_to_kill means how many hits are necessary to kill, this is more related to the weapon power/efficiency (ex: 91% of the hits will kills).\nrodrigo_efficiency \u0026lt;- rodrigo_stats %\u0026gt;% filter( name_match %in% c(\u0026#34;ak47\u0026#34;, \u0026#34;aug\u0026#34;, \u0026#34;awp\u0026#34;, \u0026#34;fiveseven\u0026#34;, \u0026#34;hkp2000\u0026#34;, \u0026#34;m4a1\u0026#34;, \u0026#34;mp7\u0026#34;, \u0026#34;p90\u0026#34;, \u0026#34;sg556\u0026#34;, \u0026#34;xm1014\u0026#34;) ) %\u0026gt;% mutate( stat_type = case_when( str_detect(name, \u0026#34;shots\u0026#34;) ~ \u0026#34;shots\u0026#34;, str_detect(name, \u0026#34;hits\u0026#34;) ~ \u0026#34;hits\u0026#34;, str_detect(name, \u0026#34;kills\u0026#34;) ~ \u0026#34;kills\u0026#34; ) ) %\u0026gt;% pivot_wider( names_from = stat_type, id_cols = name_match, values_from = value ) %\u0026gt;% mutate( kills_efficiency = kills/shots*100, hits_efficiency = hits/shots*100, hits_to_kill = kills/hits*100 ) kbl(rodrigo_efficiency) %\u0026gt;% kable_styling() name_match kills shots hits kills_efficiency hits_efficiency hits_to_kill fiveseven 1288 28187 5558 4.569482 19.71831 23.17380 xm1014 5611 205982 42541 2.724024 20.65278 13.18963 p90 3469 133273 20245 2.602928 15.19062 17.13510 awp 2051 6260 2235 32.763578 35.70288 91.76734 ak47 6969 154852 24823 4.500426 16.03014 28.07477 aug 2120 37949 8487 5.586445 22.36423 24.97938 hkp2000 1401 36975 6737 3.789047 18.22042 20.79561 sg556 1243 25091 4567 4.953968 18.20175 27.21699 mp7 1788 52657 10186 3.395560 19.34406 17.55350 m4a1 3526 81126 14687 4.346325 18.10394 24.00763 rodrigo_efficiency %\u0026gt;% top_n(n = 10, wt = kills) %\u0026gt;% ggplot(aes(x = name_match, size = shots)) + geom_point(aes(y = kills_efficiency, color = \u0026#34;Kills Efficiency\u0026#34;)) + geom_point(aes(y = hits_efficiency, color = \u0026#34;Hits Efficiency\u0026#34;)) + geom_point(aes(y = hits_to_kill, color = \u0026#34;Hits to Kill\u0026#34;)) + ggtitle(\u0026#34;WEAPON EFFICIENCY\u0026#34;) + ylab(\u0026#34;Efficiency (%)\u0026#34;) + xlab(\u0026#34;\u0026#34;) + labs(color = \u0026#34;Efficiency Type\u0026#34;, size = \u0026#34;Shots\u0026#34;) + theme_csgo( text = element_text(family = \u0026#34;quantico\u0026#34;), panel.grid.major.x = element_line(size = .1, color = \u0026#34;black\u0026#34;,linetype = 2) ) + scale_color_csgo() In conclusion, I would advise Rodrigo to use the **awp** in his next games, because this weapon presented the best efficiency in terms of **shots to kill**, **shots to hit**, and **hits to kill**. But we definitely need more shots with this weapon to see if this efficiency remains.. hahahaha ","permalink":"https://adsoncostanzifilho.github.io/blog/csgo-package/","summary":"\u003cscript src=\"https://adsoncostanzifilho.github.io/blog/csgo-package/index_files/kePrint/kePrint.js\"\u003e\u003c/script\u003e\n\u003clink href=\"https://adsoncostanzifilho.github.io/blog/csgo-package/index_files/lightable/lightable.css\" rel=\"stylesheet\" /\u003e\n\u003ch2 id=\"overview\"\u003eOverview\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eGitHub:\u003c/strong\u003e \u003ca href=\"https://github.com/adsoncostanzifilho/CSGo\"\u003eadsoncostanzifilho/CSGo\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eCSGo\u003c/strong\u003e package is an R client for accessing Steam\u0026rsquo;s REST API specifically for the Counter-Strike Global Offensive Game (CS Go) data. Check out the \u003ca href=\"https://developer.valvesoftware.com/wiki/Steam_Web_API\"\u003eSteam documentation website\u003c/a\u003e and the \u003ca href=\"https://adsoncostanzifilho.github.io/CSGo/\"\u003ePackage Page\u003c/a\u003e for more information.\u003c/p\u003e\n\u003ch2 id=\"installation\"\u003eInstallation\u003c/h2\u003e\n\u003cp\u003eTo get the current released version from \u003ca href=\"https://cran.r-project.org/web/packages/CSGo/index.html\"\u003eCRAN\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-r\" data-lang=\"r\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nf\"\u003einstall.packages\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;CSGo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTo get the current development version from \u003ca href=\"https://github.com/adsoncostanzifilho/CSGo\"\u003eGitHub\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-r\" data-lang=\"r\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# install.packages(\u0026#34;devtools\u0026#34;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003edevtools\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"nf\"\u003einstall_github\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;adsoncostanzifilho/CSGo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"example\"\u003eExample\u003c/h2\u003e\n\u003cp\u003eThe first step to use the \u003ccode\u003eCSGo\u003c/code\u003e package is to have your own credentials (API key) to pull the CSGo data from the Steam API. For more information about how to get your own API Key run in your R \u003ccode\u003evignette(\u0026quot;auth\u0026quot;, package = \u0026quot;CSGo\u0026quot;)\u003c/code\u003e, or click \u003ca href=\"https://cran.r-project.org/web/packages/CSGo/vignettes/auth.html\"\u003ehere\u003c/a\u003e.\u003c/p\u003e","title":"CSGo Package"},{"content":"Motivation If you are using a script more than 3 times it is time to create a function and if you are using a function in 3 different projects it is time to create a package. \u0026ldquo;I heard it from someone, but I don\u0026rsquo;t remember who..\u0026rdquo;\nRecently I experienced the whole flow to create a new R package with the help of amazing packages like devtools, usethis, pkgdown, and roxygen2. That is why I decided to write about it while I still remember all the necessary steps to make your local functions available for the R community (CRAN and Github).\nThe material I followed to guide me through this process was the R Packages Book by Hadley Wickham. Of course, there is MUCH MORE content in his book than the one presented here, but maybe this post can also help someone in some way.\nFunctions A package is nothing more than a bunch of functions together in the same place (sharing the same scope), so the main key to having a good package is also to have good functions.\nThis post will not cover the guidelines to create useful functions. For that I recommend you to take a look on the Functions section of the Advanced R Book.\nIn order to make the next steps easier for you to pack your functions, it is important to keep in mind two things:\nFirst, develop your functions the more generic as possible, and always include comments explaining the inputs, outputs and at least one example on how to use it.\nSecond, remember all the packages you used and if possible always use the package::function structure when using foreigners functions inside your own one.\nPS: Be careful with those packages we always use but usually we forget about because \u0026ldquo;they were always there\u0026rdquo;, such as stats and utils.\nThe base R is the only one that don`t need to be mentioned!\nNow that we have our functions in a good shape let`s move to the package development itself.\nHow to start The first thing to do is to install the packages that will make our life easier.\ninstall.packages(c(\u0026#34;devtools\u0026#34;, \u0026#34;usethis\u0026#34;, \u0026#34;pkgdown\u0026#34;, \u0026#34;roxygen2\u0026#34;)) If you also want to share your package on Github, now it is a good time to create a new Github repository with the name you want to call your package, for example \u0026lsquo;mypackage\u0026rsquo;. Clone this empty repository inside some folder you want.\nNow it should be possible to run the command devtools::create(\u0026quot;~/path/mypackage\u0026quot;)(give the path of the Github repository you just cloned). This line of code will create the folders and files structure we are going to follow from now on. As soon as you run it a new RStudio session in an R project structure will prompt and it will set you inside the \u0026ldquo;~/path/mypackage\u0026rdquo; folder. If everything went well you must be able to see a folder called \u0026ldquo;R\u0026rdquo;, and the \u0026ldquo;DESCRIPTION\u0026rdquo; and \u0026ldquo;NAMESPACE\u0026rdquo; files.\nR folder: The R folder will be the place where you should put your scripts (which contains your functions, the .R files). There isn\u0026rsquo;t a rule on how you should organize your scripts inside this folder, however I like to follow the one function per script rule. For me, having one function per script structure makes the process of debugging and documentation easier. But at the end it is up to you!\nDESCRIPTION: This file will expose some important information about your package. It is not that challenge to fill the main options inside this file, indeed the file has very good explanations on how to fill it correctly. Also we have functions like usethis::use_package(\u0026quot;packagename\u0026quot;) to help us on how to fill the other sections of this file. We will talk more about it later.\nNAMESPACE: This file brings all the functions the user of your package will be able to use (all those functions defined with a @export. We also will cover more about it later). You should not edit this file, instead, you can run devtools::document() to update it.\nFunction Documentation Now it is time to document your functions. This step is really important to make your package useful for the R community and to help the proper usage of each one of your functions. To do that we are going to use the roxygen2 package.\nThanks to roxygen2 package the documentation process is more simple than ever. If you are on RStudio you can simple open the script which contains your function, position the cursor in the begin of your function and go to the Code menu \u0026gt; Insert Roxygen Skeleton or ctrl+shift+alt+R. If everything went well you should see an output like this:\n#\u0026#39; Title #\u0026#39; #\u0026#39; @param a #\u0026#39; @param b #\u0026#39; #\u0026#39; @return #\u0026#39; @export #\u0026#39; #\u0026#39; @examples myfunction \u0026lt;- function(a,b) { return(a+b) } Now it is only a matter of fill the presented options with clear explanations regarding the use of the function and parameters. In addition, you must provide at least one example of how to use it and explain what the user should expect in return.\nSometimes the example we provided will only work in very specific conditions. For these cases you should create your examples inside the \\dontrun{}, it will prevent the execution of it while compile and check your package.\nNote that the default skeleton roxigen2 provides us considers the #' @export. It only means that this function will be exposed to the end user, in other words the user should be able to run mypackage::myfunction(). If for some reason you don\u0026rsquo;t want to export this function you can only remove this line from your script.\nFunctions defined without the #' @export will work internally with no problems, but the end user will be able to access it only with the ::: structure, like mypackage:::myfunction().\nAt the end of this process your function script should be something like this:\n#\u0026#39; My Function #\u0026#39; #\u0026#39; This function provides the sum of two values (the worst example ever, I know!). #\u0026#39; #\u0026#39; @param a the first numeric value #\u0026#39; @param b the second numeric value #\u0026#39; #\u0026#39; @return a numeric value with the sum of a + b #\u0026#39; @export #\u0026#39; #\u0026#39; @examples #\u0026#39; \\dontrun{ #\u0026#39; ## the parameters must be numeric #\u0026#39; #\u0026#39; myfunction(a = 1, b = 1) #\u0026#39; } myfunction \u0026lt;- function(a,b) { return(a+b) } Once you have your function documented you should run devtools::document() this will create/update the folder called \u0026ldquo;man\u0026rdquo;. This folder will store all your functions documentations. Don\u0026rsquo;t forget to run devtools::document() every time you update your functions descriptions!\nYou can also run devtools::load_all() to load your package in your current R session, than you should be able to see how your documentation looks like by running help('mypackage::myfunction') or ?mypackage::myfunction.\nForeigner Packages It is very unlikely that you will create your functions without using ANY dependencies (foreigner packages), and that is not a problem at all. However you must provide this information for the end user in some way, otherwise, the users will not be able to run your codes as expected.\nThe right place for this information is inside the DESCRIPTION file in the \u0026ldquo;Imports\u0026rdquo; section. It is possible to fill this by hand by opening the DESCRIPTION file and including all the packages you used in your functions (separated by \u0026ldquo;,\u0026rdquo;) OR you can use the function usethis::use_package(\u0026quot;ggplot2\u0026quot;) and it will take care of filling it for you.\nThe use_package function also provides options like the minimum pakage version and the type of dependency.\nDO NOT USE library() OR require() IN YOUR R SCRIPTS!!!\nOne other possibility is to include just one function from a foreigner package. This is very common because sometimes we used only one function from a specific package and we don\u0026rsquo;t want to \u0026ldquo;import\u0026rdquo; the whole package but only that one function we are using. For that you can include @importFrom package_name function_name in the documentation of your function, this way you should be able to use the function without declare the package it came from. From now on it will be available like your own functions mypackage::function_name().\nLet\u0026rsquo;s say we want to include the beep() function from the beepr package, but we don\u0026rsquo;t want the whole beepr. The script should be something like this:\n#\u0026#39; My Function #\u0026#39; #\u0026#39; This function provides the sum of two values (the worst example ever, I know!). #\u0026#39; #\u0026#39; @param a the first numeric value #\u0026#39; @param b the second numeric value #\u0026#39; #\u0026#39; @return a numeric value with the sum of a + b #\u0026#39; @export #\u0026#39; #\u0026#39; @importFrom beepr beep #\u0026#39; #\u0026#39; @examples #\u0026#39; \\dontrun{ #\u0026#39; ## the parameters must be numeric #\u0026#39; #\u0026#39; myfunction(a = 1, b = 1) #\u0026#39; } myfunction \u0026lt;- function(a,b) { beep() return(a+b) } From now one the beep() function should be part of mypackage. If you run devtools::document() and devtools::load_all() you will see that mypackage::beep() is going to work.\nIt is also very common to use the %\u0026gt;% operator inside your functions. As we know the pipe operator is from the magrittr package but it is not necessary to import the whole magrittr package to only use the %\u0026gt;%. For this you can run the usethis::use_pipe() and that is it!\nIncluding Data What if my package uses external data? That other very common possibility and it is very easy to include external data sources in your package. Thanks again to the usethis package for provide us the use_data() function! So, to make your external data available inside your function environment you just need to run usethis::use_data(mydf), like this:\nmydf \u0026lt;- data.frame( x = rnorm(10,0,1), y = runif(10) ) usethis::use_data(mydf) From now on you should be able to use the \u0026ldquo;mydf\u0026rdquo; data frame inside your functions without problems.\nJust like functions data objects also must be documented, and the idea is almost the same as documenting your functions. First, open a new R script and save it inside the R folder with the name you want (my advise is to follow the name of your data). Then you can follow the structure presented bellow.\n#\u0026#39; Random values #\u0026#39; #\u0026#39; A completely useless data set. #\u0026#39; #\u0026#39; #\u0026#39; @format A data frame with 10 rows and 2 variables: #\u0026#39; \\describe{ #\u0026#39; \\item{x}{10 values from a normal distribution with mean = 0 and sd = 1} #\u0026#39; \\item{y}{10 values from a uniform distribution} #\u0026#39; ... #\u0026#39; } #\u0026#39; @source Created by the author. \u0026#34;mydf\u0026#34; Once you finish this process you can run devtools::document() and a new file named like your data will be created inside the \u0026ldquo;man\u0026rdquo; folder. To actually see the result of your documentation just run devtools::load_all() and then you should be able to run help(mypackage::mydf).\nNever @export a data set!\nCreating Vignettes The Vignettes are an important part of the package development process because it is the space for you to actually make a \u0026ldquo;walking through\u0026rdquo; your package capabilities. It is important to highlight that you can create as many vignettes as you like!\nStarting a new Vignette is really simple, you just need to run devtools::use_vignette(\u0026quot;intro\u0026quot;). It will create a new folder called \u0026ldquo;vignettes\u0026rdquo; and inside this folder, you can see a file named \u0026ldquo;intro.Rmd\u0026rdquo;. The \u0026ldquo;intro.Rmd\u0026rdquo; is at the end a standard Rmarkdown file, now you can create the content of it the way you like.\nIf you need some help with the rmarkdown package my advice is to take a look at the Rmarkdown Book!\nCreating README As the idea is also to make the package available on Github it is almost mandatory to have a good README section. Thinking on that (AGAIN) the usethis package has the usethis::use_readme_rmd() function to help us organize our README file. Now it is only a matter of opening the file created by the usethis::use_readme_rmd() following the structure and including whatever you want.\nRemember to Knit any time you changed something on the README file!\nIt is a good idea to take a look in other packages repositories on Github to get inspiration.\nTo include the badges you can use the usethis package (ex:usethis::use_badge(), usethis::use_cran_badge(), etc).\nCRAN Submission Now it is time to update your package on the main R repository the Comprehensive R Archive Network, CRAN. All the work we have done so far is essential to have your package accepted on CRAN repository.\nThe first thing to do is be in accordance with the CRAN Repository Policy. Here you will find the rules and guidelines to follow to have your package hosted by CRAN. The next step is to fill the web form.\nSpoiler Alert: The web form will request you to provide your package in a .tar.gz file, and also they will run some automatic routines to verify if your package is in a good shape to be review by someone on CRAN. Before we \u0026ldquo;build\u0026rdquo; your package in a .tar.gz format let\u0026rsquo;s take a look if our package will pass the CRAN\u0026rsquo;s automatic tests. To simulate the CRAN\u0026rsquo;s check procedure you can run the devtools::check(), it should provide you a good idea if your package is ready to be hosted by CRAN.\nNow that you have a package with 0 errors 0 warnings and 0 notes it is time to actually build the package in the .tar.gz. The simple way to do that is by running the devtools::build() and that\u0026rsquo;s it! Your package now is ready to be submitted on CRAN! Follow the steps presented on the web form, and be aware of your email (all the communications about your package status will be over email).\nFor the next version of your pacakge you can use the devtools::release()!\npkgdown Now that our package is available on Github and on CRAN we can easily create its own page, like a pro! Thanks to pkgdown it is very simple to make a very beautiful page to spreading your package for the whole R community.\nI will not gona cover the whole functionality of pkgdown for that you can see the pkgdown page!\nSince we already have the package structure the only thing to do to create your packages\u0026rsquo; page is:\n# Run to configure package to use pkgdown (once) usethis::use_pkgdown() # Run to build the website (every time you change it) pkgdown::build_site() I told you that this is the easier part! Now let\u0026rsquo;s host the page on Github Pages!\nTo do that you should enter your package Github repository and go to Settings \u0026gt; GitHub Pages:\nNow you only need to change the Source where will be the page structure (for me it is in the master branch and inside the docs folder).\nThe pkgdown by default will create the docs folder for you when you run pkgdown::build_site()!\nDone! Just add, commit, push and your package\u0026rsquo;s page will be online at: your_github_user.github.io/repository_name.\nThat is all I hope someone finds this tutorial useful. As always your feedback is much appreciated, feel free to get in touch with me over social media! 😄\n","permalink":"https://adsoncostanzifilho.github.io/blog/package-development-tutorial/","summary":"\u003ch2 id=\"motivation\"\u003eMotivation\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIf you are using a script more than 3 times it is time to create a function and if you are using a function in 3 different projects it is time to create a package. \u0026ldquo;\u003cem\u003eI heard it from someone, but I don\u0026rsquo;t remember who..\u003c/em\u003e\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eRecently I experienced the whole flow to create a new R package with the help of amazing packages like \u003ccode\u003edevtools\u003c/code\u003e, \u003ccode\u003eusethis\u003c/code\u003e, \u003ccode\u003epkgdown\u003c/code\u003e, and \u003ccode\u003eroxygen2\u003c/code\u003e. That is why I decided to write about it while I still remember all the necessary steps to make your local functions available for the R community (CRAN and Github).\u003c/p\u003e","title":"Package Development Tutorial"},{"content":"Motivation I had the idea of writing some \u0026ldquo;walking through\u0026rdquo; about blogdown, first because it was my first time using the package and I still have all the necessary steps fresh in my mind and second because probably I will need to have it all documented if I decided to refresh this blog one day. Of course, there are a lot of great tutorials about blogdown over the internet (the blogdown book for example), but maybe someone could find this one easier in some way\u0026hellip;\nThis post is divided into 3 sections: How to start, How to customize and use, How to deploy. In the first section, you will find some hints on how to start the development of your own page using RStudio and blogdown, the second section is about the functionalities blogdown has to make our life easier and, the last one is the necessary steps to deploy your page.\nHow to start The very first thing to do is install.packages(\u0026quot;blogdown\u0026quot;) to install the blogdown package. Once it is done you will need to install Hugo blogdown::install_hugo(force = TRUE) which is the static site generator blogdown uses (the force =TRUE parameter will update the Hugo version you may have installed).\nNow that everything is installed we can start the development of our page. There are two ways to start: using the RStudio Addins or by command lines in the console, let\u0026rsquo;s try do it in both!\nTo start a new blogdown project over RStudio is very easy, you just need to jump in the menu File \u0026gt; New Project \u0026gt; New Directory and click in Website using blogdown option.\nIn the second screen you will need to choose a name for the project folder, the sub-directory of the project and the Hugo template (here is the fun part). Hugo has A LOT of templates available here, I strongly recommend you to try some of them and choose that one which best fits your expectations.\nAfter choose the hugo template you just need to click in the \u0026ldquo;Download\u0026rdquo; button and you will be redirected to the template repository on Github.\nNow you just need to fill the repository in the Hugo theme option and click in Create Project.\nIf you prefer to use the console (old school style) you just need to execute the blogdown::new_site(theme = \u0026quot;devcows/hugo-universal-theme\u0026quot;) function and fill the theme parameter.\nThis page was developed using the Universal Theme\nHow to customize and use If everything went well, RStudio should show you a preview of your site in the Viewer tab, and it should open a config.toml script. Inside your project folder blogdwon will create A LOT of folders, we will jump on that later.\nThe config.toml script gives you the option to customize your site without change anything in the CSS, HTML, or JavaScript (of course, if you want to deeply change your site you must have some knowledge in CSS at least). In this file you will find options to change the name of your site, images, some colors, etc. I encourage you to modify those options and see the results, once you save the file the Viewer tab will refresh your site automatically, so you will be able to see your changes.\nAlmost all templates have a README file with some explanations about the functionalities the template has, it will help you to use the theme properly (you can find it inside the themes folder).\nThe folders 😖 I know this folder structure can be very confusing at first, that is one of the reasons I decided to create this post (because I don\u0026rsquo;t know if I will remember all of it in the next week).\ncontent folder The content folder is where all your posts and tabs must be stored, every time you write a new post this folder will be updated with the content of your post. We will talk more about the new posts later.\nstatic folder The static folder is where you will update all the images you want to use in your page. You should replace the existing images presented in this folder with your own images.\nSometimes, it is necessary to clean the cache of your browser to see the new image you just changed, and restart your R over the RStudio menu Session \u0026gt; Restart R to see it in the Viewer tab.\nthemes folder The themes folder is the main folder of your template, here you can find the README file, CSS, JS, HTML, and you may find for some themes an Example folder. This is the place you should go if you want to change some structures of your page.\nNew posts You probably want to create new posts on your page without pain. With that in mind, Yihui Xie, the responsible for the blogdown package, creates the function blogdown::new_post() (or over the RStudio Addins \u0026gt; New Post).\nBefore we start using it, there is another thing we can do to make this \u0026ldquo;new post\u0026rdquo; creation process even easier. Let\u0026rsquo;s change some Global options! To do that we need to modify and save the .Rprofile file, this is a script that is executed every time your R session is started. Here is the command to open this script: file.edit('.Rprofile'). Now we can set some default options for our new posts (take a look at here to see the other possible options).\n# default extension and default author options(blogdown.ext = \u0026#39;.Rmd\u0026#39;, blogdown.author = \u0026#39;Your Name\u0026#39;) In my case I choosed the .Rmd extention because I am more confortable writing using it, but you can, for example, choose .md, if you prefere. Now that we have everything configured the way we want, let\u0026rsquo;s start to write the post part😰. Once you start a New Post a standard .Rmd file will be created, now it is just about writing your content!\nIt is not necessary to Knit the file, the blogdown will render the post automatically when you save the file, and you can follow the updates in the Viewer tab on RStudio.\nHow to deploy Now that everything is done on our page, it is time to deploy it. I will show how to do that using the Github Pages, but of course there are many other options (I just think this is the easier one..). To deploy our page we just need this 6 steps:\nCreate a Github account\nCreate a new repository\nThe name of your repository MUST BE your Github username + .github.io (USERNAME.github.io)\nClone this repository INSIDE your project folder\nExecute the function blogdown::build_site()\nBefore execute this function you should change the publishDir option inside the config.toml to the folder USERNAME.github.io (which is your Github repository).\npublishDir = \u0026#34;USERNAME.github.io\u0026#34; PS: If your config.toml doesn\u0026rsquo;t have this option you can create it by yourself.\nPush the changes to your Github Repository On the Terminal tab go inside the USERNAME.github.io folder using cd. Once inside that folder you just need to: git add, git commit -m \u0026quot;first deploy my blog\u0026quot;, git push.\nYour page will be online on USERNAME.github.io That is all The blogdown package has MUCH MORE features than those presented in this post. To learn more about it I recommend you to read the blogdown book.\nI hope someone finds this tutorial useful. As always your feedback is much appreciated, feel free to get in touch with me over social media! 😄\n","permalink":"https://adsoncostanzifilho.github.io/blog/blogdown-tutorial/","summary":"\u003ch2 id=\"motivation\"\u003eMotivation\u003c/h2\u003e\n\u003cp\u003eI had the idea of writing some \u0026ldquo;walking through\u0026rdquo; about blogdown, first because it was my first time using the package and I still have all the necessary steps fresh in my mind and second because probably I will need to have it all documented if I decided to refresh this blog one day. Of course, there are a lot of great tutorials about blogdown over the internet (the \u003ca href=\"https://bookdown.org/yihui/blogdown/\"\u003eblogdown book\u003c/a\u003e for example), but maybe someone could find this one easier in some way\u0026hellip;\u003c/p\u003e","title":"Blogdown Tutorial"},{"content":"Overview GitHub: adsoncostanzifilho/TextMining\nText Mining Tool is an interface developed in R using mainly the shiny, tidytext and rtweet packages. The idea of this interface is to allow to you make your own text analysis using live Twitter data.\nThe tool is online on shinyapps\u0026rsquo; repository at the address https://adsoncostanzi.shinyapps.io/TextMining/.\nHow does this interface work? The interface is divided into 5 tabs presented in the menu on the left: Home , Search , Word Cloud , Sentiment Analysis and, Topic Modeling .\nThe first thing you need to do to use the entire page is to collect some data from Twitter. To do that you just need to jump into the Search tab and follow the steps presented there!\nOnce you have finished the \u0026ldquo;data collection\u0026rdquo; step on the Search tab, you will be able to use the other tabs available on the left menu.\nPS: You will find over the interface some ? signs, once you click in one of those a pop-up with explanations will open to guide you on how to use that option properly.\n","permalink":"https://adsoncostanzifilho.github.io/blog/text-mining-tool/","summary":"\u003ch2 id=\"overview\"\u003eOverview\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eGitHub:\u003c/strong\u003e \u003ca href=\"https://github.com/adsoncostanzifilho/TextMining\"\u003eadsoncostanzifilho/TextMining\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eText Mining Tool\u003c/strong\u003e is an interface developed in R using mainly the shiny, tidytext and rtweet packages. The idea of this interface is to allow to you make your own text analysis using live Twitter data.\u003c/p\u003e\n\u003cp\u003eThe tool is online on shinyapps\u0026rsquo; repository at the address \u003ca href=\"https://adsoncostanzi.shinyapps.io/TextMining/\"\u003ehttps://adsoncostanzi.shinyapps.io/TextMining/\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"how-does-this-interface-work\"\u003eHow does this interface work?\u003c/h2\u003e\n\u003cp\u003eThe interface is divided into 5 tabs presented in the menu on the left: Home , Search , Word Cloud , Sentiment Analysis and, Topic Modeling .\u003c/p\u003e","title":"Text Mining Tool"},{"content":"Overview GitHub: adsoncostanzifilho/soothsayeR\nSoothsayeR is an interface based on the old prank called ‘Peter answers’..\nThe game’s idea is to play with your friends making questions that you know the answer, and make them believe that R is who is answering…\nThe app demonstrates how easy it is to integrate Shiny with Javascript through the shinyjs library.\nThe tool is online on shinyapps\u0026rsquo; repository at the address https://adsoncostanzi.shinyapps.io/soothsayeR/.\nHow to play with soothsayeR? You just need to press dot (.) on the keyboard in the request session and then write the answer secretly. When you press dot in the request text input everything you type will be masked, so you could put the answer without anyone noticing.\nThen, when you have finished typing the answer you just need to press dot again and complete the request phrase anyway you want.\nExample You tell a friend next to you that R can answer any question. To prove it you say you’re going to ask R the color of the shirt he’s wearing.\nIn the request session you will write \u0026lsquo;.red.ase answer\u0026rsquo;, but, only \u0026lsquo;R please answer\u0026rsquo; will be shown on the screen. In the next step you will write the following question: \u0026lsquo;What is the color of the t-shirt of the person next to me?\u0026rsquo;.\nThat done, just press \u0026lsquo;Guess\u0026rsquo; button and the answer red will appear!\n","permalink":"https://adsoncostanzifilho.github.io/blog/soothsayer/","summary":"\u003ch2 id=\"overview\"\u003eOverview\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eGitHub:\u003c/strong\u003e \u003ca href=\"https://github.com/adsoncostanzifilho/soothsayeR\"\u003eadsoncostanzifilho/soothsayeR\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSoothsayeR\u003c/strong\u003e is an interface based on the old prank called ‘Peter answers’..\u003c/p\u003e\n\u003cp\u003eThe game’s idea is to play with your friends making questions that you know the answer, and make them believe that R is who is answering…\u003c/p\u003e\n\u003cp\u003eThe app demonstrates how easy it is to integrate \u003cstrong\u003eShiny\u003c/strong\u003e with \u003cstrong\u003eJavascript\u003c/strong\u003e through the \u003cstrong\u003eshinyjs\u003c/strong\u003e library.\u003c/p\u003e\n\u003cp\u003eThe tool is online on shinyapps\u0026rsquo; repository at the address \u003ca href=\"https://adsoncostanzi.shinyapps.io/soothsayeR/\"\u003ehttps://adsoncostanzi.shinyapps.io/soothsayeR/\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"how-to-play-with-soothsayer\"\u003eHow to play with soothsayeR?\u003c/h2\u003e\n\u003cp\u003eYou just need to press dot (.) on the keyboard in the request session and then write the answer secretly. When you press dot in the request text input everything you type will be masked, so you could put the answer without anyone noticing.\u003c/p\u003e","title":"soothsayeR"},{"content":"Adson Costanzi Filho Data Scientist at Laboratoria I am a statistician graduated from the Federal University of Rio Grande do Sul (UFRGS), Brazil, with about 7 years of experience working in data science environments. My work focuses mainly on model development, text mining, sentiment analysis, data visualization, and report creation.\nI am currently a Data Scientist at Laboratoria, where I am responsible for the data pipeline management, leveraging automation to streamline management reports and dashboard generation. My role revolves around designing experiments and implementing statistical models and machine learning algorithms to enhance the student experience and drive business improvement initiatives. I work daily with R, Python, SQL, Docker and Google Cloud.\nI am an active member of the R community and the developer/maintainer of CSGo, an R package hosted on CRAN that pulls data from Steam\u0026rsquo;s API for Counter-Strike: Global Offensive. You can find more projects I am involved in on my GitHub.\nExperience Data Scientist — Laboratoria, Remote (Oct 2021 – present) Senior Data Scientist — Evalueserve, Viña del Mar, Chile (Jan 2021 – Oct 2021) Data Scientist — Evalueserve, Viña del Mar, Chile (Sep 2019 – Jan 2021) Credit Modeling Specialist — Renner S.A., Porto Alegre, Brazil (Jun 2019 – Aug 2019) Data Scientist Analyst II — Agibank, Porto Alegre, Brazil (Dec 2018 – Jun 2019) Data Scientist Analyst I — Agibank, Porto Alegre, Brazil (Jul 2018 – Dec 2018) Fraud Prevention Analyst — Agibank, Porto Alegre, Brazil (Aug 2017 – Jul 2018) Data Scientist Assistant — British American Tobacco, Porto Alegre, Brazil (Aug 2016 – Aug 2017) Data Scientist Intern — British American Tobacco, Porto Alegre, Brazil (Nov 2015 – Aug 2016) Education B.Sc. in Statistics — Federal University of Rio Grande do Sul (UFRGS), Porto Alegre, Brazil (2012 – 2017) Exchange program in Statistics — Universidad de Valladolid, Valladolid, Spain (2014 – 2015) Technical skills R · Python · SQL · Git · CSS · SAS · Office · VBA · JavaScript (beginner)\nLanguages Portuguese (native) · English (advanced) · Spanish (advanced)\nContact Feel free to reach out at adsoncostanzi32@gmail.com or through my social links. You can also download my full CV (PDF).\n","permalink":"https://adsoncostanzifilho.github.io/about/","summary":"\u003ch2 id=\"adson-costanzi-filho\"\u003eAdson Costanzi Filho\u003c/h2\u003e\n\u003ch4 id=\"data-scientist-at-laboratoria\"\u003eData Scientist at \u003ca href=\"https://www.laboratoria.la/\"\u003eLaboratoria\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003eI am a statistician graduated from the Federal University of Rio Grande do Sul (UFRGS), Brazil, with about 7 years of experience working in data science environments. My work focuses mainly on \u003cstrong\u003emodel development\u003c/strong\u003e, \u003cstrong\u003etext mining\u003c/strong\u003e, \u003cstrong\u003esentiment analysis\u003c/strong\u003e, \u003cstrong\u003edata visualization\u003c/strong\u003e, and \u003cstrong\u003ereport creation\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eI am currently a Data Scientist at \u003ca href=\"https://www.laboratoria.la/\"\u003eLaboratoria\u003c/a\u003e, where I am responsible for the data pipeline management, leveraging automation to streamline management reports and dashboard generation. My role revolves around designing experiments and implementing statistical models and machine learning algorithms to enhance the student experience and drive business improvement initiatives. I work daily with \u003cstrong\u003eR\u003c/strong\u003e, \u003cstrong\u003ePython\u003c/strong\u003e, \u003cstrong\u003eSQL\u003c/strong\u003e, \u003cstrong\u003eDocker\u003c/strong\u003e and \u003cstrong\u003eGoogle Cloud\u003c/strong\u003e.\u003c/p\u003e","title":"About"}]