~scipystats/+junk/skipper-revjp

« back to all changes in this revision

Viewing changes to nipy/fixes/scipy/stats/models/tools.py

  • Committer: joep
  • Date: 2009-08-17 03:43:53 UTC
  • mfrom: (1799.1.26 skipper-working)
  • Revision ID: josef.pktd@gmail.com-20090817034353-ktg588ju3qhmruvq
merge from Skipper, trying to clear up move, keeping history

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
'''
2
 
Utility functions for data manipulation
 
2
Utility functions models code
3
3
'''
4
4
 
5
5
import numpy as np
6
6
import numpy.lib.recfunctions as nprf
 
7
import numpy.linalg as L
 
8
import scipy.interpolate
 
9
import scipy.linalg
7
10
 
8
11
#FIXME: make this more robust
9
12
# needs to not return a dummy for *every* variable...
160
163
#        lfit.calc_beta = self.calc_beta # needed for cov_beta()
161
164
#        return lfit
162
165
 
 
166
def isestimable(C, D):
 
167
    """
 
168
    From an q x p contrast matrix C and an n x p design matrix D, checks
 
169
    if the contrast C is estimable by looking at the rank of vstack([C,D]) and
 
170
    verifying it is the same as the rank of D.
 
171
    """
 
172
    if C.ndim == 1:
 
173
        C.shape = (C.shape[0], 1)
 
174
    new = np.vstack([C, D])
 
175
    if rank(new) != rank(D):
 
176
        return False
 
177
    return True
 
178
 
 
179
def recipr(X):
 
180
    """
 
181
    Return the reciprocal of an array, setting all entries less than or
 
182
    equal to 0 to 0. Therefore, it presumes that X should be positive in
 
183
    general.
 
184
    """
 
185
    x = np.maximum(np.asarray(X).astype(np.float64), 0)
 
186
    return np.greater(x, 0.) / (x + np.less_equal(x, 0.))
 
187
 
 
188
def mad(a, c=0.6745, axis=0):
 
189
    """
 
190
    Median Absolute Deviation:
 
191
 
 
192
    median(abs(a - median(a))) / c
 
193
 
 
194
    """
 
195
 
 
196
    _shape = a.shape
 
197
    a.shape = np.product(a.shape,axis=0)
 
198
    m = np.median(np.fabs(a - np.median(a))) / c
 
199
    a.shape = _shape
 
200
    return m
 
201
 
 
202
def recipr0(X):
 
203
    """
 
204
    Return the reciprocal of an array, setting all entries equal to 0
 
205
    as 0. It does not assume that X should be positive in
 
206
    general.
 
207
    """
 
208
    test = np.equal(np.asarray(X), 0)
 
209
    return np.where(test, 0, 1. / X)
 
210
 
 
211
def clean0(matrix):
 
212
    """
 
213
    Erase columns of zeros: can save some time in pseudoinverse.
 
214
    """
 
215
    colsum = np.add.reduce(matrix**2, 0)
 
216
    val = [matrix[:,i] for i in np.flatnonzero(colsum)]
 
217
    return np.array(np.transpose(val))
 
218
 
 
219
def rank(X, cond=1.0e-12):
 
220
    """
 
221
    Return the rank of a matrix X based on its generalized inverse,
 
222
    not the SVD.
 
223
    """
 
224
    X = np.asarray(X)
 
225
    if len(X.shape) == 2:
 
226
        D = scipy.linalg.svdvals(X)
 
227
        return int(np.add.reduce(np.greater(D / D.max(), cond).astype(np.int32)))
 
228
    else:
 
229
        return int(not np.alltrue(np.equal(X, 0.)))
 
230
 
 
231
def fullrank(X, r=None):
 
232
    """
 
233
    Return a matrix whose column span is the same as X.
 
234
 
 
235
    If the rank of X is known it can be specified as r -- no check
 
236
    is made to ensure that this really is the rank of X.
 
237
 
 
238
    """
 
239
 
 
240
    if r is None:
 
241
        r = rank(X)
 
242
 
 
243
    V, D, U = L.svd(X, full_matrices=0)
 
244
    order = np.argsort(D)
 
245
    order = order[::-1]
 
246
    value = []
 
247
    for i in range(r):
 
248
        value.append(V[:,order[i]])
 
249
    return np.asarray(np.transpose(value)).astype(np.float64)
 
250
 
 
251
class StepFunction:
 
252
    """
 
253
    A basic step function: values at the ends are handled in the simplest
 
254
    way possible: everything to the left of x[0] is set to ival; everything
 
255
    to the right of x[-1] is set to y[-1].
 
256
 
 
257
    Examples
 
258
    --------
 
259
    >>> from numpy import arange
 
260
    >>> from models.tools import StepFunction
 
261
    >>>
 
262
    >>> x = arange(20)
 
263
    >>> y = arange(20)
 
264
    >> f = StepFunction(x, y)
 
265
    >>>
 
266
    >>> print f(3.2)
 
267
    3.0
 
268
    >>> print f([[3.2,4.5],[24,-3.1]])
 
269
    [[  3.   4.]
 
270
     [ 19.   0.]]
 
271
    """
 
272
 
 
273
    def __init__(self, x, y, ival=0., sorted=False):
 
274
 
 
275
        _x = np.asarray(x)
 
276
        _y = np.asarray(y)
 
277
 
 
278
        if _x.shape != _y.shape:
 
279
            raise ValueError, 'in StepFunction: x and y do not have the same shape'
 
280
        if len(_x.shape) != 1:
 
281
            raise ValueError, 'in StepFunction: x and y must be 1-dimensional'
 
282
 
 
283
        self.x = np.hstack([[-np.inf], _x])
 
284
        self.y = np.hstack([[ival], _y])
 
285
 
 
286
        if not sorted:
 
287
            asort = np.argsort(self.x)
 
288
            self.x = np.take(self.x, asort, 0)
 
289
            self.y = np.take(self.y, asort, 0)
 
290
        self.n = self.x.shape[0]
 
291
 
 
292
    def __call__(self, time):
 
293
 
 
294
        tind = np.searchsorted(self.x, time) - 1
 
295
        _shape = tind.shape
 
296
        return self.y[tind]
 
297
 
 
298
def ECDF(values):
 
299
    """
 
300
    Return the ECDF of an array as a step function.
 
301
    """
 
302
    x = np.array(values, copy=True)
 
303
    x.sort()
 
304
    x.shape = np.product(x.shape,axis=0)
 
305
    n = x.shape[0]
 
306
    y = (np.arange(n) + 1.) / n
 
307
    return StepFunction(x, y)
 
308
 
 
309
def monotone_fn_inverter(fn, x, vectorized=True, **keywords):
 
310
    """
 
311
    Given a monotone function x (no checking is done to verify monotonicity)
 
312
    and a set of x values, return an linearly interpolated approximation
 
313
    to its inverse from its values on x.
 
314
    """
 
315
 
 
316
    if vectorized:
 
317
        y = fn(x, **keywords)
 
318
    else:
 
319
        y = []
 
320
        for _x in x:
 
321
            y.append(fn(_x, **keywords))
 
322
        y = np.array(y)
 
323
 
 
324
    a = np.argsort(y)
 
325
 
 
326
    return scipy.interpolate.interp1d(y[a], x[a])
 
327