[R] cast function in package reshape

hadley wickham h.wickham at gmail.com
Fri Apr 17 16:06:59 CEST 2009


On Fri, Apr 17, 2009 at 8:38 AM, David Hajage <dhajage.r at gmail.com> wrote:
> Hello R useRs,
>
> I have a function which returns a list of functions :
>
> freq1 <- function(x) {
>  lev <- unique(x[!is.na(x)])
>  nlev <- length(lev)
>  args <- alist(x=)
>
>  if (nlev == 1) {
>    body <- c("{", "sum(!is.na(x))", "}")
>    f <- function() {}
>    formals(f) <- as.pairlist(args)
>    body(f) <- parse(text = body)
>    namef <- paste("freq", as.character(nlev), sep = "_")
>    assign(namef, f)
>    res <- list(get(namef))
>    names(res) <- namef
>  }
>  if (nlev > 1) {
>    res <- NULL
>    namesf <- NULL
>    for (i in 1:nlev) {
>      body <- c("{", paste("sum(x[!is.na(x)] ==", as.character(lev[i]), ")",
> sep = " "), "}")
>      f <- function() {}
>      formals(f) <- as.pairlist(args)
>      body(f) <- parse(text = body)
>      namef <- paste("freq", as.character(lev[i]), sep = "_")
>      assign(namef, f)
>      namesf <- c(namesf, namef)
>      res <- c(res, get(namef))
>    }
>    names(res) <- namesf
>  }
>  return(res)
> }
>
> df <- data.frame(id = 1:50, x = sample(c(NA, 1), 50, T), y = sample(1:2, 50,
> T), z = sample(letters[1:2], 50, T))
>
>> freq1(df$x)
> $freq_1
> function (x)
> {
>    sum(!is.na(x))
> }
> <environment: 0x03d99684>
>
>> freq1(df$y)
> $freq_2
> function (x)
> {
>    sum(x[!is.na(x)] == 2)
> }
> <environment: 0x03d6c930>
>
> $freq_1
> function (x)
> {
>    sum(x[!is.na(x)] == 1)
> }
> <environment: 0x03d6c930>
>
>
> I would like to use this list of functions with cast function (in package
> reshape by Hadley Wickham) :
>
>> cast(melt(df, id = c("id", "z"), measure = c("x", "y")), variable +
> result_variable ~ z, fun = function(x) freq1(x), margins = "grand_col")
> Erreur dans freq1(x) : objet "res" non trouvé
>
> Here the result I would like to have :
>
>  variable                  a  b (all)
> 1        x          freq_1 10 14    24
> 2        y          freq_1 18 32    50
> 3        y          freq_2  9 14    23
>
> I admit it is a bit far-fetched, but is this actually possible ?

Something like this?

df <- data.frame(
  id = 1:50,
  x = sample(c(NA, 1), 50, T),
  y = sample(1:2, 50, T),
  z = sample(letters[1:2], 50, T)
)
dfm <- melt(df, id = c("id", "z"))


f1 <- function(base)
  function(x) table(factor(x, levels = unique(base)))
cast(dfm, variable + result_variable ~ z, f1(dfm$value),
  margins = "grand_col")

I think f1 effectively does what your freq1 function does, but always
returns the same number of results, a requirement of the aggregation
function in cast.

Hadley

-- 
http://had.co.nz/




More information about the R-help mailing list