views:

321

answers:

4

Hi I'm having a bit of a problem programming R for Sweave, and the #rstats twitter group often points here, so I thought I'd put this question to the SO crowd. I'm an analyst- not a programmer- so go easy on me my first post.

Here's the problem: I am drafting a survey report in Sweave with R and would like to report the marginal returns in line using \Sexpr{}. For example, rather than saying:

Only 14% of respondents said 'X'.

I want to write the report like this:

Only \Sexpr{p.mean(variable)}$\%$ of respondents said 'X'.

The problem is that Sweave() converts the results of the expression in \Sexpr{} to a character string, which means that the output from expression in R and the output that appears in my document are different. For example, above I use the function 'p.mean':

p.mean<- function (x) {options(digits=1)  
mmm<-weighted.mean(x, weight=weight, na.rm=T)  
print(100*mmm)  
}

In R, the output looks like this:

p.mean(variable)
>14

but when I use \Sexpr{p.mean(variable)}, I get an unrounded character string (in this case: 13.5857142857143) in my document. I have tried to limit the output of my function to 'digits=1' in the global environment, in the function itself, and and in various commands. It only seems to contain what R prints, not the character transformation that is the result of the expression and which eventually prints in the LaTeX file.

as.character(p.mean(variable))  
>[1] 14  
>[1] "13.5857142857143"  

Does anyone know what I can do to limit the digits printed in the LaTeX file, either by reprogramming the R function or with a setting in Sweave or \Sexpr{}? I'd greatly appreciate any help you can give.

Thanks, David

+2  A: 
as.character(round(p.mean(variable)))

?

KennyTM
Thanks! rewriting my function to:> p.mean<- function (x) { mmm<-weighted.mean(x, weight=weight, na.rm=T) return(round(100*mmm)) }works perfectly.
deoksu
A: 

Try 'format':

options(digits=1)

and then:

\Sexpr{format(p.mean(variable))}

You can also use the 'nsmall' argument:

options(digits=3)
...
\Sexpr{format(sqrt(2)-0.41,nsmall=2)}

And you can also try 'sprintf' if you're familiar with C.

cocinerox
+1  A: 

@KennyTM got it. @David, you should avoid options(digits = 1) since it will affect all of your calculations (it will suppress decimals in each output afterwards). So use round() function after applying the weighted.mean(). Something like this:

\Sexpr{round(p.mean(x))}

And do not use print(), but return(). Here's why:

> set.seed(1234)
> x <- rnorm(100)
> foo <- function(x) {
   res <- mean(x) + 5
   print(res)
}
> foo(x)
[1] 5
> foo(x) + 10
[1] 5
[1] 15

Use return() or just type the resulting variable in the last line:

> bar <- function(x) {
   res <- mean(x) + 5
   return(res)
}
> bar(x) + 10
[1] 15

So, rewrite your function, and be sure to use as.character()... you have all the bits, now just put it all together.

P.S.

I'm not sure how you function works... I've never used weighed mean in my analysis. The bit that's puzzling me the most is weight=weight. Wouldn't it be nicer to put one more argument in function? Frankly, I'm still amazed by the fact that your function is giving you right result... probably because you have weight variable defined prior to function definition. [EDIT] You will not get the weighted mean with your function if you don't have weight function predefined, but "regular" mean!

I hope this one helped you!

Kind regards, Aleksandar

aL3xa
Thanks, Aleksandar. I rewrote the function like this: p.mean<- function (x) { mmm<-weighted.mean(x, weight=weight, na.rm=T) return(round(100*mmm)) } I prespecified the weight variable because I am attempting to minimize programming as I am type. Because all of the datasets that I work with have their weight variable labeled 'weight', this makes my writing just a tiny bit more efficient.
deoksu
A: 

the sprintf() function is great for formatting numerical output.

Thierry