Hi Sam,

The heart of your problem is that you are not using strings in your off
statements. Rather, you are calling objects called norm and cumu and R is
trying to test those for equality.

In the first case, when you get to norm, R tries to call the norm()
function, which is the magnitude of a vector, not the normal distribution,
and do an equality test there. In the second, R looks for a cumu, but since
there's nothing available to it by that name, throws an error.

Instead, write the following (I've cleaned it up a little and I'll note that
below)

my.fun <- function(x, bMelt=TRUE, dist.type="norm") {
    library(reshape)
    N.dist <- as.data.frame(sapply(seq_along(x),
function(i){x[[i]]/rowSums(x[,1:4])*100}))
    if (dist.type == "norm") {
        #Normalized distribution
        if (! bMelt) return(N.dist)
        return(melt.data.frame(N.dist))
    } else if (dist.type == "cumu") {
        ## Cumulative distribution
        C.dist <- as.data.frame(t(apply(N.dist, 1, cumsum)))
        if (! bMelt) return(C.dist)
        return(melt.data.frame(C.dist))
    } else stop("Could not match distribution type.")
}

I'll note a few other things in your code:

0) probably best not to actually use melt as a value since it's also a
function name.

1) Since melt is a T/F value, it's unnecessary to check if melt==T when that
has exactly the same value as melt itself. Similarly melt==F can be written
!melt.

2) It's generally better to use seq_along(x) rather than 1:length(x) because
it handles the case when x is empty/null/whatever better.

3) Since return ends function execution, you can simplify alot of your code
and reduce doubling up on calls to test equality etc. Specifically, if you
haven't ended due to the return following !bMelt (so melt is TRUE) then you
can just assume bMelt is true and go straight to that return statement.

4) No need to have the melt.data.frame call unless you actually do need it:
will save you some computing time.

5) If you put a library(reshape) call in, you won't get caught unawares
without the requisite package. You could also do this more properly with a
require() call, but library throws a good error, so you might want to stick
with it for now.

6) No need for c(1:4), that's exactly the same as 1:4 to R.

> identical(c(1:4),1:4)
[1] TRUE


7) Standard R practice is, in my experience, to enclose the definition of a
function in {} rather than ().

Hope this helps (and that I didn't break anything important)

Let me know if I can explain anything further,

Michael Weylandt


On Thu, Aug 25, 2011 at 7:07 PM, Sam Albers <tonightsthenight@gmail.com>wrote:

> Hello all,
>
> I am trying write a fairly simple function that provide a quick way to
> calculate several distributions for a data set. I am trying to provide
> a function that has a argument that specifies which distribution is
> outputted (here "norm" or "cumu"). I also have a melt argument but
> that seems to be working fine. I have been able to get my function
> working well for just one distribution but when I add another and try
> to add a "dist.type" argument (with potential values "cumu" and
> "norm"), I get an error message (see below). I am having trouble
> finding material that explains how to add an argument that isn't a
> TRUE/FALSE situation. Could any explain what I am doing wrong with the
> second "distribution specifying" argument? I apologize as I am sure
> this is a simple problem but I am just getting my feet wet with this
> type of thing in R and am having a little trouble diagnosing the
> problem.
>
> #Example below:
>
> library(reshape)
>
> dat <- data.frame(`v1`=runif(6, 0, 125),
>                  `v2`=runif(6, 50, 75),
>                  `v3`=runif(6, 0, 100),
>                  `v4`=runif(6, 0, 200)
>                  )
>
>
> my.norm <- function(x, melt=TRUE)
> {
>         #Normalized distribution
>         N.dist <- as.data.frame(sapply(1:length(x), function(i)
> (x[[i]]/rowSums(x[,c(1:4)]))*100 ))
>         norm.melt <- melt.data.frame(N.dist)
>         if (melt == TRUE) ##Default is a melted data frame
>          return(norm.melt)
>           if (melt == FALSE)
>            return(N.dist)
>       }
>
> ## So this single distribution function works fine
> my.norm(dat, melt=TRUE)
>
> my.fun <- function(x, melt=TRUE, dist.type=norm)
> {
>         #Normalized distribution
>         N.dist <- as.data.frame(sapply(1:length(x), function(i)
> (x[[i]]/rowSums(x[,c(1:4)]))*100 ))
>         norm.melt <- melt.data.frame(N.dist)
>         if (melt == TRUE && dist.type == norm) ##Default is a melted data
> frame
>          return(norm.melt)
>           if (melt == FALSE && dist.type == norm)
>            return(N.dist)
>
>         ## Cumulative distribution
>         C.dist <- as.data.frame(t(apply(N.dist, 1, cumsum)))
>         cumu.melt <- melt.data.frame(C.dist)
>         if (melt == TRUE && dist.type == cumu) ##Default is a melted data
> frame
>          return(cumu.melt)
>           if (melt == FALSE && dist.type == cumu)
>            return(C.dist)
>       }
>
> ## But this function when used yields two different error messages
> depending on the value used for dist.type:
> my.fun(dat, melt=TRUE, dist.type = norm)
> ## Error in dist.type == norm :
> ##  comparison (1) is possible only for atomic and list types
>
> my.fun(dat, melt=TRUE, dist.type = cumu)
> ## Error in my.fun(dat, dist.type = cumu) : object 'cumu' not found
>
> Thanks in advance!
>
> Sam
>
> ______________________________________________
> R-help@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>

	[[alternative HTML version deleted]]

