Repository URL to install this package:
|
Version:
0.3.1 ▾
|
import sys
import numpy as np
from scipy import stats
#from scikits.statsmodels.iolib.table import SimpleTable
from scikits.statsmodels.iolib.table import SimpleTable
class Describe(object):
'''
Calculates descriptive statistics for data.
Defaults to a basic set of statistics, "all" can be specified, or a list can
be given.
dataset : can be either a structured or ndarray (Larry?), observations in
rows, variables in columns.
'''
def __init__(self, dataset):
self.dataset = dataset
# First position is the function
# Second position is the tuple/list of column names/numbers
# third is are the results in order of the columns
self.univariate = dict(
obs = [len, None, None],
mean = [np.mean, None, None],
std = [np.std, None, None],
min = [np.min, None, None],
max = [np.max, None, None],
ptp = [np.ptp, None, None],
mode_val = [self._mode_val, None, None],
mode_bin = [self._mode_bin, None, None],
median = [np.median, None, None],
skew = [stats.skew, None, None],
uss = [stats.ss, None, None],
kurtosis = [stats.kurtosis, None, None],
percentiles = [self._percentiles, None, None],
#sign_test_M = [self.sign_test_m, None, None],
#sign_test_P = [self.sign_test_p, None, None]
)
#TODO: Basic stats for strings
#self.strings = dict(
#unique = [np.unique, None, None],
#number_uniq = [len(
#most = [
#least = [
#TODO: Multivariate
#self.multivariate = dict(
#corrcoef(x[, y, rowvar, bias]),
#cov(m[, y, rowvar, bias]),
#histogram2d(x, y[, bins, range, normed, weights])
#)
self._arraytype = None
self._columns_list = None
def _percentiles(self,x):
p = [stats.scoreatpercentile(x,per) for per in
(1,5,10,25,50,75,90,95,99)]
return p
def _mode_val(self,x):
return stats.mode(x)[0][0]
def _mode_bin(self,x):
return stats.mode(x)[1][0]
def _array_typer(self):
"""if not a sctructured array"""
if not(self.dataset.dtype.names):
"""homogeneous dtype array"""
self._arraytype = 'homog'
elif self.dataset.dtype.names:
"""structured or rec array"""
self._arraytype = 'sctruct'
else:
assert self._arraytype == 'sctruct' or self._arraytype == 'homog'
def _is_dtype_like(self, col):
"""
Check whether self.dataset.[col][0] behaves like a string, numbern unknown.
`numpy.lib._iotools._is_string_like`
"""
def string_like():
#TODO: not sure what the result is if the first item is some type of missing value
try:
self.dataset[col][0] + ''
except (TypeError, ValueError):
return False
return True
def number_like():
try:
self.dataset[col][0] + 1.0
except (TypeError, ValueError):
return False
return True
if number_like()==True and string_like()==False:
return 'number'
elif number_like()==False and string_like()==True:
return 'string'
else:
assert (number_like()==True or string_like()==True), '\
Not sure of dtype'+str(self.dataset[col][0])
#@property
def summary(self, stats='basic', columns='all'):
"""
prints a table of summary statistics and stores the stats.
stats: The desired statistics, A list[] or 'basic' or 'all' are options
'basic' = ('obs', 'mean', 'std', 'min', 'max')
'All' = ('obs', 'mean', 'std', 'min', 'max', 'ptp', 'var', 'mode',
'meadian', 'skew', 'uss', 'kurtosis', 'percentiles')
Columns: The columns/variables to report the statistics, defualt is 'all'
structured array: specify the column names
summary(stats='basic', columns=['alpha', 'beta'])
standard array: Specifiy column numbers (NEED TO TEST)
"""
if self._arraytype == None:
self._array_typer()
if stats == 'basic':
stats = ('obs', 'mean', 'std', 'min', 'max')
elif stats == 'all':
stats = self.univariate.keys()
else:
for astat in stats:
assert astat in self.univariate
if any([aitem[1] for aitem in self.univariate.items() if aitem[0] in stats]):
if columns == 'all':
self._columns_list = []
if self._arraytype == 'sctruct':
self._columns_list = self.dataset.dtype.names
#self._columns_list = [col for col in self.dataset.dtype.names if
#(self._is_dtype_like(col)=='number')]
else:
self._columns_list = range(self.dataset.shape[1])
else:
self._columns_list = columns
if self._arraytype == 'sctruct':
for col in self._columns_list:
assert (col in self.dataset.dtype.names)
else:
assert self._is_dtype_like(self.dataset) == 'number'
columstypes = self.dataset.dtype
#TODO: do we need to make sure they dtype is float64 ?
for astat in stats:
calc = self.univariate[astat]
if self._arraytype == 'sctruct':
calc[1] = self._columns_list
calc[2] = [calc[0](self.dataset[col]) for col in
self._columns_list if (self._is_dtype_like(col) ==
'number')]
#calc[2].append([len(np.unique(self.dataset[col])) for col
#in self._columns_list if
#self._is_dtype_like(col)=='string']
else:
calc[1] = ['Col '+str(col) for col in self._columns_list]
calc[2] = [calc[0](self.dataset[:,col]) for col in self._columns_list]
return self.print_summary(stats)
else:
return self.print_summary(stats)
def print_summary(self, stats):
#TODO: need to specify a table formating for the numbers, using defualt
title = 'Summary Statistics'
header = stats
stubs = self.univariate['obs'][1]
data = [[self.univariate[astat][2][col] for astat in stats] for col in
range(len(self.univariate['obs'][2]))]
table = SimpleTable(data,
header,
stubs,
title=title,)
return table
def sign_test(samp,mu0=0):
'''
Signs test with mu0=0 by default (though
the median is often used in practice)
Parameters
----------
samp
mu0
Returns
---------
M, p-value
where
M=(N(+) - N(-))/2, N(+) is the number of values above Mu0,
N(-) is the number of values below. Values equal to Mu0
are discarded.
The p-value for M is calculated using the binomial distrubution
and can be intrepreted the same as for a t-test.
See Also
---------
scipy.stats.wilcoxon
'''
pos=np.sum(samp>mu0)
neg=np.sum(samp<mu0)
M=(pos-neg)/2.
p=stats.binom_test(min(pos,neg),pos+neg,.5)
return M, p
#TODO: There must be a better way but formating the stats of a fuction that
# returns 2 values is a problem.
#def sign_test_m(samp,mu0=0):
#return self.sign_test(samp,mu0)[0]
#def sign_test_p(samp,mu0=0):
#return self.sign_test(samp,mu0)[1]
########################################
########################################
import unittest
data1 = np.array([(1,2,'a','aa'),
(2,3,'b','bb'),
(2,4,'b','cc')],
dtype = [('alpha',float), ('beta', int),
('gamma', '|S1'), ('delta', '|S2')])
data2 = np.array([(1,2),
(2,3),
(2,4)],
dtype = [('alpha',float), ('beta', float)])
data3 = np.array([[1,2,4,4],
[2,3,3,3],
[2,4,4,3]], dtype=float)
data4 = np.array([[1,2,3,4,5,6],
[6,5,4,3,2,1],
[9,9,9,9,9,9]])
class TestSimpleTable(unittest.TestCase):
#from scikits.statsmodels.iolib.table import SimpleTable, default_txt_fmt
def test_basic_1(self):
print('test_basic_1')
t1 = Describe(data1)
print(t1.summary())
def test_basic_2(self):
print('test_basic_2')
t2 = Describe(data2)
print(t2.summary())
def test_basic_3(self):
print('test_basic_3')
t1 = Describe(data3)
print(t1.summary())
def test_basic_4(self):
print('test_basic_4')
t1 = Describe(data4)
print(t1.summary())
def test_basic_1a(self):
print('test_basic_1a')
t1 = Describe(data1)
print(t1.summary(stats='basic', columns=['alpha']))
def test_basic_1b(self):
print('test_basic_1b')
t1 = Describe(data1)
print(t1.summary(stats='basic', columns='all'))
def test_basic_2a(self):
print('test_basic_2a')
t2 = Describe(data2)
print(t2.summary(stats='all'))
def test_basic_3(aself):
t1 = Describe(data3)
print(t1.summary(stats='all'))
def test_basic_4a(self):
t1 = Describe(data4)
print(t1.summary(stats='all'))
if __name__ == "__main__":
unittest.main()