34

Is there a way to read parameters from a file in an R script?

I want to create a config file that has

db_host=xxxx
db_name=xxxx
db_user=xxxx
db_pass=xxxx

and then use it in the R script to create DB Connection.

dbConnect(PgSQL(), host="xxxx", dbname="xxxxx", user="xxxx", password="xxxxx")

and then how do I use it in the R Script.

EDITED: I also want to know if there is a way in which I can use a single config file across R Scripts, Perl Scripts & Java?

Blaszard
  • 30,954
  • 51
  • 153
  • 233
Salman A. Kagzi
  • 3,833
  • 13
  • 45
  • 64

5 Answers5

45

I'd go for YAML. Designed for human read-writability unlike XML. R package "yaml" exists on CRAN, I'm sure perl and java packages exist too.

http://ftp.heanet.ie/mirrors/cran.r-project.org/web/packages/yaml/index.html

You can't get more cross-platform than this:

http://yaml.org/

at least until I write a YAML FORTRAN package...

[edit]

Example. Suppose you have config.yml:

db:
 host : foo.example.com
 name : Foo Base
 user : user453
 pass : zoom

Then yaml.load_file("config.yml") returns:

$db
$db$pass
[1] "zoom"

$db$user
[1] "user453"

$db$name
[1] "Foo Base"

$db$host
[1] "foo.example.com"

So you do:

library(yaml)
config = yaml.load_file("config.yml")
dbConnect(PgSQL(), host=config$db$host, dbname=config$db$name, user=config$db$user, password=config$db$pass)

Add as many sections and parameters as you need. Sweeeeyit.

The yaml.load_file returns your configuration as an R list, and you can access named elements of lists using $-notation.

Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • Thank. I tried this. But I am getting `Error: could not find function "yaml.load_file" Execution halted`. I have installed YAML package in my R installation using `install.packages("yaml", dependencies=TRUE)` and it did complete successfully. Can you help me get past this. – Salman A. Kagzi Mar 12 '11 at 18:34
  • @Salman: Did you load the yaml package before calling `yaml.load_file` using `library(yaml)`? – Sharpie Mar 13 '11 at 05:30
  • I've edited my answer to give this example. You should read a good R intro so you understand some of the basics - it won't take too long! – Spacedman Mar 13 '11 at 10:19
  • Thanks a ton Spacedman. Actually I had worked my way through this already. YAML is a wonderful suggestion and there is no doubt, I am using this now to share DB Configuration across Java, Perl and R. Very simple to use I must say. – Salman A. Kagzi Mar 13 '11 at 17:38
  • Plays nice with Python too. I use it for persistence - it's the best thing ever!! – David Heffernan Mar 13 '11 at 22:27
  • this is amazing. it saved me – kRazzy R Jun 30 '19 at 16:33
12

You can source() an R script in at the top of your main script that reads in your config file parameters. Depending on who you are sharing your scripts with, there may be issues with database security and having the login information in an unencrypted format. There is a recent question here on SO about that, I'll see if I can find it in a minute.

Anyways, store all of your db parameters in a file named config.R and then on your main script, run:

source("config.R") #Will create four objects named "db_host, db_name, db_user, db_pass"

dbConnect(PgSQL(), host=db_host, dbname=db_name, user=db_user, password=db_pass)
Chase
  • 67,710
  • 18
  • 144
  • 161
  • Thanks Chase. This is good. Security is not that much of a problem in my case. Can you suggest a way in which I can share same config file across R script, perl script and a Java class? – Salman A. Kagzi Mar 11 '11 at 12:45
  • @Salman - I don't know enough about perl or Java to answer in specifics - but I'm sure that both languages have the ability to parse a flat file and extract meaningful information out of them. From what I know of perl, that's exactly what it's designed to do. Sorry I can't be of more help with the details... – Chase Mar 11 '11 at 13:09
  • Use coma (,) delimited file then. python has csv library which would read that without problems, perl probably as well, even though parsing this file is easy. – bua Mar 11 '11 at 13:09
  • @Chase - Thanks. Dont worry about it. Is it possible to read environment variable in R. We can do that easily in Java & Perl. I dont want to resort much on file parsing and use something that is available out of the box. – Salman A. Kagzi Mar 11 '11 at 13:18
  • @Salman - [rJava](http://rosuda.org/rJava/) and/or this link on [omegahat](http://www.omegahat.org/RSPerl/RFromPerl.html) may be worth looking into – Chase Mar 11 '11 at 16:00
  • 1
    Salman, please consider `help(Sys.getenv)`. Environment variables can be a help indeed. – Dirk Eddelbuettel Mar 11 '11 at 17:55
  • Environment variables are visible to all via 'ps'. Its yet another security problem if you start passing usernames and passwords around with them. You should never stick usernames and passwords in args or envs. – Spacedman Mar 11 '11 at 18:49
3

The built-in R function read.table handles this INI format well if you suggest that it split columns using the equals sign.

key.val <- read.table(filename, sep="=", col.names=c("key","value"), as.is=c(1,2))

If you want a more traditional INI behavior, so that you can use multiple config files, try assigning the key-value pairs to an R environment. For example:

read.config <- function(filename) {
  conf.vars <- new.env()
  for (f in filename) {
    if (file.exists(f)) {
      header <- 1
      key.val <- read.table(f, sep="=", col.names=c("key","value"), skip=header,
          as.is=c(1,2))
      for (kidx in seq(length(key.val$key))) {
        assign(key.val[["key"]][kidx], key.val[["value"]][kidx], envir=conf.vars)
      }
    }
  }
  return(conf.vars)
}

get.config <- function(name) {
  kv.env=read.config(c("project.cfg","project_local.cfg"))
  return(kv.env[[name]])
}
ah bon
  • 9,293
  • 12
  • 65
  • 148
adolgert
  • 31
  • 1
1

What you describe here is a desire for common configuration across systems, platforms, languages, ...

That is a big topic and much ink has been spilled on this. Some people see XML as the answer, other prefer simpler related formats like JSON. You could also try Apache-style config files as most languages have libraries for it (but R may be an exception).

I happen to like Google ProtocolBuffers which are fast, efficient, cross-platform, multi-language, forward-compatible ... but have the one downside of not being ascii files (though you can read ascii files first and then create proto files). For R, there is the RProtoBuf package.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
0

If you use an INI configuration file, you can use the ini package. For example:

library(ini)
config <- read.ini('/config/database.ini')

https://cran.r-project.org/web/packages/ini/ini.pdf

Giacomo
  • 1,796
  • 1
  • 24
  • 35