Skip to Content
Author's profile photo Former Member

Analytics with SAP and R

Something that piqued my curiosity lately was the developments with SAP HANA and R (good overview here).  This is definitely a new and exciting direction for SAP, with creating a well structured, and organised ‘Big Table’ option for in memory computing, and then going the extra mile to embed a specialised Open Source Statistical Computing package (R) in it – making the fore front of the world of statistical analysis open to those that dare.

This is utterly brilliant, but the problem is that I can’t access it as I don’t have access to a SAP HANA instance (nor would most people).  It is also heavily geared to ‘Big Data’, when there is still an awful lot to be gained from small, and mid-range data analysis arenas (resisting the temptation about size and clichés).

This has definitely touched on my hackers itch, and in response to this I’ve created one more Scripting Language Connector for R – RSAP.

The idea of this is to enable RFC calls (using the SAP NW RFC SDK) where any table contents are returned as data.frames (in R parlance).

Once you have this data in R, then the world is your oyster – it is up to your imagination as to what you do with it.  To give an overview of how it works, and what you can do, I’m going to step through the process of installing and using RSAP.

Obtaining and Installing

Firstly you need to install R.  I recommend using RStudio as it is a comfortable graphical user interface – you can get it from here.  

Under debian (read Ubuntu) flavoured Linux you can install R first before downloading/installing RStudio using:

sudo apt-get install r-base-core r-base-dev r-base-html r-recommended


The SDK is available from the SAP Service Market Place SWDC – this is a forum discussion on getting it

If you have (like me) installed the NPL SAP Test Drive instance, then the SAP NW RFC libs exist in the /usr/sap/NPL/SYS/exe/run directory, the only problem being that it does not contain the C header files (really – SAP should make this available on SDN).


Download or clone the RSAP project source from


Ensure that the R library prerequisites are installed.  To do this there is a helper script in the RSAP source code directory.  cd to the source directory (downloaded above) – in my case /home/piers/git/public/RSAP – and run the following:

R –no-save < install_dependencies.R

This will prompt to install the packages yaml, reshape, plotrix, and RUnit.

To build and install the RSAP package, cd to the source directory (downloaded above) – in my case /home/piers/git/public/RSAP – run the following:

R CMD INSTALL –build –preclean –clean –configure-args=’–with-nwrfcsdk-include=/home/piers/code/sap/nwrfcsdk/include –with-nwrfcsdk-lib=/home/piers/code/sap/nwrfcsdk/lib’ .

You must change the values for –with-nwrfcsdk-include and –with-nwrfcsdk-lib to point to the directory locations that you have downloaded the SAP NW RFC SDK to.

Under Linux, it is also likely that you need to add the lib directory to the LD cache or set the LD_LIBRARY_PATH variable.

Setting the LD Cache:

as root, edit /etc/ and add the lib path from above to it on it’s own line.  Now regenrate the cache by executiong ‘sudo ldconfig’.


You must ensure that the following environment variable is set in all your shells:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/nwrfcsdk/lib

The easiest way to do this is to add the above line to your $HOME/.bashrc file so that it happens automatically for all future shells.

Does it work?

Once the build and install of the RSAP package is complete, now you should test to make sure it’s all working.

Change to the package source code directory (you are probably still there from the above activities), and launch either R or RStudio.

From the R command line try the following:

> library(RSAP)

Loading required package: yaml


You should get the above confirmation message that the dependent yaml package has been loaded.  Now we are ready to try some R wizardry.

How to work with RSAP

Lets work through the general process steps for interacting with SAP.

Connecting to SAP

Using RSAP we need to establish a connection to SAP.  For this you need an account that has the appropriate access for RFC calls, and functionality access.  Connections can be built in two ways – directly passing connection parameters:

>     conn <- RSAPConnect(ashost=”nplhost”, sysnr=”42″,

                          client=”001″, user=”developer”,

                          passwd=”developer”, lang=”EN”)


Or using a YAML encoded file that contains the connection details:

> conn <- RSAPConnect(“sap.yml”)


The sap.yml file is structured like:

ashost: nplhost

sysnr: “42”

client: “001”

user: developer

passwd: developer

lang: EN

trace: 1

The above activates the trace functionality in NW RFC SDK.  This will create trace files in the current working directory, and are invaluable for debugging connectivity problems.

Calling SAP

Now we have the connection object, we can get connection info with it:

info <- RSAPGetInfo(conn)

Query the system with:

res <- RSAPInvoke(conn, “<RFC Function Name”, parms)

Or close the connection:


RSAPInvoke() is what we are most interested in, and we need to pass the parameters as a series of nested named lists.  The classic example is RFC_READ_TABLE:

parms <- list(‘DELIMITER’ = ‘|’,

              ‘FIELDS’ = list(FIELDNAME = list(‘CARRID’, ‘CONNID’, ‘PRICE’,

                                               ‘SEATSMAX’, ‘SEATSOCC’)),

              ‘OPTIONS’ = list(TEXT = list(“CARRID = ‘AA’ “, ” AND CONNID = 0017 “)),

              ‘QUERY_TABLE’ = ‘SFLIGHTS2’)

res <- RSAPInvoke(conn, “RFC_READ_TABLE”, parms)

The names must correspond directly to the parameter and structure (for tables) names, and use numeric and character types as appropriate.

The other thing that is really important to get your head around is that R data structures are column oriented, which means we have to think differently about tables that we get from SAP.  Tables in SAP translate to lists of vectors where the outer list is a list of column names (a slightly loose analogy but it will do) and the vectors hang off these column names corresponding to all the values in that column down the rows.

Working through the examples in get_flights.R

In the source code package there is an example script – get_flights.R.  It uses the standard demonstration data for the Flight Data system contained in table SFLIGHT2.  Let’s look at what this does.

Load libraries:

> library(RSAP)

Loading required package: yaml

> library(reshape)

Loading required package: plyr

  Attaching package: ‘reshape’

  The following object(s) are masked from ‘package:plyr’:

      rename, round_any

> library(plotrix)


We now have all the necessary libraries for the rest of the examples.

conn <- RSAPConnect(“sap.yml”)

parms <- list(‘DELIMITER’ = ‘;’,

              ‘QUERY_TABLE’ = ‘SFLIGHTS2’)

res <- RSAPInvoke(conn, “RFC_READ_TABLE”, parms)


sflight = res$DATA

flds <- sub(“\\s+$”, “”, res$FIELDS$FIELDNAME)

sflight <- data.frame(sflight, colsplit(sflight$WA, split = “;”, names = flds))

This connects to SAP, calls RFC_READ_TABLE to get the contents of SFLIGHT2, and sets the column delimiter for that table as ‘;’.  We close the connection and copy the table data from the return parameter res$DATA (see RFC_READ_TABLE in transaction SE37) into sflight.  We also grab the field names returned in table FIELDS, and remove the whitespace at the end.  Next – this is where the importance of the ‘;’ delimiter is – using the colsplit() function from the reshape package, we split return DATA into columns named by the FIELDS that RFC_READ_TABLE provided us.

Now we have a data.frame that looks a lot like the table SFLIGHT2 when viewed in transaction SE16.

sflight <- cbind(sflight, FLIGHTNO = paste(sub(“\\s+$”, “”,

                                           sflight$CARRID),sflight$CONNID, sep=””))

sflight$SEGMENT <- paste(sflight$AIRPFROM, sflight$AIRPTO, sep=” – “)

sflight$CARRNAME <- sub(“\\s+$”, “”, sflight$CARRNAME)

sflight$DISTANCE <- as.numeric(lapply(sflight$DISTANCE,

                                      FUN=function (x) {sub(“\\*”,””, x)}))

sflight$DISTANCE <- as.numeric(lapply(sflight$DISTANCE,

                                      FUN=function (x) {if (x == 0) NA else x}))

sflight[sflight$CARRNAME == ‘Qantas Airways’,’DISTANCE’] <- 10258

This next chunk created  new vectors (columns) FLIGHTNO combined from CARRID and CONNID, SEGMENT from AIRPFROM and AIRPTO, and cleaned vectors CARRNAME, and DISTANCE.

Now create some aggregated views, to generate visualisations from:

airline_avgocc <- aggregate(data.frame(SEATSMAX=sflight$SEATSMAX,



                            by=list(carrname=sflight$CARRNAME), FUN=mean, na.rm=TRUE)

airline_sumocc <- aggregate(data.frame(SEATSOCC=sflight$SEATSOCC),

                            by=list(carrname=sflight$CARRNAME), FUN=sum, na.rm=TRUE)

Show a pie chart  – sum of airline occupancy as a share of market:


lbls <- paste(airline_sumocc$carrname, “\n”, sprintf(“%.2f%%”,         

        (airline_sumocc$SEATSOCC/sum(airline_sumocc$SEATSOCC))*100), sep=””)

pie3D(airline_sumocc$SEATSOCC, labels=lbls,


      main=”Occupancy sum share for Airlines”, explode=0.1)


Create a Stacked Bar Plot with Colors and Legend showing a summary of occupancy by segment and carrier – to do this we need to generate a summary (aggregate), and fill in the missing combinations of the grid, and then switch the orientation of rows for columns to present to the plotting funcitons:

d <- aggregate(SEATSOCC ~ CARRNAME:SEGMENT, data=sflight, FUN=sum, na.rm=FALSE)

d2 <- with(d, expand.grid(CARRNAME = unique(d$CARRNAME), SEGMENT = unique(d$SEGMENT)))

airline_sumsegocc <- merge(d, d2, all.y = TRUE)

airline_sumsegocc$SEATSOCC[$SEATSOCC)] <- 0

# switch orientation to segment * carrier

counts <- data.frame(unique(airline_sumsegocc$CARRNAME))

for (a in unique(airline_sumsegocc$SEGMENT)) 

    {counts <- cbind(counts,

     airline_sumsegocc$SEATSOCC[which(airline_sumsegocc$SEGMENT == a)]);}

counts[,1] <- NULL

colnames(counts) <- unique(airline_sumsegocc$SEGMENT);

rownames(counts) <- unique(airline_sumsegocc$CARRNAME);


barplot(as.matrix(counts), main=”Total Occupancy by Segment and Carrier”,

        ylab=”Number of Seats”,


        ylim=c(0, 15000), legend = rownames(counts))


Lastly – we create a simple performance indicator using a time series comparison of different airlines:

# performance by airline over time – dollars per customer KM

sflight$FLDATEYYMM <- substr(sflight$FLDATE, start=1, stop=6)

d <- aggregate(data.frame(PAYMENTSUM=sflight$PAYMENTSUM,



                          PERFORMANCE=(sflight$PAYMENTSUM/(sflight$SEATSOCC *




               FUN=sum, na.rm=TRUE)

d2 <- with(d, expand.grid(carrname = unique(d$carrname),

                          fldateyymm = unique(d$fldateyymm)))

agg_perf <- merge(d, d2, all.y = TRUE)

agg_perf <- agg_perf[order(agg_perf$carrname, agg_perf$fldateyymm),]


# create time series and plot comparison

perf_series <- data.frame(1:length(unique(agg_perf$fldateyymm)))

for (a in unique(agg_perf$carrname))

    {perf_series <- cbind(perf_series,

       agg_perf$PERFORMANCE[which(agg_perf$carrname == a)]);}

perf_series[,1] <- NULL

colnames(perf_series) <- unique(agg_perf$carrname);

# convert all to time series

for (a in length(unique(agg_perf$carrname)))

    {perf_series[[a]] <- ts(perf_series[,a], start=c(2011,5), frequency=12)}

# plot the first and line the rest


ts.plot(ts(perf_series, start=c(2011,5), frequency=12),

           gpars=list(main=”Performance: dollar per customer KM”,



                      col=rainbow(dim(perf_series)[2]), xy.labels=TRUE))

legend(2012.05, 3.2, legend=colnames(perf_series),

                     col=rainbow(dim(perf_series)[2]), lty=1, seg.len=1)


Hopefully, I’ve shown that there is a lot that can be done with R – especially in the area of adHoc advanced business intelligence and data analysis.  I have not really even scratched the surface in terms of what R can offer for advanced statistical analysis and modelling – that is where the true wizards live.

I would love to hear back from anyone who tries RSAP out – issues and user experiences alike.


I should note that Alvaro has been here before me with OData/JSON/and R –


Basic R Tutorials

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Nigel James
      Nigel James

      Awesome Piers.

      Thanks for creating this. I look forward to see what the community can create with this.



      Author's profile photo Alvaro Tejada Galindo
      Alvaro Tejada Galindo

      Piers! You just blow my mind off 😘 I'm just trying to get the SWDC and try to make the installation on Windows work 😉 This is just so awesome!



      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Great!  When you make that happen, we could create a little installation package for others to spread the word.


      Piers Harding.

      Author's profile photo Former Member
      Former Member

      great !!

      Author's profile photo Former Member
      Former Member

      @Piers Harding, does this work on Mac OS X? I am having hard time in downloading SAP NW RFCSDK. My credentials are not working for SAP Service Market Place and I do not have S number ID.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Hi Charlie.   I'm not sure that the SDK is available for OSX - that is the limiting factor.   Try Linux, perhaps.


      Piers Harding

      Author's profile photo Satish Vadlamani
      Satish Vadlamani


      I am trying to install RSAP on WIN7 64bit machine and having a really hard time. I am trying to follow the steps but it is having some issues. I installed devtools package and other dependencies like reshape and yaml. I also installed rtools.

      I am pasting below some of output of the install. I tried from Rstudio as will as the R interface that came with the 3.2.4 install.

      Can you help? Much appreciated in advance.

      Satish Vadlamani


      > install_github('RSAP', username='piersharding', args=c("--configure-args='--with-nwrfcsdk-include=/home/piers/code/sap/nwrfcsdk/include --with-nwrfcsdk-lib=/home/piers/code/sap/nwrfcsdk/lib' --no-clean-on-error"))

      Downloading GitHub repo piersharding/RSAP@master

      from URL

      Installing RSAP

      Installing 1 package: Rcpp

      package ‘Rcpp’ successfully unpacked and MD5 sums checked

      Warning: cannot remove prior installation of package ‘Rcpp’

      "C:/PROGRA~1/R/R-32~1.4/bin/i386/R" --no-site-file --no-environ --no-save --no-restore  \

        CMD INSTALL  \

        "C:/Users/Satish/AppData/Local/Temp/RtmpaQ9Oa0/devtools172034a22ec3/piersharding-RSAP-0a06486"  \

        --library="C:/Users/Satish/Documents/R/win-library/3.2" --install-tests  \

        --configure-args='--with-nwrfcsdk-include=/home/piers/code/sap/nwrfcsdk/include  \

        --with-nwrfcsdk-lib=/home/piers/code/sap/nwrfcsdk/lib' --no-clean-on-error

      Warning: unknown option '--with-nwrfcsdk-lib=/home/piers/code/sap/nwrfcsdk/lib''

      * installing *source* package 'RSAP' ...

      ** libs

      Warning: this package has a non-empty '' file,

      so building only the main architecture

      gcc -m32 -I"C:/PROGRA~1/R/R-32~1.4/include" -DNDEBUG -I. -I"C:/nwrfcsdk/include" -DSAPwithUNICODE -DUNICODE -D_UNICODE -D_AFXDLL -D_CRT_NON_CONFORMING_SWPRINTFS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DSAPonNT -DSAP_PLATFORM_MAKENAME=ntintel     -I"d:/RCompile/r-compiling/local/local323/include"     -O3 -Wall  -std=gnu99 -mtune=core2 -c RSAP.c -o RSAP.o

      In file included from RSAP.c:41:0:

      C:/nwrfcsdk/include/sapnwrfc.h:28:0: warning: ignoring #pragma warning  [-Wunknown-pragmas]

      RSAP.c: In function 'u8to16c':

      RSAP.c:133:12: warning: variable 'rc' set but not used [-Wunused-but-set-variable]

      RSAP.c: In function 'u8to16':

      RSAP.c:150:12: warning: variable 'rc' set but not used [-Wunused-but-set-variable]

      RSAP.c: In function 'u8to16r':

      RSAP.c:167:12: warning: variable 'rc' set but not used [-Wunused-but-set-variable]

      RSAP.c: In function 'u16to8c':

      RSAP.c:184:12: warning: variable 'rc' set but not used [-Wunused-but-set-variable]

      RSAP.c: In function 'u16to8':

      RSAP.c:208:12: warning: variable 'rc' set but not used [-Wunused-but-set-variable]

      RSAP.c: At top level:

      C:/nwrfcsdk/include/sapuc.h:853:24: warning: 'sccsidU16' defined but not used [-Wunused-variable]

      gcc -m32 -shared -s -static-libgcc -o RSAP.dll tmp.def RSAP.o -L. -LC:/nwrfcsdk/lib -lsapnwrfc -llibsapucum -Ld:/RCompile/r-compiling/local/local323/lib/i386 -Ld:/RCompile/r-compiling/local/local323/lib -LC:/PROGRA~1/R/R-32~1.4/bin/i386 -lR

      installing to C:/Users/Satish/Documents/R/win-library/3.2/RSAP/libs/i386

      ** R

      ** tests

      ** preparing package for lazy loading

      Error in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck = vI[[j]]) :

        there is no package called 'Rcpp'

      Error : package 'reshape' could not be loaded

      ERROR: lazy loading failed for package 'RSAP'

      Error: Command failed (1)

      In addition: Warning message:

      Username parameter is deprecated. Please use piersharding/RSAP


      > require("RSAP")

      Loading required package: RSAP

      Error in inDL(x, as.logical(local), as.logical(now), ...) :

        unable to load shared object 'C:/Users/Satish/Documents/R/win-library/3.2/RSAP/libs/i386/RSAP.dll':

        LoadLibrary failure:  The specified module could not be found.


      Author's profile photo Former Member
      Former Member

      Satish, I'm also having troubles when trying to install this for windows. Were you able to get anywhere with it?

      Author's profile photo Pavan Krishna Mulpur
      Pavan Krishna Mulpur

      Hi Piers,

      I want to know if RSAP or R has any library that can actually extract data from a SAP BEx query or BEX Analyzer and then analyze that data further in R.

      I've checked but couldn't come across any such package so just wanted to check with you.

      Thank you.