Jb.
Jb.

Reputation: 109

Rounding output from by function in R

I'm trying to round an output from a simple by() function in R. This is what I have:

> by(glaciers[,1:3],glaciers$activity.level,mean)

glaciers$activity.level: Active
       aspect  sun.duration      latitude 
-9.444444e+00  1.771778e+03  3.247643e+09 
-------------------------------------------
glaciers$activity.level: Inactive
      aspect sun.duration     latitude 
1.041667e+01 2.067583e+03 4.048301e+09 
-------------------------------------------
glaciers$activity.level: Relict
      aspect sun.duration     latitude 
1.766667e+01 2.168000e+03 2.759283e+09 

How can I get my output to round to say 5 decimal places, and still keep the factors?

I've tried: round(by(glaciers[,1:3],glaciers$activity.level,mean),5) but get an error: Non-numeric argument to mathematical function.

Upvotes: 8

Views: 15743

Answers (6)

Rob Hyndman
Rob Hyndman

Reputation: 31800

by(glaciers[,1:3], glaciers$activity.level, function(x){round(mean(x),5)})

UPDATE

Here is a working example:

glaciers <- as.data.frame(matrix(rnorm(1000),ncol=4)) 
glaciers[,4] <- sample(0:3,250,replace=TRUE) 
colnames(glaciers) <- c("A","B","C","activity.level") 
by(glaciers[,1:3], glaciers$activity.level, function(x){round(mean(x),5)})

Upvotes: 4

hatmatrix
hatmatrix

Reputation: 44862

If you already have the output saved to a variable, say x:

x <- by(glaciers[,1:3],glaciers$activity.level,mean)

Then apply round() to each element (the output of by() in this case is a list).

x[] <- lapply(x,round,5)
x

reassigning to x[] rather than x allows x to retain attributes attached to it from by().

Edit: round() actually changes the value of the variables but is decoupled from its printing. If you want to suppress the scientific notation output format, use format="f" argument to formatC()

> round(1.2345e10,5)
[1] 1.2345e+10
> formatC(1.2345e10,digits=5,format="f")
[1] "12345000000.00000"

So the correction to the expression originally posted would be

x[] <- lapply(x,formatC,digits=5,format="f")

Upvotes: 10

DamonJW
DamonJW

Reputation: 3662

You asked "How can I get my output to round to say 5 decimal places?" but I think what you meant was "How can I get my output to show say 6 significant figures?" The following code combines two of the previous answers -- the idea of reassigning to res[], and the use of signif rather than round.

glaciers <- data.frame(aspect=runif(20)*100,
                       sun.duration=runif(20)*10000,
                       latitude=runif(20)*10^9,
                       activity.level=sample(c('Active','Inactive','Relict'),20,replace=TRUE))
res <- by(glaciers[,1:3],glaciers$activity.level,mean)
res[] <- lapply(res,signif,3)
res

This code produces the following output:

glaciers$activity.level: Active
      aspect sun.duration     latitude 
    3.66e+01     4.72e+03     4.56e+08 
------------------------------------------------- 
glaciers$activity.level: Inactive
      aspect sun.duration     latitude 
    5.81e+01     5.28e+03     4.83e+08 
------------------------------------------------- 
glaciers$activity.level: Relict
      aspect sun.duration     latitude 
    6.08e+01     4.75e+03     3.98e+08 

Upvotes: 2

Shane
Shane

Reputation: 100144

round() doesn't make sense in this instance, since you're working with very large numebrs. You want to use the format() command, and choose how many digits to display. For instance, to show 3 significant digits:

by(glaciers[,1:3], glaciers$activity.level, function(x) {
      as.numeric(format(mean(x), digits=3))
})

Upvotes: 6

Matt Parker
Matt Parker

Reputation: 27339

Only have a couple of minutes, but you might try looking at the format(), formatC(), and prettyNum() functions. Their help files look like gibberish to me right now, but I haven't slept much. However, I did use one of these functions - most likely formatC() - for a Sweave report some months ago in which I needed very specifically formatted numbers.

Upvotes: 1

Harlan
Harlan

Reputation: 19361

Do you want to round or to just truncate the number of digits shown? If the latter, use options(digits=3) or whatever.

> by(mpg[,8:9], mpg$cyl, mean)
mpg$cyl: 4
   cty    hwy 
21.012 28.802 
------------------------------------------------------------ 
mpg$cyl: 5
  cty   hwy 
20.50 28.75 
------------------------------------------------------------ 
mpg$cyl: 6
   cty    hwy 
16.215 22.823 
------------------------------------------------------------ 
mpg$cyl: 8
   cty    hwy 
12.571 17.629 
> options(digits=3)
> by(mpg[,8:9], mpg$cyl, mean)
mpg$cyl: 4
 cty  hwy 
21.0 28.8 
------------------------------------------------------------ 
mpg$cyl: 5
 cty  hwy 
20.5 28.8 
------------------------------------------------------------ 
mpg$cyl: 6
 cty  hwy 
16.2 22.8 
------------------------------------------------------------ 
mpg$cyl: 8
 cty  hwy 
12.6 17.6 

Upvotes: 1

Related Questions