Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programming R/Sweave for proper \Sexpr output

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 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 the 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{}?

like image 312
deoksu Avatar asked Mar 21 '10 06:03

deoksu


1 Answers

@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

like image 171
aL3xa Avatar answered Oct 10 '22 02:10

aL3xa