0

I'm trying to reproduce the following code (nls function does not perform well), but with an extra implementation, using for loops, sprintf and as.formula(), that adds variables depending of the number of peaks in the given spectrum. To be more coherent among peaks, I vectorized the variable names for each peak, so peak number 1 has 'alfa[1]', 'peak[1]' and 'height[1]' related to it.

So far, I got the expected formula:

height[1]/(pi*alfa[1]*(1+((x-peak[1])/alfa[1])^2))+height[2]/(pi*alfa[2]*(1+((x-peak[2])/alfa[2])^2))+drift.a+drift.b*x

Nevertherless, I have some problems when I try to replicate the same system for the par line. This should show:

par=c(alfa[1]=0.001,
      peak[1]=2.156460,
      height[1]=1,
      alfa[2]=0.001,
      peak[2]=2.170150,
      height[2]=1, 
      drift.a=0, 
      driftb=0)

But instead, when I collapse all strings and used the as.formula command afterwards, I got:

Error en parse(text = x) : <text>:1:15: unexpected '='
1: par=c( alfa[1]=
                  ^

If I print the collapsed string, the character line is the one expected, so I'm thinking that it will be somehow linked to the as.formula command (i.e. it may not be the appropiated command)

Community
  • 1
  • 1
  • Add the names separately ie `par <- c(0.001, 2.15646,...); names(par) <- c(alfa[1], peak[1],...)`. – Jake Burkhead Jan 30 '14 at 12:29
  • 1
    With no disrespect to JHoward, I'd suggest *not* using "par" as a variable name, since it can conflict with the graphical function `par` . But anyway, I suspect that trying to create names like "alfa[1]" is the problem, since `R` tries to find the first element of the object `alpha` . If you just write `par=c(alfa1=1,peak1=2,...` that probably will parse OK. – Carl Witthoft Jan 30 '14 at 13:09

2 Answers2

1

When you create a named vector using c, the names must be valid variable names, or you have to wrap them in quotes.

This is OK:

c(alfa1 = 0.001)
## alfa1 
## 0.001

alfa[1] is not a valid variable name – it's the first element of a variable – so you have to wrap it in quotes:

c(alfa1[1] = 0.001)
## Error: unexpected '=' in "c(alfa1[1] ="

c("alfa1[1]" = 0.001)
## alfa1[1] 
##    0.001

Backquotes also work:

c(`alfa1[1]` = 0.001)
## alfa1[1] 
##    0.001

See also is_valid_variable_name in the assertive package.

library(assertive)
is_valid_variable_name(c("alfa1", "alfa[1]"))
##   alfa1 alfa[1] 
##    TRUE   FALSE

You can turn your coefficient names into valid variable names using make.names:

make.names("alfa[1]")
## [1] "alfa.1."
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • When I collapse the strings I obtain: "par=c('alfa[1]'=0.001,'peak[1]'=2.156460,'height[1]'=1,'alfa[2]'=0.001,'peak[2]'=2.170150,'height[2]'=1 ,drift.a=0, drift.b=0)", but when I use the as.formula command thereafter it reported this error: Error in formula.default(eval(parse(text = x)[[1L]])) : invalid formula. – user3032330 Jan 30 '14 at 14:23
  • Richie, well explained but I fear well over the OP's head. – Carl Witthoft Jan 30 '14 at 14:56
  • I don't know how you are "collaps[ing] the strings", but from reading jlhoward's answer to your other question, I think you want `make.names(names(coef(nls.out)))`. – Richie Cotton Jan 30 '14 at 14:57
0

You want to have vectors like alfa and so on to store several values, if I understand you correctly. Maybe you should try to combine this vectors in a list, this makes them more accessible.

And it should be a good idea to name this list not par.

As far as I understand your question, you have more than one peak to process. So you have data like:

peak <- c(2.31, 3.17, ...)
alfa <- c(0.001, 0.002, ...)

In this case, you could use list(peak = peak, ...) to construct a list with all your parameters and then call your function and supply appropriate objects from the list.

Or did I missed the main point of your question?

r_chemist
  • 11
  • 3