Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send queries to R server programmatically

Tags:

r

svsocket

Please consider the following example (using 2 R sessions):

1st R session - R Server

library(svSocket)
startSocketServer()

2nd R session - R Client

library(svSocket)
con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)

value<-"setosa"
evalServer(con, tmp, value) # first call to the server
evalServer(con, head(iris[iris$Species==tmp,])) # second call to the server
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

To send the above query I need a 2-step process where I first save my parameter in the server and then I use them to query the table.

Problem

Do the same in one step only. For example, building the query using paste and send it to the server like I would in PHP + MySQL. Basically, I need to avoid that a different user overwrites tmp between the first and the second call to the server. The above commands will be running behind web apps with 30 to 50 users simultaneously connected, so I reckon that this inconvenience might happen.

like image 675
Michele Avatar asked Apr 21 '26 04:04

Michele


1 Answers

One possible answer

$ query <- paste0('evalServer(con,"head(iris[iris$Species==\'', value,'\',])")')
$ eval(parse(text=query))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

This does the job but it's kind of a dial... The code is very messy and difficult to read.

Final solution:

I ended up modifying/simplifying evalServer. This version accept only a character string with the expression to evaluate in the server

evalServer2 <- function (con, expr) 
{
  if(!is.character(expr)) stop("expr must be a character string containing the expression to evaluate in the server.")
  cat("..Last.value <- try(eval(parse(text = \"", expr, "\"))); .f <- file(); dump(\"..Last.value\", file = .f); flush(.f); seek(.f, 0); cat(\"\\n<<<startflag>>>\", gsub(\"<pointer: [0-9a-fx]+>\", \"NULL\", readLines(.f)), \"<<<endflag>>>\\n\", sep = \"\\n\"); close(.f); rm(.f, ..Last.value); flush.console()\n", 
      file = con, sep = "")
  objdump <- ""
  endloc <- NULL
  while (!length(endloc)) {
    obj <- readLines(con, n = 1000, warn = FALSE)
    if (!length(obj)) {
      Sys.sleep(0.01)
      next
    }
    endloc <- grep("<<<endflag>>>", obj)
    if (length(endloc)) 
      obj <- obj[0:(endloc[length(endloc)] - 1)]
    objdump <- c(objdump, obj)
  }
  startloc <- grep("<<<startflag>>>", objdump)
  if (!length(startloc)) 
    stop("Unable to find <<<startflag>>>")
  objdump <- objdump[-(1:startloc[length(startloc)])]
  nospace <- grep("[^ ]$", objdump)
  nospace <- nospace[nospace < length(objdump)]
  for (i in rev(nospace)) {
    objdump[i] <- paste(objdump[i], objdump[i + 1], sep = "")
    objdump[i + 1] <- ""
  }
  objcon <- textConnection(objdump)
  on.exit(close(objcon))
  source(objcon, local = TRUE, echo = FALSE, verbose = FALSE)
  return(..Last.value)
}

which allows:

> x <- "5 + 4"
> evalServer2(con, x)
[1] 9

Instead, evalServer would retrieve a variable called x stored in the R server

> evalServer(con, x, 23)
[1] TRUE
> evalServer(con, x)
[1] 23
> evalServer2(con, "x")
[1] 23
like image 140
Michele Avatar answered Apr 23 '26 20:04

Michele



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!