This should work. I updated a personal modification of aggregate that I made
to facilitate return of multiple values if necessary:
#modified aggregate command, implementing na.rm for all functions and
allowing for multiple and/or named return values values
agg=function(z,Ind,FUN,na.rm=F,...){
if(na.rm){
for(i in 1:length(Ind)){
Ind[[i]] = Ind[[i]][!is.na(z)]
}
z = z[!is.na(z)]
}
FUN.out=by(z,Ind,FUN,...)
num.cells=length(FUN.out)
num.values=length(FUN.out[[1]])
Ind.levels = list()
for(i in 1:length(Ind)){
Ind.levels[[i]]=levels(factor(Ind[[i]]))
}
temp=expand.grid(Ind.levels)
if(is.character(names(Ind))){
names(temp) = names(Ind)
}else{
names(temp) = paste('Var',1:length(Ind),sep='')
}
for(i in 1:num.values){
temp$new=NA
n=names(FUN.out[[1]])[i]
names(temp)[length(temp)]=ifelse(!is.null(n),n,ifelse(i==1,'x',paste('x',i,sep='')))
for(j in 1:num.cells){
temp[j,length(temp)]=FUN.out[[j]][i]
}
}
return(temp)
}

# create some data
z=rnorm(100)
A=rep(1:2,each=25,2)
B=rep(1:2,each=50)
Ind=list(A=A,B=B)

aggregate(z,Ind,mean)
agg(z,Ind,mean) #should be identical to aggregate

aggregate(z,Ind,summary) #returns an error
agg(z,Ind,summary) #returns named columns

# Make a function that returns multiple unnamed values
summary2=function(x){
s=summary(x)
names(s)=NULL
return(s)
}
agg(z,Ind,summary2) #returns multiple columns, default names

#demonstrate implementation of na.rm
z[1]=NA
z[100]=NA
agg(z,Ind,sum) #returns NA for some cells
agg(z,Ind,sum,na.rm=T) #removes NAs before calculating sum


On Sun, Dec 7, 2008 at 8:06 AM, Daren Tan <daren76@hotmail.com> wrote:

>
> The aggregate function does "almost" all that I need to summarize a
> datasets, except that I can't specify exclusion of NAs without a little bit
> of hassle.
>
> > set.seed(143)
> > m <- data.frame(A=sample(LETTERS[1:5], 20, T), B=sample(LETTERS[1:10],
> 20, T), C=sample(c(NA, 1:4), 20, T), D=sample(c(NA,1:4), 20, T))
> > m
>   A B  C  D
> 1  E I  1 NA
> 2  A C NA NA
> 3  D I NA  3
> 4  C I  2  4
> 5  A C  3  2
> 6  E J  1  2
> 7  D J  2  2
> 8  C G  4  1
> 9  C D NA  3
> 10 B G  3 NA
> 11 C B  4  2
> 12 A B NA NA
> 13 E A NA  4
> 14 B B  3  3
> 15 E I  4  1
> 16 E J  3  1
> 17 B J  4  4
> 18 B J  1  3
> 19 D D  4  2
> 20 B B  4  3
>
> > aggregate(m[,-c(1:2)], by=list(m[,1]), sum)
>  Group.1  C  D
> 1       A NA NA
> 2       B 15 NA
> 3       C NA 10
> 4       D NA  7
> 5       E NA NA
>
> > aggregate(m[,-c(1:2)], by=list(m[,1]), length)
>  Group.1 C D
> 1       A 3 3
> 2       B 5 5
> 3       C 4 4
> 4       D 3 3
> 5       E 5 5
>
> My own defined version of length and sum to exclude NA
>
> > mylength <- function(x) {  sum(as.logical(x), na.rm=T) }
> > mysum <- function(x) {sum(x, na.rm=T)}
>
> > aggregate(m[,-c(1:2)], by=list(m[,1]), mysum)   <----------------- this
> computes correctly.
>  Group.1  C  D
> 1       A  3  2
> 2       B 15 13
> 3       C 10 10
> 4       D  6  7
> 5       E  9  8
>
> > aggregate(m[,-c(1:2)], by=list(m[,1]), mylength) <----------------- this
> computes correctly.
>  Group.1 C D
> 1       A 1 1
> 2       B 5 4
> 3       C 3 4
> 4       D 2 3
> 5       E 4 4
>
> There are other statistics I need to compute e.g. var, sd, and it is a
> hassle to create customized versions to exclude NA. Any alternative
> approaches ?
>
>
>
>
> _________________________________________________________________
> [[elided Hotmail spam]]
>
> ______________________________________________
> 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.
>



-- 
Mike Lawrence
Graduate Student
Department of Psychology
Dalhousie University
www.thatmike.com

Looking to arrange a meeting? Do so at:
http://www.timetomeet.info/with/mike/

~ Certainty is folly... I think. ~

	[[alternative HTML version deleted]]

