11

In Python, you can specify string formats by name (this is of course a silly example):

parameters = {'label':'months', 'april':4,'may':5,'june':6}
formatstring = '%(label)s: %(april)d %(may)d %(june)d'
outputstring = formatstring % parameters

(The formatstring % parameters notation is the Python equivalent to do.call(sprintf,c(formatstring,as.list(parameters))) in R.)

The output string would be "months: 4, 5, 6". parameters is stored as a key-value pair (which might be called a dictionary, hashtable, or named list in various languages). The string format %(text)s allows you to reference which dictionary item (text) should be formatted in that slot.

Is there anything equivalent in R, or you have you found a good workaround?

5
  • In your own interest you shouldn't assume that everyone able to help you with R understands Python. Explain what the Python code does. Commented Jul 4, 2013 at 17:47
  • this question provides some useful background on "printf" in R. Commented Jul 4, 2013 at 17:55
  • Thanks @Roland, I have added explanation. Commented Jul 4, 2013 at 18:01
  • I would use the brew or whisker package for this; they're powerful templating tools. See this question for an example. Commented Jul 4, 2013 at 18:33
  • 1
    See also stackoverflow.com/q/46085274/149988 Commented Apr 18, 2018 at 14:29

2 Answers 2

13

1. Try gsubfn in the gsubfn package:

library(gsubfn)
parameters <- list(label = "months", april = 4, may = 5, june = 6)

gsubfn("\\w+", parameters, "label: april, may, june")

2. or try fn$ from the same package:

with(parameters, fn$identity("$label: $april, $may, $june"))

3. Here is a short infix function that transforms a format string and a list of parameters to a sprintf and then runs it:

library(gsubfn)
`%format%` <- function(fmt, list) {
    pat <- "%\\(([^)]*)\\)"
    fmt2 <- gsub(pat, "%", fmt)
    list2 <- list[strapplyc(fmt, pat)[[1]]]
    do.call("sprintf", c(fmt2, list2))
}

Use it like this:

> '%(label)s: %(april)d %(may)d %(june)d' %format% parameters
[1] "months: 4 5 6"
Sign up to request clarification or add additional context in comments.

2 Comments

This is beautiful, thank you. I knew gsubfn would be the key to the solution. I've been a fan of your work since the R-help days.
This is a nice solution!
6

Although this is not built in to the system sprintf functions that R is using (see man printf for the system docs), it's easy enough to implement such a feature in R by replacing the named references with their respective positions -

sprintf_named <- function(fmt, ...) {
  args <- list(...)
  argn <- names(args)
  if(is.null(argn)) return(sprintf(fmt, ...))

  for(i in seq_along(args)) {
    if(argn[i] == "") next;
    fmt <- gsub(sprintf("%%{%s}", argn[i]), sprintf("%%%d$", i), fmt, fixed = TRUE)
  }

  do.call(sprintf, append(args, fmt, 0))
}

Here is an example usage:

sprintf_named("%{HIA}s!! %{RYLAH}s", RYLAH="Rock You Like a Hurricane", HIA="Here I Am")
## [1] "Here I Am!! Rock You Like a Hurricane"

We could also make it an infix:

`%format%` <- function(left, right) do.call(sprintf_named, append(right, left, 0))

"%{b}s %{a}s" %format% list(a='ya', b='boo')
## [1] "boo ya"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.