Doing Macros in R


#1

I'm fairly familiar with SAS and know how to use macros to simplify repetitive tasks. However, I'm new to R and don't know how I can do that.

here's the code I got:

psd.coffee <- read.csv (unzip ("C:\Users\me\Desktop\FAS (PSD)\psd_coffee_csv.zip", exdir = "C:\Users\me\Desktop\FAS (PSD)"))

As you can see, the code extracts as well as reads the csv file that's within the zipped file. now I have a bunch of zipped files (e.g. psd_grain_csv.zip, psd_fruits_csv.zip, and so on).

I want to be able to create a new data set for ever zip file based off of the commodity without having to write the entire code all over again. Again, this would be a pretty simple task in SAS, but have no clue how to do it in R. Any help is much appreciated.


#2

Macros in SAS are fairly analogous to functions in R

So in your example, one way to do that would be:

psd.func <- function(file){
    read.csv(unzip(paste0("C:/Users/me/Desktop/FAS (PSD)/",file,"_csv.zip"),exdir="C:/Users/me/Desktop/FAS (PSD)"))
}

psd.coffee <- psd.func(file="psd_coffee")

Something to that effect. Definitely double check my code but that's the gist.

EDIT: Updated so that the properly named object is created in the code.
EDIT2: In my previous correction I messed up the function param definition (type of "filet" instead of "file"). Also, for more efficient ways definitely look at @nwerth 's comment


#3

If they're all in the same directory, you can further reduce repetition.

psd_files <- list.files(
  "C:/users/me/desktop/FAS (PSD)",
   pattern = "^psd_.*zip$",
  full.names = TRUE
)
datasets <- lapply(psd_files, FUN = psd.func)
datasets[[1]]
# <Printed version of the first data.frame>

Or, you could use loops to write the code for you.

psd_names <- gsub("_csv.zip", "", basename(psd_files))
code_lines <- paste0(psd_names, " <- psd.func(file = '", psd_names, "')")
cat(code_lines, sep = "\n")
# psd_coffee <- psd.func(file = 'psd_coffee')
# psd_grain <- psd.func(file = 'psd_grain')
# psd_fruits <- psd.func(file = 'psd_fruits')

Final tip: if you don't want to keep the extracted files, try using unz() to read directly from the zip file:

psd.func <- function(filet){
  zip_path <- paste0("C:/Users/me/Desktop/FAS (PSD)/", file, "_csv.zip")
  csv_name <- gsub("_csv.zip", ".csv", basename(zip_path))
  zip_con <- unz(zip_path, csv_name)
  on.exit(close(zip_con))
  read.csv(zip_con)
}

#4

So, in other words, you want to program.


What I frequently notice here is that people that come to R from a no-code background (SAS, SPSS, Excel, Tableau, you name it, any GUI that works with data) see R as their next SAS/SPSS/Excel/Tableau. What escapes many is that R is based on a different concept, which is programming.

What you want from SAS in R is all that R is. Macros in SAS or Excel are essentially pieces of code with a sequence of steps. Well, that is the main concept of any programming language, including R.

My answer may seem to be impractical for this specific problem, but I believe that the frame of reference matters. Understanding how the tool works may help its users use it better.


#5

Thank you all for the feedback and help. I will try to codes suggested by Nathan and Sean. Hopefully that'll help me out.

Thank you again.


#6

To be fair to OP, SAS is a programming language.

While there is a point and click interface that could be used, I would assume that OP is coming from the programming side of things with their mention of macros. Macros in SAS function similarly to R's functions in that you can take bits of code, define parameters and make reusable chunks.


#7

Most people might not have this problem, but it took me a while to overcome a mental block: SAS macros are for code generation, R functions are for encapsulating processing. And these are fundamentally two different things.

Yes, SAS macros can take parameters. Yes, they can do processing on macro variables inside themselves. But, at the end of the day, they just write code to be compiled and run. (SAS does let macros be run during other processing with special CALLs, but that just makes the macro system more complex. Use PROC FCMP to create functions.)

By comparison, R functions actually do processing, just like a plain top-level R statement. It's possible to generate code in R, but this is rarely needed because of functions. There's almost always a simpler way than code generation in R.

To compare apples to apples:

Language Functions Code generation
R function() expression(), parse()
SAS PROC FCMP %MACRO

#8

Indeed SAS macros are essentially a way to copy and paste code programmatically, there are no variable types and no value returned, instead of vectors you typically use "space separated lists" or even worse numbered variables built by horrible loops. @mustafghan I promise you that once you get a grip of R you will not want to touch SAS again.


#9

That's a great point. I was comparing them more on the surface that they look and seem to behave similarly in that they make it easier to run the same code over again, however you are absolutely right. The SAS macro system literally processes the provided code chunk, replaces parameters with user specification and just runs it as if you had that chunk/chunks of code in there all along rather than encapsulating.