def collapse (listoflists,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None):
    """
Averages data in collapsecol, keeping all unique items in keepcols
(using unique, which keeps unique LISTS of column numbers), retaining the
unique sets of values in keepcols, the mean for each.  Setting fcn1
and/or fcn2 to point to a function rather than None (e.g., stats.sterr, len)
will append those results (e.g., the sterr, N) after each calculated mean.
cfcn is the collapse function to apply (defaults to mean, defined here in the
pstat module to avoid circular imports with stats.py, but harmonicmean or
others could be passed).

Usage:    collapse (listoflists,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None)
Returns: a list of lists with all unique permutations of entries appearing in
    columns ("conditions") specified by keepcols, abutted with the result of
    cfcn (if cfcn=None, defaults to the mean) of each column specified by
    collapsecols.
"""
    def collmean (inlist):
        s = 0
        for item in inlist:
            s = s + item
        return s/float(len(inlist))

    if type(keepcols) not in [ListType,TupleType]:
        keepcols = [keepcols]
    if type(collapsecols) not in [ListType,TupleType]:
        collapsecols = [collapsecols]
    if cfcn == None:
        cfcn = collmean
    if keepcols == []:
        means = [0]*len(collapsecols)
        for i in range(len(collapsecols)):
            avgcol = colex(listoflists,collapsecols[i])
            means[i] = cfcn(avgcol)
            if fcn1:
                try:
                    test = fcn1(avgcol)
                except:
                    test = 'N/A'
                    means[i] = [means[i], test]
            if fcn2:
                try:
                    test = fcn2(avgcol)
                except:
                    test = 'N/A'
                try:
                    means[i] = means[i] + [len(avgcol)]
                except __HOLE__:
                    means[i] = [means[i],len(avgcol)]
        return means
    else:
        values = colex(listoflists,keepcols)
        uniques = unique(values)
        uniques.sort()
        newlist = []
        if type(keepcols) not in [ListType,TupleType]:  keepcols = [keepcols]
        for item in uniques:
            if type(item) not in [ListType,TupleType]:  item =[item]
            tmprows = linexand(listoflists,keepcols,item)
            for col in collapsecols:
                avgcol = colex(tmprows,col)
                item.append(cfcn(avgcol))
                if fcn1 <> None:
                    try:
                        test = fcn1(avgcol)
                    except:
                        test = 'N/A'
                    item.append(test)
                if fcn2 <> None:
                    try:
                        test = fcn2(avgcol)
                    except:
                        test = 'N/A'
                    item.append(test)
                newlist.append(item)
        return newlist
dataset/ETHPy150Open sunlightlabs/clearspending/completeness/statlib/pstat.py/collapse