[
  {
    "path": ".gitignore",
    "content": "doc.yaml\n*.swp\n*.rbc\ncoverage\n*~\nagregar_adsense_a_doc.rb\npkg\ndoc\n.yardoc\nexamples/images/*\nexamples/*.html\nweb/upload_task.rb\n.idea\n"
  },
  {
    "path": ".travis.yml",
    "content": "language:\n  ruby\n\nrvm:\n  - '1.9.3'\n  - '2.0.0'\n  - '2.1.1'\n\nscript:\n  bundle exec rake test\n  \nbefore_install:\n  - sudo apt-get update -qq\n  - sudo apt-get install -y libgsl0-dev r-base r-base-dev\n  - sudo Rscript -e \"install.packages(c('Rserve','irr'),,'http://cran.us.r-project.org')\"\n"
  },
  {
    "path": "Gemfile",
    "content": "source \"https://www.rubygems.org\"\ngem 'minitest'\ngem 'rdoc'\ngem 'mocha', '0.14.0' #:require=>'mocha/setup'\ngem 'shoulda','3.5.0'\ngem 'shoulda-matchers','2.2.0'\ngem 'hoe'\n#gem 'bio-statsample-timeseries'\ngem 'reportbuilder'\ngem 'dirty-memoize'\ngem 'distribution'\ngem 'extendmatrix'\ngem 'minimization'\ngem 'rserve-client'\ngem 'rubyvis'\ngem 'spreadsheet'\ngem 'rb-gsl'\ngem 'awesome_print'\n"
  },
  {
    "path": "History.txt",
    "content": "=== 1.4.0 / 2014-10-11\n  * Replaced README.txt for README.md\n  * Replace File.exists? for File.exist?\n  + New Dataset.join to join two dataset based on some fields\n  * Deleted MLE based regression (Probit and logistic). Now all GML methods are on statsample-glm\n  \n=== 1.3.1 / 2014-06-26\n\n  * Example referred to a SimpleRegression class which doesn't exist. Updated to working example.\n  * Merge pull request #15 from Blahah/patch-1\n  * Updated Gemfile\n  * Updated README.txt for v1.3.0\n  * Updated to ruby 2.1.0\n\n=== 1.3.0 / 2013-09-19\n\n  * Merge remote-tracking branch 'vpereira/master' into vpereira\n  * New Wilcoxon Signed Rank test\n  * Remove TimeSeries class. Now is available on gem \"bio-statsample-timeseries\" [GSOC 2013 project :) ]\n  * Update shoulda support\n  * added Bundle depds\n  * improved the csv read method (requires tests)\n  * open svg on mac osx\n\n=== 1.2.0 / 2011-12-15\n  \n  * Added support for time series (TimeSeries object): MA, EMA, MACD, acf, lag and delta. [Rob Britton]\n  * Changed summary attribute to properly display 'b' value for simple linear regression [hstove]\n  * Merge pull request #6 from hstove/patch-1Changed summary attribute to properly display 'b' value for simple linear regression [Claudio Bustos]\n  * fix example code for CovariateMatrix [James Kebinger]\n\n=== 1.1.0 / 2011-06-02\n\n* New Statsample::Anova::Contrast\n* Jacknife and bootstrap for Vector. Thanks to John Firebaugh for the idea\n* Improved Statsample::Analysis API\n* Updated CSV.read. Third argument is a Hash with options to CSV class  \n* Added restriction on Statsample::Excel.read\n* Updated spanish po \n* Better summary for Vector\n* Improving summary of t related test (confidence interval and estimate output)\n* Replaced c for vector on Statsample::Analysis examples\n* Added Vector#median_absolute_deviation\n* First implementation of Kolmogorov Smirnov test. Returns correct D value, but without Kolmogorov distribution isn't very useful.\n\n=== 1.0.1 / 2011-01-28\n\n* Updated spanish po.\n* Update distribution gem dependence. On Ruby 1.8.7, distribution 0.2.0 raises an error.\n\n=== 1.0.0 / 2011-01-27\n\n* Added Statsample::Analysis, a beautiful DSL to perform fast statistical analysis using statsample. See directory /examples\n* Created benchmarks directory \n* Removed Distribution module from statsample and moved to a gem. Changes on code to reflect new API\n* Optimized simple regression.  Better library detection\n* New 'should_with_gsl' to test methods with gsl. Refactored Factor::MAP\n* Almost complete GSL cleanup on Vector\n* Updated some doc on Vector\n* Used GSL::Matrix on Factor classes when available\n* SkillScaleAnalysis doesn't crash with one or more vectors with 0 variance\n* Modified examples using Statsample::Analysis\n* Simplified eigen calculations\n* Updated some examples. Added correlation matrix speed suite\n* Correlation matrix optimized. Better specs \n* Optimized correlation matrix. Use gsl matrix algebra or pairwise correlations depending on empiric calculated equations. See benchmarks/correlation_matrix.rb to see implementation of calculation \n* Moved tests fixtures from data to test/fixtures\n* Fixed some errors on tests\n* Bug fix: constant_se on binomial regression have an error \n* All test should work on ruby 1.9.3 \n* New Vector.[] and Vector.new_scale\n* Detect linearly dependent predictors on OLS. \n\n=== 0.18.0 / 2011-01-07\n* New Statsample.load_excel \n* New Statsample.load_csv\n* Statsample::Dataset#[] accepts an array of fields and uses clone\n* New Dataset#correlation_matrix  and Statsample::Dataset#covariance_matrix\n* Statsample::Dataset.filter add labels to vectors\n* Principal Components generation complete on PCA (covariance matrix prefered)\n* Added note on Statsample::Factor::PCA about erratic signs on eigenvalues,\n* Statsample::Factor::PCA.component_matrix calculated different for covariance matrix\n* Improved summary for PCA using covariance matrix\n* New attribute :label_angle for Statsample::Graph::Boxplot\n* Fixed Scatterplots scaling problems\n* New attributes for Scatterplots: groups, minimum_x, minimum_y, maximum_x, \n* New Statsample::Multiset#union allows to create a new dataset based on a m\n* New Statsample::Multiset#each to traverse through datasets\n* Bug fix: Vector#standarized and Vector#percentile crash on nil data\n* Bug fix: Vector#mean and Vector#sd crash on data without valid values\n* Modified methods names on Statsample::Factor::PCA : feature_vector to feature_matrix, data_transformation to principal_components\n* Added Statsample::Vector.vector_centered\n* Factor::MAP.with_dataset() implemented \n* Bug fix: Factor::MAP with correlation matrix with non-real eigenvalues crashes * Added documentation for Graph::Histogram \n* Added MPA to Reliability::MultiScaleAnalysis\n* Added custom names for returned vectors and datasets \n* Updated spanish traslation \n* Graph::Histogram updated. Custom x and y max and min, optional normal distribution drawing \n* Updated Histogram class, with several new methods compatibles with GSL::Histogram\n\n=== 0.17.0 / 2010-12-09\n* Added Statsample::Graph::Histogram and Statsample::Graph::Boxplot\n* Added Statsample::Reliability::SkillScaleAnalysis for analysis of skill based scales.\n* Delete combination and permutation clases. Backport for ruby 1.8.7 widely available\n* Deleted unused variables (thanks, ruby-head)\n\n=== 0.16.0 / 2010-11-13\n* Works on ruby 1.9.2 and HEAD. Updated Rakefile and manifest\n* Removed all graph based on Svg::Graph. \n* First operative version of Graph with Rubyvis\n* Corrected bug on Distribution::Normal.cdf. \n* Added reference on references.txt\n* Ruby-based random gaussian distribution generator when gsl not available\n* Added population average deviation [Al Chou]\n\n=== 0.15.1 / 2010-10-20\n* Statsample::Excel and Statsample::PlainText add name to vectors equal to field name \n* Statsample::Dataset.delete_vector accept multiple fields.\n* Statsample::Dataset.dup_only_valid allows duplication of specific fields \n* ScaleAnalysis doesn't crash on one-item scales \n* Updated references\n\n=== 0.15.0 / 2010-09-07\n* Added class Statsample::Reliability::ICC for calculation of Intra-class correlation (Shrout & Fleiss, 1979; McGraw & Wong, 1996). Tested with SPSS and R values.\n* References: Updated and standarized references on many classes. Added grab_references.rb script, to create a list of references for library\n* Added Spearman-Brown prophecy on Reliability module\n* Distribution::F uses Gsl when available\n* Added mean r.p.b. and item sd on Scale Analysis\n* Corrected bug on Vector.ary_method and example of Anova Two Way using vector.  \n\n\n=== 0.14.1 / 2010-08-18\n\n* Added extra information on $DEBUG=true. \n* Changed ParallelAnalysis: with_random_data parameters, bootstrap_method options are data and random, resolve bug related to number of factors to preserve, resolved bug related to original eigenvalues, can support failed bootstrap of data for Tetrachoric  correlation. \n* Optimized eigenpairs on Matrix when GSL is available. \n* Added test for parallel analysis using data bootstraping\n* Updated .pot and Manifest.txt\n* Added test for kmo(global and univariate), bartlett and anti-image. Kmo and Bartlett have test based on Dziuban and Shirkey with correct results\n* Complete set of test to test if a correlation matrix is appropriate for factor analysis: test of sphericity, KMO and anti-image (see Dziuban and Shirkey, 1974)\n* Updated Parallel Analysis to work on Principal Axis Analysis based on O'Connors formulae\n* Added reference for Statsample::Factor::MAP\n\n=== 0.14.0 / 2010-08-16\n* Added Statsample::Factor::MAP, to execute Velicer's (1976) MAP to determine the number of factors to retain on EFA \n* Bug fix on test suite on Ruby 1.8.7\n* Horn's Parallel Analysis operational and tested for pure random data\n* Fixed bug on Excel writer on Ruby1.9 (frozen string on header raises an error). \n* Extra information on Factorial Analysis on summaries\n* Fixed bug on Factor::Rotation when used ::Matrix without field method. \n* Added Vector#vector_percentil method\n* Summaries for PCA, Rotation, MultiScale and ScaleAnalysis created or improved. \n* Factor::PCA could have rotation and parallel analysis on summary.\n* Cronbach's alpha from covariance matrix raise an error on size<2 \n* MultiScaleAnalysis could have Parallel Analysis on summary.\n* Added Chi Square test\n* Added new information on README.txt\n\n=== 0.13.1 / 2010-07-03\n\n* Rserve extensions for dataset and vector operational\n* On x86_64, variance from gsl is not exactly equal to sum of variance-covariance on Statsample::Reliability::Scale, but in delta 1e-10\n* Updated README.txt\n* Reliability::ScaleAnalysis uses covariance matrix for 'if deleted' calculations to optimize memory and speed. Test for 'if deleted' statistics\n* More string translated. Added dependency on tetrachoric on parallel analysis\n\n=== 0.13.0 / 2010-06-13\n\n* Polychoric and Tetrachoric moved to gem statsample-bivariate-extension\n* All classes left with summary method include Summarizable now. Every method which return localizable string is now parsed with _()\n* Correct implementation of Reliability::MultiScaleAnalysis. \n* Spanish translation for Mann-Whitney's U\n* Added example for Mann-Whitney's U test\n* Better summary for Mann-Whitney's U Test\n* Added Statsample::Bivariate::Pearson class to retrieve complete analysis for r correlations\n* Bug fix on DominanceAnalysis::Bootstrap\n\n=== 0.12.0 / 2010-06-09\n\n* Modified Rakefile to remove dependencies based on C extensions. These are moved to statsample-optimization\n* T test with unequal variance fixed on i686\n* API Change: Renamed Reliability::ItemAnalysis and moved to independent file \n* New Reliability::MultiScaleAnalysis for easy analysis of scales on a same survey, includind reliability, correlation matrix and Factor Analysis\n* Updated README to reflect changes on Reliability module\n* SvgGraph works with reportbuilder. \n* Added methods on Polychoric based on Olsson(1979): the idea is estimate using second derivatives.\n* Distribution test changed (reduced precision on 32 bits system\n\n=== 0.11.2 / 2010-05-05\n* Updated dependency for 'extendedmatrix' to 0.2 (Matrix#build method)\n\n=== 0.11.1 / 2010-05-04\n* Removed Matrix almost all Matrix extensions and replaced by dependency on 'extendmatrix' gem\n* Added dependency to gsl >=1.12.109. Polychoric with joint method fails without this explicit dependency\n=== 0.11.0 / 2010-04-16\n<b>New features:</b>\n* Added Statsample::Anova::TwoWay and Statsample::Anova::TwoWayWithVectors\n* Added Statsample.clone_only valid and Statsample::Dataset.clone_only_valid, for cheap copy on already clean vectors\n<b>Optimizations and bug fix</b> \n* Removed library statistics2 from package. Used gem statistics2 instead, because have a extension version\n* Added example for Reliability class\n* Bug fix on Statsample::DominanceAnalysis\n\n=== 0.10.0 / 2010-04-13\n\n<b>API modifications</b>\n* Refactoring of Statsample::Anova module. \n  * Statsample::Anova::OneWay :implementation of generic ANOVA One-Way, used by Multiple Regression, for example.\n  * Statsample::Anova::OneWayWithVectors: implementation of ANOVA One-Way to test differences of means.\n\n<b>New features</b>\n* New Statsample::Factor::Parallel Analysis, to performs Horn's 'parallel analysis' to a PCA, to adjust for sample bias on retention of components.\n* New Statsample.only_valid_clone and Statsample::Dataset.clone, which allows to create shallow copys of valid vector and datasets. Used by correlation matrix methods to optimize calculations\n* New module Statsample::Summarizable, which add GetText and ReportBuilder support to classes. Better summaries for Vector, Dataset, Crosstab, PrincipalAxis, PCA and Regression::Multiple classes\n\n<b>Optimizations and bug fix</b>\n\n* Refactoring of Statsample::Regression::Multiple classes. Still needs works\n* Bug fix on Statsample::Factor::PCA and Statsample::Factor::PrincipalAxis\n* Bug fix on Statsample::Bivariate::Polychoric.new_with_vectors. Should be defined class method, no instance method.\n* Optimized correlation and covariance matrix. Only calculates the half of matrix and the other half is returned from cache\n* More tests coverage. RCOV Total: 82.51% , Code: 77.83%\n\n=== 0.9.0 / 2010-04-04\n* New Statsample::Test::F. Anova::OneWay subclasses it and Regression classes uses it.\n=== 0.8.2 / 2010-04-01\n* Statsample::PromiseAfter replaced by external package DirtyMemoize [http://rubygems.org/gems/dirty-memoize]\n=== 0.8.1 / 2010-03-29\n* Fixed Regression summaries\n=== 0.8.0 / 2010-03-29\n* New Statsample::Test::T module, with classes and methods to do Student's t tests for one and two samples. \n* Statsample::PromiseAfter module to set a number of variables without explicitly call the compute or iterate method\n* All tests ported to MiniUnit\n* Directory 'demo' renamed to 'examples'\n* Bug fix on report_building on Statsample::Regression::Multiple classes\n\n=== 0.7.0 / 2010-03-25\n* Ported to ReportBuilder 1.x series\n* Implementation of ruby based covariance and correlation changed to a clearer code\n* Statsample::Vector#svggraph_frequencies accepts IO\n* Some test ported to Miniunit\n* CSV on Ruby1.8 uses FasterCSV\n\n=== 0.6.7 / 2010-03-23\n* Bug fix: dependency on ReportBuilder should be set to \"~>0.2.0\", not \"0.2\"\n=== 0.6.6 / 2010-03-22\n* Set ReportBuilder dependency to '0.2.~' version, because future API break\n* Removed Alglib dependency\n* Factor::PrincipalAxis and Factor::PCA reworked\n* Standarization of documentation on almost every file\n* New Statsample::Test::Levene, to test equality of variances\n* Constant HAS_GSL replaced by Statsample.has_gsl?\n* PCA and Principal Axis test based on R and SPSS results\n* Bug fix on test_dataset.rb / test_saveload\n* Added Rakefile\n* Demos for levene, Principal Axis\n\n=== 0.6.5 / 2010-02-24\n\n* Bug fix on test: Use tempfile instead of tempdir\n* Multiple Regression: Calculation of constant standard error , using covariance matrix.\n* Calculation of R^2_yx and P^2_yx for Regresion on Multiple Dependents variables\n* Dominance Analysis could use Correlation or Covariance Matrix as input.\n* Dominance Analysis extension to multiple dependent variables (Azen & Budescu, 2006)\n* Two-step estimate of Polychoric correlation uses minimization gem, so could be executed without rb-gsl\n\n\n=== 0.6.4 / 2010-02-19\n* Dominance Analysis and Dominance Analysis Bootstrap allows multivariate dependent analysis. \n* Test suite for Dominance Analysis, using Azen and Budescu papers as references\n* X^2 for polychoric correlation\n\n=== 0.6.3 / 2010-02-15\n* Statsample::Bivariate::Polychoric have joint estimation.\n* Some extra documentation and bug fixs\n\n=== 0.6.2 / 2010-02-11\n* New Statsample::Bivariate::Polychoric. For implement: X2 and G2\n* New matrix.rb, for faster development of Contingence Tables and Correlation Matrix\n\n=== 0.6.1 / 2010-02-08\n* Bug fix on DominanceAnalysis summary for Ruby1.9\n* Some extra documentation\n=== 0.6.0 / 2010-02-05\n* New Statsample::Factor module. Include classes for extracting factors (Statsample::Factor::PCA and  Statsample::Factor::PrincipalAxis) and rotate component matrix  ( Statsample::Factor::Rotation subclasses). For now, only orthogonal rotations\n* New Statsample::Dataset.crosstab_with_asignation, Statsample::Dataset.one_to_many\n* New class Statsample::Permutation to produce permutations of a given array\n* New class Statsample::Histogram, with same interface as GSL one \n* New class Statsample::Test::UMannWhitney, to perform Mann-Whitney's U test. Gives z based and exact calculation of probability\n* Improved support for ReportBuilder\n* Statsample::Codification module reworked\n* Fixed bugs on Dominance Analysis classes\n* Fixed bugs on Statsample::Vector.kurtosis and Statsample::Vector.skew \n\n=== 0.5.1 / 2009-10-06\n\n* New class Statsample::Bivariate::Tetrachoric, for calculation of tetrachoric correlations. See http://www.john-uebersax.com/stat/tetra.htm for information.\n* New Statsample::Dataset.merge\n* New Statsample::Vector.dichotomize\n* New ItemReliability.item_difficulty_analysis\n* New module Statsample::SPSS, to export information to SPSS. For now, only tetrachoric correlation matrix are provided\n* All SpreadSheet based importers now accept repeated variable names and renames they on the fly\n* MultipleRegression::BaseEngine moved to new file\n* Bug fix for MultipleRegression::GslEngine checks for Alglib, not GSL\n\n=== 0.5.0 / 2009-09-26\n* Vector now uses a Hash as a third argument\n* Tested on Ruby 1.8.6, 1.8.7 and 1.9.1 with multiruby\n\n=== 0.4.1 / 2009-09-12\n* More methods and usage documentation\n* Logit tests\n* Bug fix: rescue for requires doesn't specify LoadError\n* Binomial::BaseEngine new methods: coeffs_se, coeffs, constant and constant_se\n\n=== 0.4.0 / 2009-09-10\n* New Distribution module, based on statistics2.rb by Shin-ichiro HARA. Replaces all instances of GSL distributions pdf and cdf calculations for native calculation.\n* New Maximum Likehood Estimation for Logit, Probit and Normal Distribution using Von Tessin(2005) algorithm. See MLE class and subclasses for more information.\n* New Binomial regression subclasses (Logit and Probit), usign MLE class\n* Added tests for gsl, Distribution, MLE and Logit\n* Bug fix on svggraph.rb. Added check_type for scale graphics\n* Bug fix on gdchart. Replaced old Nominal, Ordinal and Scale for Vector\n\n=== 0.3.4 / 2009-08-21\n* Works with statsample-optimization 2.0.0\n* Vector doesn't uses delegation. All methods are part of Vector\n* Added Combination. Generates all combination of n elements taken r at a time\n* Bivariate#prop_pearson now can uses as a second parameter :both, :left, :right, :positive or :negative\n* Added LICENSE.txt\n\n=== 0.3.3 / 2009-08-11\n* Added i18n support. For now, only spanish translation available\n* Bug fix: Test now load libraries on ../lib path\n* Excel and CSV importers automatically modify type of vector to Scale when all data are numbers or nils values\n\n=== 0.3.2 / 2009-08-04\n\n* Added Regression::Multiple::GslEngine\n* Added setup.rb\n* Crosstab#row_label and #column_name\n* DominanceAnalysis and DominanceAnalysisBootstrap uses Dataset#labels for Vector names.\n\n=== 0.3.1 / 2009-08-03\n\n* Name and logic of Regression classes changed. Now, you have Regression::Simple class and Regression::Multiple module with two engines: RubyEngine and AlglibEngne\n* New Crosstab#summary\n\n=== 0.3.0 / 2009-08-02\n\n* Statsample renamed to Statsample\n* Optimization extension goes to another gem: ruby-statsample-optimization\n\n=== 0.2.0 / 2009-08-01\n\n* One Way Anova on Statsample::Anova::OneWay\n* Dominance Analysis!!!! The one and only reason to develop a Multiple Regression on pure ruby.\n* Multiple Regression on Multiple Regression module. Pairwise (pure ruby) or MultipleRegressionPairwise and Listwise (optimized) on MultipleRegressionAlglib and \n* New Dataset#to_gsl_matrix, #from_to,#[..],#bootstrap,#vector_missing_values, #vector_count_characters, #each_with_index, #collect_with_index\n* New Vector#box_cox_transformation\n* Module Correlation renamed to Bivariate\n* Some fancy methods and classes to create Summaries\n* Some documentation about Algorithm used on doc_latex\n* Deleted 'distributions' extension. Ruby/GSL has all the pdf and cdf you ever need.\n* Tests work without any dependency. Only nags about missing deps. \n* Test for MultipleRegression, Anova, Excel, Bivariate.correlation_matrix and many others \n\n=== 0.1.9 / 2009-05-22\n\n* Class Vector: new method vector_standarized_pop, []=, min,max\n* Class Dataset: global variable $RUBY_SS_ROW stores the row number on each() and related methods. dup() with argument returns a copy of the dataset only for given fields. New methods: standarize, vector_mean, collect, verify,collect_matrix\n* Module Correlation: new methods covariance, t_pearson, t_r, prop_pearson, covariance_matrix, correlation_matrix, correlation_probability_matrix\n* Module SRS: New methods estimation_n0 and estimation_n\n* Module Reliability: new ItemCharacteristicCurve class\n* New HtmlReport class\n* New experimental SPSS Class. \n* Converters: Module CSV with new options. Added write() method for GGobi module \n* New Mx exporter (http://www.vcu.edu/mx/)\n* Class SimpleRegression: new methods standard error\n\n* Added tests for regression and reliability, Vector#vector_mean, Dataset#dup (partial)  and Dataset#verify\n\n\n=== 0.1.8 / 2008-12-10\n* Added Regression and Reliability modules\n* Class Vector: added methods vector_standarized, recode, inspect, ranked\n* Class Dataset: added methods vector_by_calculation, vector_sum, filter_field\n* Module Correlation: added methods like spearman, point biserial and tau-b\n* Added tests for Vector#ranked, Vector#vector_standarized,  Vector#sum_of_squared_deviation, Dataset#vector_by_calculation, Dataset#vector_sum, Dataset#filter_field and various test for Correlation module\n* Added demos: item_analysis and sample_test\n\n=== 0.1.7 / 2008-10-1\n* New module for codification\n* ...\n=== 0.1.6 / 2008-09-26\n* New modules for SRS and stratified sampling\n* Statsample::Database for read and write onto databases.\n  You could use Database and CSV on-tandem for mass-editing and reimport\n  of databases\n\n=== 0.1.5 / 2008-08-29\n* New extension statsampleopt for optimizing some functions on Statsample submodules\n* New submodules Correlation and Test\n\n=== 0.1.4 / 2008-08-27\n\n* New extension, with cdf functions for\n  chi-square, t, gamma and normal distributions. \n  Based on dcdflib (http://www.netlib.org/random/)\n  Also, has a function to calculate the tail for a noncentral T distribution\n\n=== 0.1.3 / 2008-08-22\n\n* Operational versions of Vector, Dataset, Crosstab and Resample\n* Read and write CSV files\n* Calculate chi-square for 2 matrixes\n\n=== 0.1.1 - 0.1.2 / 2008-08-18\n\n* Included several methods on Ruby::Type classes\n* Organized dirs with sow\n\n\n=== 0.1.0 / 2008-08-12\n\n* First version.\n\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2009-2014, Claudio Bustos\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Manifest.txt",
    "content": ".travis.yml\nGemfile\nGemfile.lock\nHistory.txt\nLICENSE.txt\nManifest.txt\nREADME.md\nRakefile\nbenchmarks/correlation_matrix_15_variables.rb\nbenchmarks/correlation_matrix_5_variables.rb\nbenchmarks/correlation_matrix_methods/correlation_matrix.ds\nbenchmarks/correlation_matrix_methods/correlation_matrix.html\nbenchmarks/correlation_matrix_methods/correlation_matrix.rb\nbenchmarks/correlation_matrix_methods/correlation_matrix.xls\nbenchmarks/correlation_matrix_methods/correlation_matrix_gsl_ruby.ods\nbenchmarks/correlation_matrix_methods/correlation_matrix_with_graphics.ods\nbenchmarks/correlation_matrix_methods/results.ds\nbenchmarks/factor_map.rb\nbenchmarks/helpers_benchmark.rb\ndata/locale/es/LC_MESSAGES/statsample.mo\ndoc_latex/manual/equations.tex\nexamples/boxplot.rb\nexamples/correlation_matrix.rb\nexamples/dataset.rb\nexamples/dominance_analysis.rb\nexamples/dominance_analysis_bootstrap.rb\nexamples/histogram.rb\nexamples/icc.rb\nexamples/levene.rb\nexamples/multiple_regression.rb\nexamples/multivariate_correlation.rb\nexamples/parallel_analysis.rb\nexamples/polychoric.rb\nexamples/principal_axis.rb\nexamples/reliability.rb\nexamples/scatterplot.rb\nexamples/t_test.rb\nexamples/tetrachoric.rb\nexamples/u_test.rb\nexamples/vector.rb\nexamples/velicer_map_test.rb\ngrab_references.rb\nlib/spss.rb\nlib/statsample.rb\nlib/statsample/analysis.rb\nlib/statsample/analysis/suite.rb\nlib/statsample/analysis/suitereportbuilder.rb\nlib/statsample/anova.rb\nlib/statsample/anova/contrast.rb\nlib/statsample/anova/oneway.rb\nlib/statsample/anova/twoway.rb\nlib/statsample/bivariate.rb\nlib/statsample/bivariate/pearson.rb\nlib/statsample/codification.rb\nlib/statsample/converter/csv.rb\nlib/statsample/converter/spss.rb\nlib/statsample/converters.rb\nlib/statsample/crosstab.rb\nlib/statsample/dataset.rb\nlib/statsample/dominanceanalysis.rb\nlib/statsample/dominanceanalysis/bootstrap.rb\nlib/statsample/factor.rb\nlib/statsample/factor/map.rb\nlib/statsample/factor/parallelanalysis.rb\nlib/statsample/factor/pca.rb\nlib/statsample/factor/principalaxis.rb\nlib/statsample/factor/rotation.rb\nlib/statsample/graph.rb\nlib/statsample/graph/boxplot.rb\nlib/statsample/graph/histogram.rb\nlib/statsample/graph/scatterplot.rb\nlib/statsample/histogram.rb\nlib/statsample/matrix.rb\nlib/statsample/multiset.rb\nlib/statsample/regression.rb\nlib/statsample/regression/multiple.rb\nlib/statsample/regression/multiple/alglibengine.rb\nlib/statsample/regression/multiple/baseengine.rb\nlib/statsample/regression/multiple/gslengine.rb\nlib/statsample/regression/multiple/matrixengine.rb\nlib/statsample/regression/multiple/rubyengine.rb\nlib/statsample/regression/simple.rb\nlib/statsample/reliability.rb\nlib/statsample/reliability/icc.rb\nlib/statsample/reliability/multiscaleanalysis.rb\nlib/statsample/reliability/scaleanalysis.rb\nlib/statsample/reliability/skillscaleanalysis.rb\nlib/statsample/resample.rb\nlib/statsample/rserve_extension.rb\nlib/statsample/shorthand.rb\nlib/statsample/srs.rb\nlib/statsample/test.rb\nlib/statsample/test/bartlettsphericity.rb\nlib/statsample/test/chisquare.rb\nlib/statsample/test/f.rb\nlib/statsample/test/kolmogorovsmirnov.rb\nlib/statsample/test/levene.rb\nlib/statsample/test/t.rb\nlib/statsample/test/umannwhitney.rb\nlib/statsample/test/wilcoxonsignedrank.rb\nlib/statsample/vector.rb\nlib/statsample/vector/gsl.rb\nlib/statsample/version.rb\npo/es/statsample.mo\npo/es/statsample.po\npo/statsample.pot\nreferences.txt\nsetup.rb\ntest/fixtures/bank2.dat\ntest/fixtures/correlation_matrix.rb\ntest/fixtures/hartman_23.matrix\ntest/fixtures/repeated_fields.csv\ntest/fixtures/stock_data.csv\ntest/fixtures/test_csv.csv\ntest/fixtures/test_xls.xls\ntest/fixtures/tetmat_matrix.txt\ntest/fixtures/tetmat_test.txt\ntest/helpers_tests.rb\ntest/test_analysis.rb\ntest/test_anova_contrast.rb\ntest/test_anovaoneway.rb\ntest/test_anovatwoway.rb\ntest/test_anovatwowaywithdataset.rb\ntest/test_anovawithvectors.rb\ntest/test_bartlettsphericity.rb\ntest/test_bivariate.rb\ntest/test_codification.rb\ntest/test_crosstab.rb\ntest/test_csv.rb\ntest/test_dataset.rb\ntest/test_dominance_analysis.rb\ntest/test_factor.rb\ntest/test_factor_map.rb\ntest/test_factor_pa.rb\ntest/test_ggobi.rb\ntest/test_gsl.rb\ntest/test_histogram.rb\ntest/test_matrix.rb\ntest/test_multiset.rb\ntest/test_regression.rb\ntest/test_reliability.rb\ntest/test_reliability_icc.rb\ntest/test_reliability_skillscale.rb\ntest/test_resample.rb\ntest/test_rserve_extension.rb\ntest/test_srs.rb\ntest/test_statistics.rb\ntest/test_stest.rb\ntest/test_stratified.rb\ntest/test_test_f.rb\ntest/test_test_kolmogorovsmirnov.rb\ntest/test_test_t.rb\ntest/test_umannwhitney.rb\ntest/test_vector.rb\ntest/test_wilcoxonsignedrank.rb\ntest/test_xls.rb\nweb/Rakefile\n"
  },
  {
    "path": "README.md",
    "content": "# Statsample\n\nHomepage :: https://github.com/sciruby/statsample\n\n[![Build Status](https://travis-ci.org/clbustos/statsample.svg?branch=master)](https://travis-ci.org/clbustos/statsample)\n[![Gem Version](https://badge.fury.io/rb/statsample.svg)](http://badge.fury.io/rb/statsample)\n## DESCRIPTION\n\nA suite for basic and advanced statistics on Ruby. Tested on Ruby 2.1.1p76 (June 2014), 1.8.7, 1.9.1, 1.9.2 (April, 2010), ruby-head(June, 2011) and JRuby 1.4 (Ruby 1.8.7 compatible).\n\nInclude:\n* Descriptive statistics: frequencies, median, mean, standard error, skew, kurtosis (and many others).\n* Imports and exports datasets from and to Excel, CSV and plain text files.\n* Correlations: Pearson's r, Spearman's rank correlation (rho), point biserial, tau a, tau b and  gamma.  Tetrachoric and Polychoric correlation provides by +statsample-bivariate-extension+ gem.\n* Intra-class correlation\n* Anova: generic and vector-based One-way ANOVA and Two-way ANOVA, with contrasts for One-way ANOVA.\n* Tests: F, T, Levene, U-Mannwhitney.\n* Regression: Simple, Multiple (OLS), Probit  and Logit\n* Factorial Analysis: Extraction (PCA and Principal Axis), Rotation (Varimax, Equimax, Quartimax) and Parallel Analysis and Velicer's MAP test, for estimation of number of factors.\n* Reliability analysis for simple scale and a DSL to easily analyze multiple scales using factor analysis and correlations, if you want it.\n* Basic time series support\n* Dominance Analysis, with multivariate dependent and bootstrap (Azen & Budescu)\n* Sample calculation related formulas\n* Structural Equation Modeling (SEM), using R libraries +sem+ and +OpenMx+\n* Creates reports on text, html and rtf, using ReportBuilder gem\n* Graphics: Histogram, Boxplot and Scatterplot\n\n## Principles\n\n* Software Design: \n  * One module/class for each type of analysis\n  * Options can be set as hash on initialize() or as setters methods\n  * Clean API for interactive sessions\n  * summary() returns all necessary informacion for interactive sessions\n  * All statistical data available though methods on objects\n  * All (important) methods should be tested. Better with random data.\n* Statistical Design\n  * Results are tested against text results, SPSS and R outputs.\n  * Go beyond Null Hiphotesis Testing, using confidence intervals and effect sizes when possible\n  * (When possible) All references for methods are documented, providing sensible information on documentation \n\n## Features\n\n* Classes for manipulation and storage of data:\n  * Statsample::Vector: An extension of an array, with statistical methods like sum, mean and standard deviation\n  * Statsample::Dataset: a group of Statsample::Vector, analog to a excel spreadsheet or a dataframe on R. The base of almost all operations on statsample. \n  * Statsample::Multiset: multiple datasets with same fields and type of vectors\n* Anova module provides generic Statsample::Anova::OneWay and vector based Statsample::Anova::OneWayWithVectors. Also you can create contrast using Statsample::Anova::Contrast\n* Module Statsample::Bivariate provides covariance and pearson, spearman, point biserial, tau a, tau b, gamma, tetrachoric (see Bivariate::Tetrachoric) and polychoric (see Bivariate::Polychoric) correlations. Include methods to create correlation and covariance matrices\n* Multiple types of regression.\n  * Simple Regression :  Statsample::Regression::Simple\n  * Multiple Regression: Statsample::Regression::Multiple\n  * Logit Regression:    Statsample::Regression::Binomial::Logit\n  * Probit Regression:    Statsample::Regression::Binomial::Probit\n* Factorial Analysis algorithms on Statsample::Factor module.\n  * Classes for Extraction of factors: \n    * Statsample::Factor::PCA\n    * Statsample::Factor::PrincipalAxis\n  * Classes for Rotation of factors: \n    * Statsample::Factor::Varimax\n    * Statsample::Factor::Equimax\n    * Statsample::Factor::Quartimax\n  * Classes for calculation of factors to retain\n    * Statsample::Factor::ParallelAnalysis performs Horn's 'parallel analysis' to a principal components analysis to adjust for sample bias in the retention of components.\n    * Statsample::Factor::MAP performs Velicer's Minimum Average Partial (MAP) test, which retain components as long as the variance in the correlation matrix represents systematic variance.\n* Dominance Analysis. Based on Budescu and Azen papers, dominance analysis is a method to analyze the relative importance of one predictor relative to another on multiple regression\n  * Statsample::DominanceAnalysis class can report dominance analysis for a sample, using uni or multivariate dependent variables\n  * Statsample::DominanceAnalysis::Bootstrap can execute bootstrap analysis to determine dominance stability, as recomended by  Azen & Budescu (2003) link[http://psycnet.apa.org/journals/met/8/2/129/]. \n* Module Statsample::Codification, to help to codify open questions\n* Converters to import and export data:\n  * Statsample::Database : Can create sql to create tables, read and insert data\n  * Statsample::CSV : Read and write CSV files\n  * Statsample::Excel : Read and write Excel files\n  * Statsample::Mx    : Write Mx Files\n  * Statsample::GGobi : Write Ggobi files\n* Module Statsample::Crosstab provides function to create crosstab for categorical data\n* Module Statsample::Reliability provides functions to analyze scales with psychometric methods. \n  * Class Statsample::Reliability::ScaleAnalysis provides statistics like mean, standard deviation for a scale, Cronbach's alpha and standarized Cronbach's alpha, and for each item: mean, correlation with total scale, mean if deleted, Cronbach's alpha is deleted.\n  * Class Statsample::Reliability::MultiScaleAnalysis provides a DSL to easily analyze reliability of multiple scales and retrieve correlation matrix and factor analysis of them.\n  * Class Statsample::Reliability::ICC provides intra-class correlation, using Shrout & Fleiss(1979) and McGraw & Wong (1996) formulations.\n* Module Statsample::SRS (Simple Random Sampling) provides a lot of functions to estimate standard error for several type of samples\n* Module Statsample::Test provides several methods and classes to perform inferencial statistics\n  * Statsample::Test::BartlettSphericity\n  * Statsample::Test::ChiSquare\n  * Statsample::Test::F\n  * Statsample::Test::KolmogorovSmirnov (only D value)\n  * Statsample::Test::Levene\n  * Statsample::Test::UMannWhitney\n  * Statsample::Test::T\n  * Statsample::Test::WilcoxonSignedRank\n* Module Graph provides several classes to create beautiful graphs using rubyvis\n  * Statsample::Graph::Boxplot\n  * Statsample::Graph::Histogram\n  * Statsample::Graph::Scatterplot\n* Gem <tt>bio-statsample-timeseries</tt> provides module Statsample::TimeSeries with support for time series, including ARIMA estimation using Kalman-Filter. \n* Gem <tt>statsample-sem</tt> provides a DSL to R libraries +sem+ and +OpenMx+\n* Gem <tt>statsample-glm</tt> provides you with GML method, to work with Logistic, Poisson and Gaussian regression ,using ML or IRWLS. \n* Close integration with gem <tt>reportbuilder</tt>, to easily create reports on text, html and rtf formats.\n\n# Examples of use:\n\nSee the [examples folder](https://github.com/clbustos/statsample/tree/master/examples/) too.\n\n## Boxplot\n\n```ruby\nrequire 'statsample'\n\nss_analysis(Statsample::Graph::Boxplot) do \n  n=30\n  a=rnorm(n-1,50,10)\n  b=rnorm(n, 30,5)\n  c=rnorm(n,5,1)\n  a.push(2)\n  boxplot(:vectors=>[a,b,c], :width=>300, :height=>300, :groups=>%w{first first second}, :minimum=>0)\nend\nStatsample::Analysis.run # Open svg file on *nix application defined\n```\n\n## Correlation matrix\n\n```ruby\nrequire 'statsample'\n# Note R like generation of random gaussian variable\n# and correlation matrix\n\nss_analysis(\"Statsample::Bivariate.correlation_matrix\") do\n  samples=1000\n  ds=data_frame(\n    'a'=>rnorm(samples), \n    'b'=>rnorm(samples),\n    'c'=>rnorm(samples),\n    'd'=>rnorm(samples))\n  cm=cor(ds) \n  summary(cm)\nend\n\nStatsample::Analysis.run_batch # Echo output to console\n```\n\n# Requirements\n\nOptional: \n\n* Plotting: gnuplot and rbgnuplot, SVG::Graph\n* Factorial analysis and polychorical correlation(joint estimate and polychoric series): gsl library and rb-gsl (https://rubygems.org/gems/rb-gsl/). You should install it using <tt>gem install rb-gsl</tt>. \n\n*Note*: Use gsl 1.12.109 or later.\n\n# Resources\n\n* Source code on github :: http://github.com/clbustos/statsample\n* Docs :: http://statsample.apsique.cl/\n* Bug report and feature request :: http://github.com/clbustos/statsample/issues\n* E-mailing list :: http://groups.google.com/group/statsample\n\n# Installation\n\n```bash\n$ sudo gem install statsample\n```\n\nOn *nix, you should install statsample-optimization to retrieve gems gsl, statistics2 and a C extension to speed some methods. \n\nThere are available precompiled version for Ruby 1.9 on x86, x86_64 and mingw32 archs.\n\n```bash\n$ sudo gem install statsample-optimization\n```\n\nIf you use Ruby 1.8, you should compile statsample-optimization, usign parameter <tt>--platform ruby</tt>\n\n```bash\n$ sudo gem install statsample-optimization --platform ruby\n```\n\nIf you need to work on Structural Equation Modeling, you could see +statsample-sem+. You need R with +sem+ or +OpenMx+ [http://openmx.psyc.virginia.edu/] libraries installed\n\n```bash\n$ sudo gem install statsample-sem\n```\n\nAvailable setup.rb file\n\n```bash\nsudo gem ruby setup.rb\n```\n\n## License\n\nBSD-3 (See LICENSE.txt)\n\nCould change between version, without previous warning. If you want a specific license, just choose the version that you need.\n"
  },
  {
    "path": "Rakefile",
    "content": "#!/usr/bin/ruby\n# -*- ruby -*-\n# -*- coding: utf-8 -*-\n$:.unshift(File.dirname(__FILE__)+'/lib/')\n\nrequire 'rubygems'\nrequire 'statsample'\nrequire 'hoe'\nrequire 'rdoc'\n\nHoe.plugin :git\nHoe.plugin :doofus\ndesc \"Ruby Lint\"\ntask :lint do\n  executable=Config::CONFIG['RUBY_INSTALL_NAME']\n  Dir.glob(\"lib/**/*.rb\") {|f|\n    if !system %{#{executable} -w -c \"#{f}\"} \n        puts \"Error on: #{f}\"\n    end\n  }\nend\n\ntask :release do\nsystem %{git push origin master}\nend\n\ntask \"clobber_docs\" do\n  # Only to omit warnings\nend\ndesc \"Update pot/po files.\"\ntask \"gettext:updatepo\" do\n  require 'gettext/tools'\n  GetText.update_pofiles(\"statsample\", Dir.glob(\"{lib,bin}/**/*.{rb,rhtml}\"), \"statsample #{Statsample::VERSION}\")\nend\n\ndesc \"Create mo-files\"\ntask \"gettext:makemo\" do\n  require 'gettext/tools'\n  GetText.create_mofiles()\n  # GetText.create_mofiles(true, \"po\", \"locale\")  # This is for \"Ruby on Rails\".\nend\n\nh=Hoe.spec('statsample') do \n  self.version=Statsample::VERSION\n  self.urls=[\"https://github.com/clbustos/statsample\"]\n  #self.testlib=:minitest\n  self.readme_file = 'README.md'\n  self.urls = ['https://github.com/clbustos/statsample']\n  self.developer('Claudio Bustos', 'clbustos@gmail.com')\n  self.extra_deps << [\"spreadsheet\",\"~>0.6\"] <<  [\"reportbuilder\", \"~>1.4\"] << [\"minimization\", \"~>0.2.0\"] << [\"fastercsv\", \">0\"] << [\"dirty-memoize\", \"~>0.0\"] << [\"extendmatrix\",\"~>0.3.1\"] << [\"statsample-bivariate-extension\", \">0\"] << [\"rserve-client\"] << [\"rubyvis\"] << [\"distribution\"]\n  \n  self.extra_dev_deps << [\"hoe\",\"~>0\"] << [\"shoulda\",\"~>3\"] << [\"minitest\", \"~>2\"]  << [\"gettext\", \"~>0\"] << [\"mocha\", \"~>0\"] << [\"hoe-git\", \"~>0\"]\n  \n  self.clean_globs << \"test/images/*\" << \"demo/item_analysis/*\" << \"demo/Regression\"\n  self.post_install_message = <<-EOF\n***************************************************\nThanks for installing statsample.\n\nOn *nix, you could install statsample-optimization\nto retrieve gems gsl, statistics2 and a C extension\nto speed some methods.\n\n  $ sudo gem install statsample-optimization\n\nOn Ubuntu, install  build-essential and libgsl0-dev \nusing apt-get. Compile ruby 1.8 or 1.9 from \nsource code first.\n\n  $ sudo apt-get install build-essential libgsl0-dev\n\n\n*****************************************************\n  EOF\n  self.need_rdoc=false\nend\n\nif Rake.const_defined?(:RDocTask)\nRake::RDocTask.new(:docs) do |rd|\n  rd.main = h.readme_file\n  rd.options << '-d' if (`which dot` =~ /\\/dot/) unless\n    ENV['NODOT'] || Hoe::WINDOZE\n  rd.rdoc_dir = 'doc'\n  \n  rd.rdoc_files.include(\"lib/**/*.rb\")\n  rd.rdoc_files += h.spec.extra_rdoc_files\n  rd.rdoc_files.reject! {|f| f==\"Manifest.txt\"}\n  title = h.spec.rdoc_options.grep(/^(-t|--title)=?$/).first\n  if title then\n    rd.options << title\n  \n    unless title =~ /\\=/ then # for ['-t', 'title here']\n    title_index = spec.rdoc_options.index(title)\n    rd.options << spec.rdoc_options[title_index + 1]\n    end\n  else\n    title = \"#{h.name}-#{h.version} Documentation\"\n    title = \"#{h.rubyforge_name}'s \" + title if h.rubyforge_name != h.name\n    rd.options << '--title' << title\n  end\nend\n\nend\n\ndesc 'Publish rdocs with analytics support'\ntask :publicar_docs => [:clean] do\n#  ruby %{agregar_adsense_a_doc.rb}\n  path = File.expand_path(\"./doc.yaml\")\n  config = YAML.load(File.read(path))\n  host = \"#{config[\"user\"]}@#{config[\"host\"]}\"\n  \n  remote_dir = config[\"dir\"]\n  local_dir = h.local_rdoc_dir\n  Dir.glob(local_dir+\"/**/*\") {|file|\n    sh %{chmod 755 #{file}}\n  }\n  sh %{rsync #{h.rsync_args} #{local_dir}/ #{host}:#{remote_dir}}\nend\n\n# vim: syntax=Ruby\n"
  },
  {
    "path": "benchmarks/correlation_matrix_15_variables.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_benchmark.rb'))\n\nextend BenchPress\ncases=250\nvars=20\n\n\nname \"gsl matrix based vs. manual ruby correlation matrix (#{vars} vars, #{cases} cases)\"\nauthor 'Clbustos'\ndate '2011-01-18'\nsummary \"\nA correlation matrix could be constructed using matrix algebra or\nmannualy, calculating covariances, means and sd for each pair of vectors.\nIn this test, we test the calculation using #{vars} variables with \n#{cases} cases on each vector\n\"\n\nreps 200 #number of repetitions\n\nds=vars.times.inject({}) {|ac,v|\nac[\"x#{v}\"]=Statsample::Vector.new_scale(cases) {rand()}\nac\n}.to_dataset\n    \nmeasure \"Statsample::Bivariate.correlation_matrix_optimized\" do\n  Statsample::Bivariate.correlation_matrix_optimized(ds)\nend\n\nmeasure \"Statsample::Bivariate.correlation_matrix_pairwise\" do\n  Statsample::Bivariate.correlation_matrix_pairwise(ds)\nend\n"
  },
  {
    "path": "benchmarks/correlation_matrix_5_variables.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_benchmark.rb'))\n\nextend BenchPress\ncases=500\nvars=5\n\n\nname \"gsl matrix based vs. manual ruby correlation matrix (#{vars} vars, #{cases} cases)\"\nauthor 'Clbustos'\ndate '2011-01-18'\nsummary \"\nA correlation matrix could be constructed using matrix algebra or\nmannualy, calculating covariances, means and sd for each pair of vectors.\nIn this test, we test the calculation using #{vars} variables with \n#{cases} cases on each vector\n\"\n\nreps 200 #number of repetitions\n\n\nds=vars.times.inject({}) {|ac,v|\nac[\"x#{v}\"]=Statsample::Vector.new_scale(cases) {rand()}\nac\n}.to_dataset\n    \nmeasure \"Statsample::Bivariate.correlation_matrix_optimized\" do\n  Statsample::Bivariate.correlation_matrix_optimized(ds)\nend\n\nmeasure \"Statsample::Bivariate.correlation_matrix_pairwise\" do\n  Statsample::Bivariate.correlation_matrix_pairwise(ds)\nend\n"
  },
  {
    "path": "benchmarks/correlation_matrix_methods/correlation_matrix.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" >\n<title>Correlation matrix analysis</title>\n        <style>\n        body {\n          margin:0;\n          padding:1em;\n        }\n        table {\n          border-collapse: collapse;\n\n        }\n        table td {\n          border: 1px solid black;\n        }\n        .section {\n          margin:0.5em;\n        }\n        </style>\n\n</head><body>\n<h1>Correlation matrix analysis</h1><div id='toc'><div class='title'>List of contents</div>\n<ul>\n<li><a href='#toc_1'>Multiple reggresion of cases,vars,c_v on time_optimized</a></li>\n<ul>\n<li><a href='#toc_2'>ANOVA</a></li>\n</ul>\n<li><a href='#toc_3'>Multiple reggresion of cases,vars,c_v on time_pairwise</a></li>\n<ul>\n<li><a href='#toc_4'>ANOVA</a></li>\n</ul>\n</ul>\n</div>\n<div class='tot'><div class='title'>List of tables</div><ul><li><a href='#table_1'>ANOVA Table</a></li><li><a href='#table_2'>Beta coefficients</a></li><li><a href='#table_3'>ANOVA Table</a></li><li><a href='#table_4'>Beta coefficients</a></li></ul></div>\n  <div class='section'><h2>Multiple reggresion of cases,vars,c_v on time_optimized</h2><a name='toc_1'></a>\n    <p>Engine: Statsample::Regression::Multiple::RubyEngine</p>\n    <p>Cases(listwise)=63(63)</p>\n    <p>R=0.978844</p>\n    <p>R^2=0.958137</p>\n    <p>R^2 Adj=0.956008</p>\n    <p>Std.Error R=3.092024</p>\n    <p>Equation=4.031667 + 0.018039cases + 0.244790vars + 0.001197c_v</p>\n    <div class='section'><h3>ANOVA</h3><a name='toc_2'></a>\n      <a name='table_1'></a><table><caption>ANOVA Table</caption><thead><th>source</th><th>ss</th><th>df</th><th>ms</th><th>f</th><th>p</th></thead>\n<tbody>\n<tr><td>Regression</td><td>12910.098</td><td>3</td><td>4303.366</td><td>450.114</td><td>0.000</td></tr>\n<tr><td>Error</td><td>564.076</td><td>59</td><td>9.561</td><td></td><td></td></tr>\n<tr><td>Total</td><td>13474.174</td><td>62</td><td>4312.927</td><td></td><td></td></tr>\n</tbody>\n</table>\n\n    </div>\n    <a name='table_2'></a><table><caption>Beta coefficients</caption><thead><th>coeff</th><th>b</th><th>beta</th><th>se</th><th>t</th></thead>\n<tbody>\n<tr><td>Constant</td><td>4.031667</td><td>-</td><td>0.752604</td><td>5.356953</td></tr>\n<tr><td>cases</td><td>0.018039</td><td>0.381587</td><td>0.001961</td><td>9.200093</td></tr>\n<tr><td>vars</td><td>0.244790</td><td>0.224390</td><td>0.036055</td><td>6.789335</td></tr>\n<tr><td>c_v</td><td>0.001197</td><td>0.584174</td><td>0.000094</td><td>12.738410</td></tr>\n</tbody>\n</table>\n\n  </div>\n  <div class='section'><h2>Multiple reggresion of cases,vars,c_v on time_pairwise</h2><a name='toc_3'></a>\n    <p>Engine: Statsample::Regression::Multiple::RubyEngine</p>\n    <p>Cases(listwise)=63(63)</p>\n    <p>R=0.999637</p>\n    <p>R^2=0.999275</p>\n    <p>R^2 Adj=0.999238</p>\n    <p>Std.Error R=0.538365</p>\n    <p>Equation=-0.520303 + -0.000708cases + 1.234451vars + 0.000735c_v</p>\n    <div class='section'><h3>ANOVA</h3><a name='toc_4'></a>\n      <a name='table_3'></a><table><caption>ANOVA Table</caption><thead><th>source</th><th>ss</th><th>df</th><th>ms</th><th>f</th><th>p</th></thead>\n<tbody>\n<tr><td>Regression</td><td>23554.271</td><td>3</td><td>7851.424</td><td>27089.134</td><td>0.000</td></tr>\n<tr><td>Error</td><td>17.100</td><td>59</td><td>0.290</td><td></td><td></td></tr>\n<tr><td>Total</td><td>23571.372</td><td>62</td><td>7851.714</td><td></td><td></td></tr>\n</tbody>\n</table>\n\n    </div>\n    <a name='table_4'></a><table><caption>Beta coefficients</caption><thead><th>coeff</th><th>b</th><th>beta</th><th>se</th><th>t</th></thead>\n<tbody>\n<tr><td>Constant</td><td>-0.520303</td><td>-</td><td>0.131039</td><td>-3.970594</td></tr>\n<tr><td>cases</td><td>-0.000708</td><td>-0.011324</td><td>0.000341</td><td>-2.074007</td></tr>\n<tr><td>vars</td><td>1.234451</td><td>0.855546</td><td>0.006278</td><td>196.641087</td></tr>\n<tr><td>c_v</td><td>0.000735</td><td>0.271138</td><td>0.000016</td><td>44.912972</td></tr>\n</tbody>\n</table>\n\n  </div>\n</body></html>"
  },
  {
    "path": "benchmarks/correlation_matrix_methods/correlation_matrix.rb",
    "content": "# This test create a database to adjust the best algorithm\n# to use on correlation matrix\nrequire(File.expand_path(File.dirname(__FILE__)+'/../helpers_benchmark.rb'))\nrequire 'statsample'\nrequire 'benchmark'\n\ndef create_dataset(vars,cases) \n  ran=Distribution::Normal.rng\n  ds=vars.times.inject({}) {|ac,v|\n    ac[\"x#{v}\"]=Statsample::Vector.new_scale(cases) {ran.call}\n  ac\n  }.to_dataset\nend\n\ndef prediction_pairwise(vars,cases)\n\tStatsample::Bivariate.prediction_pairwise(vars,cases) / 10\nend\ndef prediction_optimized(vars,cases)\n\tStatsample::Bivariate.prediction_optimized(vars,cases) / 10\nend\n\n\n\nif !File.exists?(\"correlation_matrix.ds\") or File.mtime(__FILE__) > File.mtime(\"correlation_matrix.ds\")\nreps=100 #number of repetitions\nds_sizes=[5,10,30,50,100,150,200,500,1000]\nds_vars=[3,4,5,10,20,30,40]\n#ds_sizes=[5,10]\n#ds_vars=[3,5,20]\nrs=Statsample::Dataset.new(%w{cases vars time_optimized time_pairwise})\n\nds_sizes.each do |cases|\n  ds_vars.each do |vars|\n      ds=create_dataset(vars,cases)\n      time_optimized= Benchmark.realtime do\n        reps.times { \n        Statsample::Bivariate.correlation_matrix_optimized(ds) \n        ds.clear_gsl\n        }\n      end\n      \n      time_pairwise= Benchmark.realtime do\n        reps.times { \n        Statsample::Bivariate.correlation_matrix_pairwise(ds)\n        }\n      end\n      \n      puts \"Cases:#{cases}, vars:#{vars} -> opt:%0.3f (%0.3f) | pair: %0.3f (%0.3f)\" % [time_optimized, prediction_optimized(vars,cases), time_pairwise, prediction_pairwise(vars,cases)]\n      \n      rs.add_case({'cases'=>cases,'vars'=>vars,'time_optimized'=>Math.sqrt(time_optimized*1000),'time_pairwise'=>Math.sqrt(time_pairwise*1000)})\n    end\n  end\n  \nelse\n  rs=Statsample.load(\"correlation_matrix.ds\")\nend\n\n\nrs.fields.each {|f| rs[f].type=:scale}\n\nrs['c_v']=rs.collect {|row| row['cases']*row['vars']}\n\nrs.update_valid_data\nrs.save(\"correlation_matrix.ds\")\nStatsample::Excel.write(rs,\"correlation_matrix.xls\")\n\n\n\nrb=ReportBuilder.new(:name=>\"Correlation matrix analysis\")\n\nrb.add(Statsample::Regression.multiple(rs[['cases','vars','time_optimized','c_v']],'time_optimized', :digits=>6))\nrb.add(Statsample::Regression.multiple(rs[['cases','vars','time_pairwise','c_v']],'time_pairwise', :digits=>6))\n\n\nrb.save_html(\"correlation_matrix.html\")\n"
  },
  {
    "path": "benchmarks/factor_map.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_benchmark.rb'))\n\nextend BenchPress\n\n\nname \"Statsample::Factor::Map with and without GSL\"\nauthor 'Clbustos'\ndate '2011-01-18'\nsummary \"Velicer's MAP uses a lot of Matrix algebra. How much we can improve the timing using GSL?\n\"\n\nreps 20 #number of repetitions\n\nm=Matrix[ \n        [ 1, 0.846, 0.805, 0.859, 0.473, 0.398, 0.301, 0.382],\n        [ 0.846, 1, 0.881, 0.826, 0.376, 0.326, 0.277, 0.415],\n        [ 0.805, 0.881, 1, 0.801, 0.38, 0.319, 0.237, 0.345],\n        [ 0.859, 0.826, 0.801, 1, 0.436, 0.329, 0.327, 0.365],\n        [ 0.473, 0.376, 0.38, 0.436, 1, 0.762, 0.73, 0.629],\n        [ 0.398, 0.326, 0.319, 0.329, 0.762, 1, 0.583, 0.577],\n        [ 0.301, 0.277, 0.237, 0.327, 0.73, 0.583, 1, 0.539],\n        [ 0.382, 0.415, 0.345, 0.365, 0.629, 0.577, 0.539, 1]\n  ]\n  \nmap=Statsample::Factor::MAP.new(m)\n\n\nmeasure \"Statsample::Factor::MAP without GSL\" do\n  map.use_gsl=false\n  map.compute\nend\n\nmeasure \"Statsample::Factor::MAP with GSL\" do\n  map.use_gsl=true\n  map.compute\nend\n\n"
  },
  {
    "path": "benchmarks/helpers_benchmark.rb",
    "content": "$:.unshift(File.expand_path(File.dirname(__FILE__)+'/../lib/'))\n$:.unshift(File.expand_path(File.dirname(__FILE__)+'/'))\n\nrequire 'statsample'\nrequire 'bench_press'"
  },
  {
    "path": "doc_latex/manual/equations.tex",
    "content": "\\part{Equations}\n\\section{Convention}\n\\begin{align*}\nn &= \\text{sample size}\\\\\nN &= \\text{population size}\\\\\np &= \\text{proportion inside a sample}\\\\\nP &= \\text{proportion inside a population}\n\\end{align*}\n\\section{Ruby::Regression::Multiple}\n\nTo compute the standard error of coefficients, you obtain the estimated variance-covariance matrix of error.\n\nLet \\mathbf{X} be matrix of predictors data, including a constant column; \\mathbf{MSE} as mean square error; SSE as Sum of squares of errors; n the number of cases; p as number of predictors\n\n\\begin{equation}\n\\mathbf{MSE}=\\frac{SSE}{n-p-1}\n\\end{equation}\n\n\\begin{equation}\n\\mathbf{E}=(\\mathbf{X'}\\mathbf{X})^-1\\mathbf{MSE}\n\\end{equation}\n\nThe root squares of diagonal should be standard errors\n\n\n\\section{Ruby::SRS}\nFinite Poblation correction is used on standard error calculation on poblation below 10.000. Function \n\\begin{verbatim}\nfpc_var(sam,pop)\n\\end{verbatim}\ncalculate FPC for variance with\n\\begin{equation}\nfpc_{var} = \\frac{N-n} {N-1}\n\\end{equation}\n\nwith n  as sam and N as pop\n\nFunction \n\\begin{verbatim}\nfpc = fpc(sam,pop)\n\\end{verbatim}\n\ncalculate FPC for standard deviation with \n\\begin{equation}\nfpc_{sd} = \\sqrt{\\frac{N-n} {N-1}}\n\\label{fpc}\n\\end{equation}\nwith n  as sample size and N as population size.\n\n\\subsection{Sample Size estimation for proportions}\n\nOn infinite poblations, you should use method\n\\begin{verbatim}\nestimation_n0(d,prop,margin=0.95)\n\\end{verbatim}\nwhich uses\n\\begin{equation}\nn = \\frac{t^2(pq)}{d^2}\n\\label{n_i}\n\\end{equation}\nwhere\n\\begin{align*}\nt &= \\text{t value for given level of confidence ( 1.96 for 95\\% )}\\\\\nd &= \\text{margin of error}\n\\end{align*}\n\nOn finite poblations, you should use\n\\begin{verbatim}\nestimation_n(d,prop,n_pobl, margin=0.95)\n\\end{verbatim}\nwhich uses\n\\begin{equation}\nn = \\frac{n_i}{1+(\\frac{n_i-1}{N})}\n\\end{equation}\n\nWhere $n_i$ is n on \\ref{n_i} and N is population size\n\n\n"
  },
  {
    "path": "examples/boxplot.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\nrequire 'statsample'\nStatsample::Analysis.store(Statsample::Graph::Boxplot) do \n  n=30\n  a=rnorm(n-1,50,10)\n  b=rnorm(n, 30,5)\n  c=rnorm(n,5,1)\n  a.push(2)\n  boxplot(:vectors=>[a,b,c],:width=>300, :height=>300, :groups=>%w{first first second}, :minimum=>0)\n  \nend\n\nif __FILE__==$0\n  Statsample::Analysis.run\nend\n"
  },
  {
    "path": "examples/correlation_matrix.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\nrequire 'statsample'\n\nStatsample::Analysis.store(\"Statsample::Bivariate.correlation_matrix\") do\n  samples=1000\n  ds=data_frame(\n    'a'=>rnorm(samples),\n    'b'=>rnorm(samples),\n    'c'=>rnorm(samples),\n    'd'=>rnorm(samples))\n  cm=cor(ds)\n  summary(cm)\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/dataset.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Dataset) do\n  samples=1000\n  a=Statsample::Vector.new_scale(samples) {r=rand(5); r==4 ? nil: r}\n  b=Statsample::Vector.new_scale(samples) {r=rand(5); r==4 ? nil: r}\n\n  ds={'a'=>a,'b'=>b}.to_dataset\n  summary(ds)\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/dominance_analysis.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\n\nStatsample::Analysis.store(Statsample::DominanceAnalysis) do\n  sample=300\n  a=rnorm(sample)\n  b=rnorm(sample)\n  c=rnorm(sample)\n  d=rnorm(sample)\n  \n  ds={'a'=>a,'b'=>b,'cc'=>c,'d'=>d}.to_dataset\n  attach(ds)\n  ds['y']=a*5+b*3+cc*2+d+rnorm(300)  \n  cm=cor(ds)\n  summary(cm)\n  lr=lr(ds,'y')\n  summary(lr)\n  da=dominance_analysis(ds,'y')\n  summary(da)\n  \n  da=dominance_analysis(ds,'y',:name=>\"Dominance Analysis using group of predictors\", :predictors=>['a', 'b', %w{cc d}])\n  summary(da)\nend\n\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/dominance_analysis_bootstrap.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::DominanceAnalysis::Bootstrap) do\n  \n  sample=300\n  a=rnorm(sample)\n  b=rnorm(sample)\n  c=rnorm(sample)\n  d=rnorm(sample)  \n  a.name=\"a\"\n  b.name=\"b\"\n  c.name=\"c\"\n  d.name=\"d\"\n  \n  ds={'a'=>a,'b'=>b,'cc'=>c,'d'=>d}.to_dataset\n  attach(ds)\n  ds['y1']=a*5+b*2+cc*2+d*2+rnorm(sample,0,10)\n  ds['y2']=a*10+rnorm(sample)\n  \n  dab=dominance_analysis_bootstrap(ds, ['y1','y2'], :debug=>true)\n  dab.bootstrap(100,nil)\n  summary(dab)\n  ds2=ds['a'..'y1']\n  dab2=dominance_analysis_bootstrap(ds2, 'y1', :debug=>true)\n  dab2.bootstrap(100,nil)\n  summary(dab2)\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/histogram.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Graph::Histogram) do\n  histogram(rnorm(3000,0,20))\nend\n\n\nif __FILE__==$0\n   Statsample::Analysis.run\nend\n"
  },
  {
    "path": "examples/icc.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Reliability::ICC) do\n\n  size=1000\n  a=Statsample::Vector.new_scale(size) {rand(10)}\n  b=a.recode{|i|i+rand(4)-2}\n  c=a.recode{|i|i+rand(4)-2}\n  d=a.recode{|i|i+rand(4)-2}\n  @ds={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n  @icc=Statsample::Reliability::ICC.new(@ds)\n  summary(@icc)\n  @icc.type=:icc_3_1\n  summary(@icc)\n  @icc.type=:icc_a_k\n  summary(@icc)\n  \nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/levene.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Test::Levene) do\n\n  a=[1,2,3,4,5,6,7,8,100,10].to_scale\n  b=[30,40,50,60,70,80,90,100,110,120].to_scale\n  summary(levene([a,b]))\nend\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/multiple_regression.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Regression::Multiple) do\n\n  samples=2000\n  ds=dataset('a'=>rnorm(samples),'b'=>rnorm(samples),'cc'=>rnorm(samples),'d'=>rnorm(samples))\n  attach(ds)\n  ds['y']=a*5+b*3+cc*2+d+rnorm(samples)\n  summary lr(ds,'y')\nend\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/multivariate_correlation.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\nrequire 'mathn'\n\n\nStatsample::Analysis.store(Statsample::Regression::Multiple::MultipleDependent) do\n  \n  complete=Matrix[\n  [1,0.53,0.62,0.19,-0.09,0.08,0.02,-0.12,0.08],\n  [0.53,1,0.61,0.23,0.1,0.18,0.02,-0.1,0.15],\n  [0.62,0.61,1,0.03,0.1,0.12,0.03,-0.06,0.12],\n  [0.19,0.23,0.03,1,-0.02,0.02,0,-0.02,-0.02],\n  [-0.09,0.1,0.1,-0.02,1,0.05,0.06,0.18,0.02],\n  [0.08,0.18,0.12,0.02,0.05,1,0.22,-0.07,0.36],\n  [0.02,0.02,0.03,0,0.06,0.22,1,-0.01,-0.05],\n  [-0.12,-0.1,-0.06,-0.02,0.18,-0.07,-0.01,1,-0.03],\n  [0.08,0.15,0.12,-0.02,0.02,0.36,-0.05,-0.03,1]]\n  \n  complete.extend Statsample::CovariateMatrix\n  complete.fields=%w{adhd cd odd sex age monly mwork mage poverty}\n  \n  lr=Statsample::Regression::Multiple::MultipleDependent.new(complete, %w{adhd cd odd})\n  \n  echo \"R^2_yx #{lr.r2yx}\"\n  echo \"P^2_yx #{lr.p2yx}\"\nend\n\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/parallel_analysis.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\nsamples=150\nvariables=30\niterations=50\nStatsample::Analysis.store(Statsample::Factor::ParallelAnalysis) do \n  \nrng = Distribution::Normal.rng()\nf1=rnorm(samples)\nf2=rnorm(samples)\nf3=rnorm(samples)\n\nvectors={}\n\nvariables.times do |i|\n  vectors[\"v#{i}\"]=samples.times.collect {|nv| f1[nv]*i+(f2[nv]*(15-i))+((f3[nv]*(30-i))*1.5)*rng.call}.to_scale\n  vectors[\"v#{i}\"].name=\"Vector #{i}\"\nend\n\n  ds=vectors.to_dataset\n\n  pa=Statsample::Factor::ParallelAnalysis.new(ds, :iterations=>iterations, :debug=>true)\n  pca=pca(cor(ds))\n  echo \"There are 3 real factors on data\"\n  summary pca\n  echo \"Traditional Kaiser criterion (k>1) returns #{pca.m} factors\"\n  summary pa\n  echo \"Parallel Analysis returns #{pa.number_of_factors} factors to preserve\"\nend\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/polychoric.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n$:.unshift(\"/home/cdx/usr/lib/statsample-bivariate-extension/lib/\")\n\nrequire 'statsample'\nStatsample::Analysis.store(Statsample::Bivariate::Polychoric) do \nct=Matrix[[rand(10)+50, rand(10)+50,  rand(10)+1],\n          [rand(20)+5,  rand(50)+4,   rand(10)+1],\n          [rand(8)+1,   rand(12)+1,   rand(10)+1]]\n\n# Estimation of polychoric correlation using two-step (default)\npoly=polychoric(ct, :name=>\"Polychoric with two-step\", :debug=>false)\nsummary poly\n\n# Estimation of polychoric correlation using joint method (slow)\npoly=polychoric(ct, :method=>:joint, :name=>\"Polychoric with joint\")\nsummary poly\n\n# Uses polychoric series (not recomended)\n\npoly=polychoric(ct, :method=>:polychoric_series, :name=>\"Polychoric with polychoric series\")\nsummary poly\nend\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/principal_axis.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Factor::PrincipalAxis) do\n\n  matrix=Matrix[\n  [1.0, 0.709501601093587, 0.877596585880047, 0.272219316266807],  [0.709501601093587, 1.0, 0.291633797330304, 0.871141831433844], [0.877596585880047, 0.291633797330304, 1.0, -0.213373722977167], [0.272219316266807, 0.871141831433844, -0.213373722977167, 1.0]]\n  \n  matrix.extend Statsample::CovariateMatrix\n  \n  #matrix.fields=%w{a b c d}\n  fa=principal_axis(matrix,:m=>1,:smc=>false)\n  \n  summary fa\nend\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/reliability.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Reliability) do\n  \n  samples=100\n  a=rnorm(samples)\n  \n  ds=Statsample::Dataset.new\n  \n  20.times do |i|\n    ds[\"v#{i}\"]=a+rnorm(samples,0,0.2)\n  end\n  \n  ds.update_valid_data\n  \n  rel=Statsample::Reliability::ScaleAnalysis.new(ds)\n  summary rel\n  \n  \n  ms=Statsample::Reliability::MultiScaleAnalysis.new(:name=>\"Multi Scale analyss\") do |m|\n    m.scale \"Scale 1\", ds.clone(%w{v1 v2 v3 v4 v5 v6 v7 v8 v9 v10})\n    m.scale \"Scale 2\", ds.clone(%w{v11 v12 v13 v14 v15 v16 v17 v18 v19})\n  end\n  \n  summary ms\nend\n\nif __FILE__==$0\n   Statsample::Analysis.run_batch\nend\n\n"
  },
  {
    "path": "examples/scatterplot.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n$:.unshift('/home/cdx/dev/reportbuilder/lib/')\n\nrequire 'benchmark'\nrequire 'statsample'\nn=100\n\nStatsample::Analysis.store(Statsample::Graph::Scatterplot) do\n  x=rnorm(n)\n  y=x+rnorm(n,0.5,0.2)\n  scatterplot(x,y)\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run\nend\n"
  },
  {
    "path": "examples/t_test.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Test::T) do\n  \n  \n  a=rnorm(10)\n  t_1=Statsample::Test.t_one_sample(a,{:u=>50})\n  summary t_1\n  \n  b=rnorm(10,2)\n  \n  t_2=Statsample::Test.t_two_samples_independent(a,b)\n  summary t_2\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/tetrachoric.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Bivariate::Tetrachoric) do\n  \na=40\nb=10\nc=20\nd=30\nsummary tetrachoric(a,b,c,d)\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/u_test.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib')\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Test::UMannWhitney) do\n\n  a=10.times.map {rand(100)}.to_scale\n  b=20.times.map {(rand(20))**2+50}.to_scale\n\n  u=Statsample::Test::UMannWhitney.new(a,b)\n  summary u\nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/vector.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Vector) do\n\n  a=Statsample::Vector.new_scale(1000) {r=rand(5); r==4 ? nil: r;}\n  summary a\n  b=c(1,2,3,4,6..10)\n  summary b\n  \nend\n\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "examples/velicer_map_test.rb",
    "content": "#!/usr/bin/ruby\n$:.unshift(File.dirname(__FILE__)+'/../lib/')\n\nrequire 'statsample'\n\nStatsample::Analysis.store(Statsample::Factor::MAP) do\n  \n  rng=Distribution::Normal.rng\n  samples=100\n  variables=10\n  \n  f1=rnorm(samples)\n  f2=rnorm(samples)\n  \n  vectors={}\n  \n  variables.times do |i|\n  vectors[\"v#{i}\"]=samples.times.collect {|nv|    \n  if i<5\n    f1[nv]*5 + f2[nv] *2 +rng.call\n  else\n    f1[nv]*2 + f2[nv] *3 +rng.call\n  end\n  }.to_scale\n  end\n  \n  \n  ds=vectors.to_dataset\n  cor=cor(ds)\n  pca=pca(cor)\n  \n  map=Statsample::Factor::MAP.new(cor)\n  \n  echo (\"There are 2 real factors on data\")\n  summary(pca)\n  echo(\"Traditional Kaiser criterion (k>1) returns #{pca.m} factors\")\n  summary(map)\n  echo(\"Velicer's MAP Test returns #{map.number_of_factors} factors to preserve\")\nend\nif __FILE__==$0\n  Statsample::Analysis.run_batch\nend\n"
  },
  {
    "path": "grab_references.rb",
    "content": "#!/usr/bin/env ruby1.9\nrequire 'reportbuilder'\nrefs=[]\nDir.glob \"**/*.rb\" do |f|\n  next if f=~/pkg/\n\treference=false\n\tFile.open(f).each_line \tdo |l|\n\t\t\n\t\tif l=~/== Reference/\n\t\t    reference=true\n\t\telsif reference\n\t\t\tif l=~/\\*\\s+(.+)/\n\t\t\t\trefs.push $1\n\t\t\telse\n\t\t\t\treference=false\n\t\t\tend\n\t        end\n\t    \n\tend\nend\n\n\nrb=ReportBuilder.new(:name=>\"References\") do |g|\n\trefs.uniq.sort.each do |r|\n\t\tg.text \"* #{r}\"\n\tend\nend\n\nrb.save_text(\"references.txt\")"
  },
  {
    "path": "lib/spss.rb",
    "content": "# = spss.rb - \n#\n# Provides utilites for working with spss files\n#\n# Copyright (C) 2009 Claudio Bustos\n#\n# Claudio Bustos mailto:clbustos@gmail.com\n\nmodule SPSS # :nodoc: all\n  module Dictionary\n    class Element\n      def add(a)\n        @elements.push(a)\n      end\n      def parse_elements(func=:to_s)\n        @elements.collect{|e| \"   \"+e.send(func)}.join(\"\\n\")\n      end\n      def init_with config\n        config.each {|key,value|\n            self.send(key.to_s+\"=\",value) if methods.include? key.to_s\n        }\n      end\n      def initialize(config={})\n        @config=config\n        @elements=[]\n      end\n    end\n    class Dictionary < Element\n      attr_accessor :locale, :date_time, :row_count\n      def initialize(config={})\n        super\n        init_with ({\n                :locale=>\"en_US\", \n                :date_time=>Time.new().strftime(\"%Y-%m-%dT%H:%M:%S\"),\n                :row_count=>1\n        })\n        init_with config\n      end\n      \n      def to_xml\n        \"<dictionary locale='#{@locale}' creationDateTime='#{@date_time}' rowCount='#{@row_count}' xmlns='http://xml.spss.com/spss/data'>\\n\"+parse_elements(:to_xml)+\"\\n</dictionary>\"\n        \n      end\n      def to_spss\n        parse_elements(:to_spss)\n      end\n    end\n    \n    class MissingValue < Element\n      attr_accessor :data, :type, :from, :to\n      def initialize(data,type=nil)\n        @data=data\n        if type.nil? or type==\"lowerBound\" or type==\"upperBound\"\n            @type=type\n        else\n            raise Exception,\"Incorrect value for type\"\n        end\n      end\n      def to_xml\n        \"<missingValue data='#{@data}' \"+(type.nil? ? \"\":\"type='#{type}'\")+\"/>\"\n      end\n    end\n    class LabelSet\n      attr_accessor\n      def initialize(labels)\n        @labels=labels\n      end\n      def parse_xml(name)\n        \"<valueLabelSet>\\n   \"+@labels.collect{|key,value| \"<valueLabel label='#{key}' value='#{value}' />\"}.join(\"\\n   \")+\"\\n   <valueLabelVariable name='#{name}' />\\n</valueLabelSet>\"\n      end\n      def parse_spss()\n        @labels.collect{|key,value| \"#{key} '#{value}'\"}.join(\"\\n   \")\n      end\n    end\n    class Variable < Element\n      attr_accessor :aligment, :display_width, :label, :measurement_level, :name, :type, :decimals, :width, :type_format, :labelset, :missing_values\n      def initialize(config={})\n        super\n        @@var_number||=1\n        init_with({\n          :aligment           =>  \"left\",\n          :display_width      =>  8,\n          :label              =>  \"Variable #{@@var_number}\",\n          :measurement_level  =>  \"SCALE\",\n          :name               =>  \"var#{@@var_number}\",\n          :type               =>  0,\n          :decimals           =>  2,\n          :width              =>  10,\n          :type_format        =>  \"F\",\n          :labelset           => nil\n        })\n        init_with config\n        @missing_values=[]\n        @@var_number+=1\n      end\n      def to_xml\n        labelset_s=(@labelset.nil?) ? \"\":\"\\n\"+@labelset.parse_xml(@name)\n        missing_values=(@missing_values.size>0) ? @missing_values.collect {|m| m.to_xml}.join(\"\\n\"):\"\"\n        \"<variable aligment='#{@aligment}' displayWidth='#{@display_width}' label='#{@label}' measurementLevel='#{@measurement_level}' name='#{@name}' type='#{@type}'>\\n<variableFormat decimals='#{@decimals}' width='#{@width}' type='#{@type_format}' />\\n\"+parse_elements(:to_xml)+missing_values+\"</variable>\"+labelset_s\n      end\n      def to_spss\n        out=<<HERE\nVARIABLE LABELS #{@name} '#{label}' .\nVARIABLE ALIGMENT #{@name} (#{@aligment.upcase}) .\nVARIABLE WIDTH #{@name} (#{@display_width}) .\nVARIABLE LEVEL #{@name} (#{@measurement_level.upcase}) .\nHERE\n        if !@labelset.nil?\n            out << \"VALUE LABELS #{@name} \"+labelset.parse_spss()+\" .\"\n        end\n        if @missing_values.size>0\n            out << \"MISSING VALUES #{@name} (\"+@missing_values.collect{|m| m.data}.join(\",\")+\") .\"\n        end\n        out\n      end\n    end\n  end\nend\nn=SPSS::Dictionary::Dictionary.new\nls=SPSS::Dictionary::LabelSet.new({1=>\"Si\",2=>\"No\"})\nvar1=SPSS::Dictionary::Variable.new\nvar1.labelset=ls\nmv1=SPSS::Dictionary::MissingValue.new(\"-99\")\nvar2=SPSS::Dictionary::Variable.new\nn.add(var1)\nn.add(var2)\nvar2.missing_values=[mv1]\n\nFile.open(\"dic_spss.sps\",\"wb\") {|f|\n    f.puts n.to_spss\n}\n"
  },
  {
    "path": "lib/statsample/analysis/suite.rb",
    "content": "module Statsample\n  module Analysis\n    class Suite \n      include Statsample::Shorthand\n      attr_accessor :output\n      attr_accessor :name\n      attr_reader :block\n      def initialize(opts=Hash.new(), &block)\n        if !opts.is_a? Hash\n          opts={:name=>opts}\n        end\n         \n        @block=block\n        @name=opts[:name] || \"Analysis #{Time.now}\"\n        @attached=[]\n        @output=opts[:output] || ::STDOUT\n      end\n      # Run the analysis, putting output on \n      def run\n         @block.arity<1 ? instance_eval(&@block) : @block.call(self)\n      end\n      # Provides a description of the procedure. Only appears as a commentary on \n      # SuiteReportBuilder outputs\n      def desc(d)\n        @output.puts(\"Description:\")\n        @output.puts(\"  #{d}\") \n      end\n      def echo(*args)\n        @output.puts(*args)\n      end\n      def summary(obj)\n        obj.summary\n      end\n      def add_to_reportbuilder(rb)\n        SuiteReportBuilder.new({:name=>name, :rb=>rb}, &block)\n      end\n      \n      def generate(filename)\n        ar=SuiteReportBuilder.new({:name=>name}, &block)\n        ar.generate(filename)\n      end\n      def to_text\n        ar=SuiteReportBuilder.new({:name=>name}, &block)\n        ar.to_text\n      end\n      \n      def attach(ds)\n        @attached.push(ds)\n      end\n      def detach(ds=nil)\n        if ds.nil?\n          @attached.pop\n        else\n          @attached.delete(ds)\n        end\n      end\n      alias :old_boxplot :boxplot\n      alias :old_histogram :histogram\n      alias :old_scatterplot :scatterplot\n\n      def show_svg(svg)\n        require 'tmpdir'\n        fn=Dir.tmpdir+\"/image_#{Time.now.to_f}.svg\"\n        File.open(fn,\"w\") {|fp| fp.write svg}\n\tif RUBY_PLATFORM =~/darwin/\n\t  %x(open -a safari #{fn})\n\telse\n\t  %x(xdg-open #{fn})\n\tend\n      end\n      def boxplot(*args)\n        show_svg(old_boxplot(*args).to_svg)\n      end\n      def histogram(*args)\n        show_svg(old_histogram(*args).to_svg)\n      end\n      def scatterplot(*args)\n        show_svg(old_scatterplot(*args).to_svg)\n      end\n      \n      def method_missing(name, *args,&block)\n        @attached.reverse.each do |ds|\n          return ds[name.to_s] if ds.fields.include? (name.to_s)\n        end\n        raise \"Method #{name} doesn't exists\"\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/analysis/suitereportbuilder.rb",
    "content": "module Statsample\n  module Analysis\n    class SuiteReportBuilder < Suite\n      attr_accessor :rb\n      def initialize(opts=Hash.new,&block)\n        if !opts.is_a? Hash\n          opts={:name=>opts}\n        end        \n        super(opts,&block)\n        @rb=opts[:rb] || ReportBuilder.new(:name=>name)\n      end\n      def generate(filename)\n        run if @block\n        @rb.save(filename)\n      end\n      def to_text\n        run if @block\n        @rb.to_text\n      end\n      def summary(o)\n        @rb.add(o)\n      end\n      def desc(d)\n        @rb.add(d)\n      end\n      def echo(*args)\n        args.each do |a|\n          @rb.add(a)\n        end\n      end\n      \n      def boxplot(*args)\n        @rb.add(old_boxplot(*args))\n      end\n      def histogram(*args)\n        @rb.add(old_histogram(*args))\n      end\n      def boxplot(*args)\n        @rb.add(old_boxplot(*args))\n      end\n      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/analysis.rb",
    "content": "require 'statsample/analysis/suite'\nrequire 'statsample/analysis/suitereportbuilder'\n\nmodule Statsample\n  # DSL to create analysis without hazzle. \n  # * Shortcuts methods to avoid use complete namescapes, many based on R  \n  # * Attach/detach vectors to workspace, like R\n  # == Example\n  #  an1=Statsample::Analysis.store(:first) do\n  #    # Load excel file with x,y,z vectors\n  #    ds=excel('data.xls')\n  #    # See variables on ds dataset\n  #    names(ds) \n  #    # Attach the vectors to workspace, like R\n  #    attach(ds)\n  #    # vector 'x' is attached to workspace like a method,\n  #    # so you can use like any variable\n  #    mean,sd=x.mean, x.sd \n  #    # Shameless R robbery\n  #    a=c( 1:10)\n  #    b=c(21:30)\n  #    summary(cor(ds)) # Call summary method on correlation matrix\n  #  end\n  #  # You can run the analysis by its name\n  #  Statsample::Analysis.run(:first)\n  #  # or using the returned variables\n  #  an1.run\n  #  # You can also generate a report using ReportBuilder.\n  #  # .summary() method call 'report_building' on the object, \n  #  # instead of calling text summary\n  #  an1.generate(\"report.html\")\n  module Analysis\n    @@stored_analysis={}\n    @@last_analysis=nil\n    def self.clear_analysis\n      @@stored_analysis.clear\n    end\n    def self.stored_analysis\n      @@stored_analysis\n    end\n    def self.last\n      @@stored_analysis[@@last_analysis]\n    end\n    def self.store(name, opts=Hash.new,&block)\n      raise \"You should provide a block\" if !block\n      @@last_analysis=name\n      opts={:name=>name}.merge(opts)\n      @@stored_analysis[name]=Suite.new(opts,&block)\n    end\n    # Run analysis +*args+\n    # Without arguments, run all stored analysis\n    # Only 'echo' will be returned to screen\n    def self.run(*args)\n      args=stored_analysis.keys if args.size==0\n      raise \"Analysis #{args} doesn't exists\" if (args - stored_analysis.keys).size>0\n      args.each do |name|\n        stored_analysis[name].run\n      end\n    end\n\n    # Add analysis +*args+ to an reportbuilder object.\n    # Without arguments, add all stored analysis\n    # Each analysis is wrapped inside a ReportBuilder::Section object\n    # This is the method is used by save() and to_text()\n    \n    def self.add_to_reportbuilder(rb, *args)\n      args=stored_analysis.keys if args.size==0\n      raise \"Analysis #{name} doesn't exists\" if (args - stored_analysis.keys).size>0\n      args.each do |name|\n        section=ReportBuilder::Section.new(:name=>stored_analysis[name].name)\n        rb_an=stored_analysis[name].add_to_reportbuilder(section)\n        rb.add(section)        \n        rb_an.run\n      end\n    end\n    \n    # Save the analysis on a file\n    # Without arguments, add all stored analysis    \n    def self.save(filename, *args)\n      rb=ReportBuilder.new(:name=>filename)\n      add_to_reportbuilder(rb, *args)\n      rb.save(filename)\n    end\n    \n    # Run analysis and return as string\n    # output of echo callings\n    # Without arguments, add all stored analysis\n    \n    def self.to_text(*args)\n      rb=ReportBuilder.new(:name=>\"Analysis #{Time.now}\")\n      add_to_reportbuilder(rb, *args)\n      rb.to_text\n    end\n    # Run analysis and return to screen all\n    # echo and summary callings\n    def self.run_batch(*args)\n      puts to_text(*args)\n    end    \n  end\nend\n"
  },
  {
    "path": "lib/statsample/anova/contrast.rb",
    "content": "module Statsample\n  module Anova\n    class Contrast\n      attr_reader :psi\n\n      attr_reader :msw\n      include Summarizable\n      def initialize(opts=Hash.new)\n        raise \"Should set at least vectors options\" if opts[:vectors].nil?\n        @vectors=opts[:vectors]\n        @c=opts[:c]\n        @c1,@c2=opts[:c1], opts[:c2]\n        @t_options=opts[:t_options] || {:estimate_name=>_(\"Psi estimate\")}\n        @name=opts[:name] || _(\"Contrast\")\n        @psi=nil\n        @anova=Statsample::Anova::OneWayWithVectors.new(@vectors)\n        @msw=@anova.msw\n      end\n      # Hypothesis contrast, selecting index for each constrast\n      # For example, if you want to contrast x_0 against x_1 and x_2\n      # you should use\n      # c.contrast([0],[1,2])\n      def c_by_index(c1,c2)\n        contrast=[0]*@vectors.size\n        c1.each {|i| contrast[i]=1.quo(c1.size)}\n        c2.each {|i| contrast[i]=-1.quo(c2.size)}\n        @c=contrast\n        c(contrast)\n      end\n      def psi\n        if @psi.nil?\n          c(@c) if @c\n          c_by_index(@c1,@c2) if (@c1 and @c2)\n        end\n        @psi\n      end\n      def confidence_interval(cl=nil)\n        t_object.confidence_interval(cl)\n      end\n      # Hypothesis contrast, using custom values\n      # Every parameter is a contrast value. You should use\n      # the same number of contrast as vectors on class and the sum\n      # of constrast should be 0.\n      def c(args=nil)\n        \n        return @c if args.nil?\n        @c=args\n        raise \"contrast number!=vector number\" if args.size!=@vectors.size\n        #raise \"Sum should be 0\" if args.inject(0) {|ac,v| ac+v}!=0\n        @psi=args.size.times.inject(0) {|ac,i| ac+(args[i]*@vectors[i].mean)}\n      end\n      def standard_error\n        sum=@vectors.size.times.inject(0) {|ac,i|\n          ac+((@c[i].rationalize**2).quo(@vectors[i].size))\n        } \n        Math.sqrt(@msw*sum)\n      end\n      alias :se :standard_error\n      def df\n        @vectors.inject(0) {|ac,v| ac+v.size}-@vectors.size\n      end\n      def t_object\n        Statsample::Test::T.new(psi, se, df, @t_options)\n      end\n      def t\n        t_object.t\n      end\n      def probability\n        t_object.probability\n      end\n      def report_building(builder)\n         builder.section(:name=>@name) do |s|\n           s.text _(\"Contrast:%s\") % c.join(\",\")\n           s.parse_element(t_object)\n         end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/anova/oneway.rb",
    "content": "module Statsample\n  module Anova\n    # = Generic Anova one-way.\n    # You could enter the sum of squares or the mean squares. You\n    # should enter the degrees of freedom for numerator and denominator.\n    # == Usage\n    #  anova=Statsample::Anova::OneWay(:ss_num=>10,:ss_den=>20, :df_num=>2, :df_den=>10, @name=>\"ANOVA for....\")\n    class OneWay\n      include Summarizable\n      attr_reader :df_num, :df_den, :ss_num, :ss_den, :ms_num, :ms_den, :ms_total, :df_total, :ss_total\n      # Name of ANOVA Analisys\n      attr_accessor :name\n      attr_accessor :name_denominator\n      attr_accessor :name_numerator\n      def initialize(opts=Hash.new)\n        @name=@name_numerator=@name_denominator=nil\n        \n        # First see if sum of squares or mean squares are entered\n        raise ArgumentError, \"You should set d.f.\" unless (opts.has_key? :df_num and opts.has_key? :df_den)\n        @df_num=opts.delete :df_num\n        @df_den=opts.delete :df_den\n        @df_total=@df_num+@df_den\n        if(opts.has_key? :ss_num and opts.has_key? :ss_den)\n          @ss_num = opts.delete :ss_num\n          @ss_den =opts.delete :ss_den\n          @ms_num =@ss_num.quo(@df_num)\n          @ms_den =@ss_den.quo(@df_den) \n        elsif (opts.has_key? :ms_num and opts.has_key? :ms_den)\n          @ms_num =opts.delete :ms_num\n          @ms_den =opts.delete :ms_den\n          @ss_num =@ms_num * @df_num\n          @ss_den =@ss_den * @df_den\n        end\n        @ss_total=@ss_num+@ss_den\n        @ms_total=@ms_num+@ms_den\n        opts_default={:name=>\"ANOVA\",\n                      :name_denominator=>_(\"Explained variance\"),\n                      :name_numerator=>_(\"Unexplained variance\")}\n        @opts=opts_default.merge(opts)\n        opts.keys.each {|k|\n          send(\"#{k}=\", @opts[k]) if self.respond_to? \"#{k}=\"\n        }\n        @f_object=Statsample::Test::F.new(@ms_num, @ms_den, @df_num,@df_den)\n      end\n      # F value\n      def f\n        @f_object.f\n      end\n      # P-value of F test\n      def probability\n        @f_object.probability\n      end\n      def report_building(builder) #:nodoc:\n        builder.section(:name=>@name) do |b|\n          report_building_table(b)\n        end\n      end\n      def report_building_table(builder) #:nodoc:\n        builder.table(:name=>_(\"%s Table\") % @name, :header=>%w{source ss df ms f p}.map {|v| _(v)}) do |t|\n          t.row([@name_numerator, sprintf(\"%0.3f\",@ss_num),   @df_num, sprintf(\"%0.3f\",@ms_num),  sprintf(\"%0.3f\",f), sprintf(\"%0.3f\", probability)])\n          t.row([@name_denominator, sprintf(\"%0.3f\",@ss_den),  @df_den, sprintf(\"%0.3f\",@ms_den), \"\", \"\"])\n          t.row([_(\"Total\"), sprintf(\"%0.3f\",@ss_total),  @df_total, sprintf(\"%0.3f\",@ms_total),\"\",\"\"])\n        end\n      end\n\n    end\n    \n    # One Way Anova with vectors\n    # Example:\n    #   v1=[2,3,4,5,6].to_scale\n    #   v2=[3,3,4,5,6].to_scale\n    #   v3=[5,3,1,5,6].to_scale\n    #   anova=Statsample::Anova::OneWayWithVectors.new([v1,v2,v3])\n    #   anova.f\n    #   => 0.0243902439024391\n    #   anova.probability\n    #   => 0.975953044203438\n    #   anova.sst \n    #   => 32.9333333333333\n    #\n    class OneWayWithVectors < OneWay\n      # Show on summary Levene test\n      attr_accessor :summary_levene\n      # Show on summary descriptives for vectors\n      attr_accessor :summary_descriptives\n      # Show on summary of contrasts\n      attr_accessor :summary_contrasts\n      # Array with stored contrasts\n      attr_reader :contrasts\n      \n      def initialize(*args)\n        if args[0].is_a? Array\n          @vectors=args.shift\n        else\n          @vectors=args.find_all {|v| v.is_a? Statsample::Vector}\n          opts=args.find {|v| v.is_a? Hash}\n        end\n        opts||=Hash.new\n        opts_default={:name=>_(\"Anova One-Way\"), \n                      :name_numerator=>_(\"Between Groups\"),\n                      :name_denominator=>_(\"Within Groups\"),\n                      :summary_descriptives=>false,\n                      :summary_levene=>true,\n                      :summary_contrasts=>true\n        }\n        @opts=opts_default.merge(opts).merge(:ss_num=>ssbg, :ss_den=>sswg, :df_num=>df_bg, :df_den=>df_wg)\n        @contrasts=[]\n        super(@opts)\n      end\n      alias :sst :ss_total \n      alias :msb :ms_num\n      alias :msw :ms_den\n      \n      # Generates and store a contrast.\n      # Options should be provided as a hash\n      # [:c]=>contrast vector\n      # [:c1 - :c2]=>index for automatic construction of contrast\n      # [:name]=>contrast name\n      \n      def contrast(opts=Hash.new)\n        name=opts[:name] || _(\"Contrast for %s\") % @name\n        opts=opts.merge({:vectors=>@vectors, :name=>name})\n        c=Statsample::Anova::Contrast.new(opts)\n        @contrasts.push(c)\n        c\n      end\n      \n      def levene\n        Statsample::Test.levene(@vectors, :name=>_(\"Test of Homogeneity of variances (Levene)\"))\n      end\n      # Total mean\n      def total_mean\n        sum=@vectors.inject(0){|a,v| a+v.sum}\n        sum.quo(n)\n      end\n      # Sum of squares within groups\n      def sswg\n        @sswg||=@vectors.inject(0) {|total,vector| total+vector.ss }\n      end\n      # Sum of squares between groups\n      def ssbg\n        m=total_mean\n        @vectors.inject(0) do |total,vector|\n          total + (vector.mean-m).square * vector.size \n        end\n      end\n      # Degrees of freedom within groups\n      def df_wg\n        @dk_wg||=n-k\n      end\n      def k\n        @k||=@vectors.size\n      end\n      # Degrees of freedom between groups \n      def df_bg\n          k-1\n      end\n      # Total number of cases\n      def n\n          @vectors.inject(0){|a,v| a+v.size}\n      end\n      def report_building(builder) # :nodoc:\n        builder.section(:name=>@name) do |s|\n          if summary_descriptives\n            s.table(:name=>_(\"Descriptives\"),:header=>%w{Name N Mean SD Min Max}.map {|v| _(v)}) do |t|\n              @vectors.each do |v|\n                t.row [v.name, v.n_valid, \"%0.4f\" % v.mean, \"%0.4f\" %  v.sd, \"%0.4f\" % v.min, \"%0.4f\" % v.max]\n              end\n            end\n          end\n          \n          if summary_levene\n            s.parse_element(levene)\n          end\n          report_building_table(s)\n          if summary_contrasts and @contrasts.size>0\n\n            @contrasts.each do |c|\n              s.parse_element(c)\n            end\n          end\n          \n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/anova/twoway.rb",
    "content": "module Statsample\n  module Anova\n    # = Generic Anova two-way.\n    # You could enter the sum of squares or the mean squares for a, b, axb and within. \n    # You should enter the degrees of freedom for a,b and within, because df_axb=df_a*df_b\n    # == Usage\n    #  anova=Statsample::Anova::TwoWay(:ss_a=>10,:ss_b=>20,:ss_axb=>10, :ss_within=>20, :df_a=>2, :df_b=>3,df_within=100 @name=>\"ANOVA for....\")\n    class TwoWay\n      include Summarizable\n      attr_reader :df_a, :df_b, :df_axb, :df_within, :df_total\n      attr_reader :ss_a, :ss_b, :ss_axb, :ss_within, :ss_total\n      attr_reader :ms_a, :ms_b, :ms_axb, :ms_within, :ms_total\n      # Name of ANOVA Analisys\n      attr_accessor :name\n      # Name of a factor\n      attr_accessor :name_a\n      # Name of b factor\n      attr_accessor :name_b\n      # Name of within factor\n      attr_accessor :name_within\n      \n      attr_reader :f_a_object, :f_b_object, :f_axb_object\n      def initialize(opts=Hash.new)\n        # First see if sum of squares or mean squares are entered\n        raise ArgumentError, \"You should set all d.f.\" unless [:df_a, :df_b, :df_within].all? {|v| opts.has_key? v}\n        \n        @df_a=opts.delete :df_a\n        @df_b=opts.delete :df_b\n        @df_axb=@df_a*@df_b\n        @df_within=opts.delete :df_within\n        @df_total=@df_a+@df_b+@df_axb+@df_within\n        \n        if [:ss_a, :ss_b, :ss_axb, :ss_within].all? {|v| opts.has_key? v}\n          @ss_a = opts.delete :ss_a\n          @ss_b = opts.delete :ss_b\n          @ss_axb = opts.delete :ss_axb\n          @ss_within = opts.delete :ss_within\n          \n          @ms_a =@ss_a.quo(@df_a)\n          @ms_b =@ss_b.quo(@df_b) \n          @ms_axb =@ss_axb.quo(@df_axb)\n          @ms_within =@ss_within.quo(@df_within) \n\n        elsif [:ms_a, :ms_b, :ms_axb, :ms_within].all? {|v| opts.has_key? v}\n          @ms_a = opts.delete :ms_a\n          @ms_b = opts.delete :ms_b\n          @ms_axb = opts.delete :ms_axb\n          @ms_within = opts.delete :ms_within\n          \n          @ss_a =@ms_a*@df_a\n          @ss_b =@ms_b*@df_b \n          @ss_axb =@ms_axb*@df_axb\n          @ss_within =@ms_within*@df_within\n        else\n          raise \"You should set all ss or ss\"\n        end\n        @ss_total=@ss_a+@ss_b+@ss_axb+@ss_within\n        @ms_total=@ms_a+@ms_b+@ms_axb+@ms_within\n        opts_default={:name=>_(\"ANOVA Two-Way\"),\n                      :name_a=>_(\"A\"),\n                      :name_b=>_(\"B\"),\n                      :name_within=>_(\"Within\")                      \n        }\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k|\n          send(\"#{k}=\", @opts[k])\n        }\n        @f_a_object=Statsample::Test::F.new(@ms_a,@ms_within,@df_a,@df_within)\n        @f_b_object=Statsample::Test::F.new(@ms_b,@ms_within,@df_b,@df_within)\n        @f_axb_object=Statsample::Test::F.new(@ms_axb,@ms_within,@df_axb,@df_within)\n      end\n      def f_a\n        @f_a_object.f\n      end\n      def f_b\n        @f_b_object.f\n      end\n      def f_axb\n        @f_axb_object.f\n      end\n      def f_a_probability\n        @f_a_object.probability\n      end\n      def f_b_probability\n        @f_b_object.probability\n      end\n      def f_axb_probability\n        @f_axb_object.probability\n      end\n            \n\n      def report_building(builder) #:nodoc:\n        builder.section(:name=>@name) do |b|\n          report_building_table(b)\n        end\n      end\n      def report_building_table(builder) #:nodoc:\n        builder.table(:name=>_(\"%s Table\") % @name, :header=>%w{source ss df ms f p}.map {|v| _(v)}) do |t|\n          t.row([@name_a, \"%0.3f\" % @ss_a,   @df_a, \"%0.3f\" % @ms_a , \"%0.3f\" % f_a, \"%0.4f\" % f_a_probability] )\n          t.row([@name_b, \"%0.3f\" % @ss_b,   @df_b, \"%0.3f\" % @ms_b , \"%0.3f\" % f_b, \"%0.4f\" % f_b_probability] )\n          t.row([\"%s X %s\" % [@name_a, @name_b], \"%0.3f\" % @ss_axb,   @df_axb, \"%0.3f\" % @ms_axb , \"%0.3f\" % f_axb, \"%0.4f\" % f_axb_probability] )          \n          t.row([@name_within, \"%0.3f\" % @ss_within,   @df_within, nil,nil,nil] )\n          t.row([_(\"Total\"), \"%0.3f\" % @ss_total,   @df_total, nil,nil,nil] )          \n        end\n      end\n    end\n    \n    # Two Way Anova with vectors\n    # Example:\n    #   v1=[1,1,2,2].to_scale\n    #   v2=[1,2,1,2].to_scale\n    #   v3=[5,3,1,5].to_scale\n    #   anova=Statsample::Anova::TwoWayWithVectors.new(:a=>v1,:b=>v2, :dependent=>v3)\n    #\n    class TwoWayWithVectors < TwoWay\n       # Show summary Levene test\n      attr_accessor :summary_levene\n      # Show summary descriptives for variables (means)\n      attr_accessor :summary_descriptives\n      attr_reader :a_var, :b_var, :dep_var\n      # For now, only equal sample cells allowed\n      def initialize(opts=Hash.new)\n        raise \"You should insert at least :a, :b and :dependent\" unless  [:a, :b, :dependent].all? {|v| opts.has_key? v}\n        @a_var='a'\n        @b_var='b'\n        @dep_var='dependent'\n        @a_vector, @b_vector, @dep_vector=Statsample.only_valid_clone opts[:a], opts[:b], opts[:dependent]\n        \n        ds={@a_var=>@a_vector, @b_var=>@b_vector, @dep_var=>@dep_vector}.to_dataset\n        @ds=ds.clone_only_valid\n        _p=@a_vector.factors.size\n        _q=@b_vector.factors.size\n        @x_general=@dep_vector.mean\n        @axb_means={}\n        @axb_sd={}\n        @vectors=[]\n        n=nil\n        @ds.to_multiset_by_split(a_var,b_var).each_vector(dep_var) {|k,v|\n          @axb_means[k]=v.mean\n          @axb_sd[k]=v.sd\n          @vectors << v\n          n||=v.size\n          raise \"All cell sizes should be equal\" if n!=v.size\n        }\n\n        @a_means={}\n        @ds.to_multiset_by_split(a_var).each_vector(dep_var) {|k,v|\n          @a_means[k]=v.mean\n        }\n        @b_means={}\n        @ds.to_multiset_by_split(b_var).each_vector(dep_var) {|k,v|\n          @b_means[k]=v.mean\n        }\n        ss_a=n*_q*@ds[a_var].factors.inject(0) {|ac,v|\n          ac+(@a_means[v]-@x_general)**2\n        }\n        ss_b=n*_p*@ds[b_var].factors.inject(0) {|ac,v|\n          ac+(@b_means[v]-@x_general)**2\n        }\n        ss_within=@ds.collect {|row|\n          (row[dep_var]-@axb_means[[row[a_var],row[b_var]]])**2\n        }.sum\n        ss_axb=n*@axb_means.inject(0) {|ac,v|\n          j,k=v[0]\n          xjk=v[1]\n          ac+(xjk-@a_means[j]-@b_means[k]+@x_general)**2\n        }\n        df_a=_p-1\n        df_b=_q-1\n        df_within=(_p*_q)*(n-1)\n        \n        opts_default={:name=>_(\"Anova Two-Way on %s\") % @ds[dep_var].name, \n          :name_a=>@ds[a_var].name,\n            :name_b=>@ds[b_var].name,\n            :summary_descriptives=>true,\n            :summary_levene=>false}\n            \n        @opts=opts_default.merge(opts).merge({:ss_a=>ss_a,:ss_b=>ss_b, :ss_axb=>ss_axb, :ss_within=>ss_within, :df_a=>df_a, :df_b=>df_b, :df_within=>df_within})\n        \n        \n        super(@opts)\n      end\n      def levene\n        Statsample::Test.levene(@vectors, :name=>_(\"Test of Homogeneity of variances (Levene)\"))\n      end      \n      def report_building(builder) #:nodoc:#\n        builder.section(:name=>@name) do |s|\n          if summary_descriptives\n            s.table(:header =>['']+@ds[a_var].factors.map {|a| @ds[a_var].labeling(a)}+[_(\"%s Mean\") % @name_b]) do |t|\n              @ds[b_var].factors.each do |b|\n                t.row([@ds[b_var].labeling(b)]+@ds[a_var].factors.map {|a| \"%0.3f\" % @axb_means[[a,b]] } + [\"%0.3f\" % @b_means[b]])\n              end\n              t.row([_(\"%s Mean\") % @name_a]+@ds[a_var].factors.map {|a| \"%0.3f\" % @a_means[a]}+ [\"%0.3f\" % @x_general])\n            end\n          end\n          if summary_levene\n            s.parse_element(levene)\n          end\n          report_building_table(s)\n\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/anova.rb",
    "content": "module Statsample\n  module Anova\n    class << self\n      def oneway(*args)\n        OneWay.new(*args)\n      end      \n      def twoway(*args)\n        TwoWay.new(*args)\n      end      \n      \n      def oneway_with_vectors(*args)\n        OneWayWithVectors.new(*args)\n      end\n      def twoway_with_vectors(*args)\n        TwoWayWithVectors.new(*args)\n      end\n      \n    end\n  end\nend\n\nrequire 'statsample/anova/oneway'\nrequire 'statsample/anova/contrast'\nrequire 'statsample/anova/twoway'\n"
  },
  {
    "path": "lib/statsample/bivariate/pearson.rb",
    "content": "module Statsample\n  module Bivariate\n    # = Pearson correlation coefficient (r) \n    # \n    # The moment-product Pearson's correlation coefficient, known as 'r'\n    # is a measure of bivariate associate between two continous\n    # variables.\n    # \n    # == Usage\n    #   a = [1,2,3,4,5,6].to_scale\n    #   b = [2,3,4,5,6,7].to_scale\n    #   pearson = Statsample::Bivariate::Pearson.new(a,b)\n    #   puts pearson.r\n    #   puts pearson.t\n    #   puts pearson.probability\n    #   puts pearson.summary\n    # \n    class Pearson\n      \n      include Statsample::Test\n      include Summarizable\n      # Name of correlation\n      attr_accessor :name\n      # Tails for probability (:both, :left or :right)\n      attr_accessor :tails     \n      attr_accessor :n      \n      def initialize(v1,v2,opts=Hash.new)\n        @v1_name,@v2_name = v1.name,v2.name\n        @v1,@v2           = Statsample.only_valid_clone(v1,v2)\n        @n=@v1.size\n        opts_default={\n          :name=>_(\"Correlation (%s - %s)\") % [@v1_name, @v2_name],\n          :tails=>:both\n        }\n        @opts=opts.merge(opts_default)\n        @opts.each{|k,v|\n          self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n      end\n      def r\n        Statsample::Bivariate.pearson(@v1,@v2)\n      end\n      def t\n        Statsample::Bivariate.t_pearson(@v1,@v2)\n      end\n      def probability\n        p_using_cdf(Distribution::T.cdf(t, @v1.size-2), tails)\n      end\n      def report_building(builder)\n        builder.text(_(\"%s : r=%0.3f (t:%0.3f, g.l.=%d, p:%0.3f / %s tails)\") % [@name, r,t, (n-2), probability, tails])\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/statsample/bivariate.rb",
    "content": "require 'statsample/bivariate/pearson'\nmodule Statsample\n  # Diverse methods and classes to calculate bivariate relations\n  # Specific classes: \n  # * Statsample::Bivariate::Pearson : Pearson correlation coefficient (r)\n  # * Statsample::Bivariate::Tetrachoric : Tetrachoric correlation\n  # * Statsample::Bivariate::Polychoric  : Polychoric correlation (using joint, two-step and polychoric series)\n  module Bivariate\n    autoload(:Polychoric, 'statsample/bivariate/polychoric')\n    autoload(:Tetrachoric, 'statsample/bivariate/tetrachoric')\n    class << self\n      # Covariance between two vectors\n      def covariance(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        return nil if v1a.size==0\n        if Statsample.has_gsl?\n          GSL::Stats::covariance(v1a.gsl, v2a.gsl)\n        else\n          covariance_slow(v1a,v2a)\n        end\n      end\n      # Estimate the ML between two dichotomic vectors\n      def maximum_likehood_dichotomic(pred,real)\n        preda,reala=Statsample.only_valid_clone(pred,real)                \n        sum=0\n        preda.each_index{|i|\n           sum+=(reala[i]*Math::log(preda[i])) + ((1-reala[i])*Math::log(1-preda[i]))\n        }\n        sum\n      end\n      \n      def covariance_slow(v1,v2) # :nodoc:\n        v1a,v2a=Statsample.only_valid(v1,v2)\n        sum_of_squares(v1a,v2a) / (v1a.size-1)\n      end\n      def sum_of_squares(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)        \n        m1=v1a.mean\n        m2=v2a.mean\n        (v1a.size).times.inject(0) {|ac,i| ac+(v1a[i]-m1)*(v2a[i]-m2)}\n      end\n      # Calculate Pearson correlation coefficient (r) between 2 vectors\n      def pearson(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        return nil if v1a.size ==0\n        if Statsample.has_gsl?\n          GSL::Stats::correlation(v1a.gsl, v2a.gsl)\n        else\n          pearson_slow(v1a,v2a)\n        end\n      end\n      def pearson_slow(v1,v2) # :nodoc:\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        # Calculate sum of squares\n        ss=sum_of_squares(v1a,v2a)\n        ss.quo(Math::sqrt(v1a.sum_of_squares) * Math::sqrt(v2a.sum_of_squares))\n      end\n      alias :correlation :pearson\n      # Retrieves the value for t test for a pearson correlation\n      # between two vectors to test the null hipothesis of r=0\n      def t_pearson(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        r=pearson(v1a,v2a)\n        if(r==1.0) \n          0\n        else\n          t_r(r,v1a.size)\n        end\n      end\n      # Retrieves the value for t test for a pearson correlation\n      # giving r and vector size\n      # Source : http://faculty.chass.ncsu.edu/garson/PA765/correl.htm\n      def t_r(r,size)\n        r * Math::sqrt(((size)-2).to_f / (1 - r**2))\n      end\n      # Retrieves the probability value (a la SPSS)\n      # for a given t, size and number of tails.\n      # Uses a second parameter \n      # * :both  or 2  : for r!=0 (default)\n      # * :right, :positive or 1  : for r > 0\n      # * :left, :negative        : for r < 0\n      \n      def prop_pearson(t, size, tails=:both)\n        tails=:both if tails==2\n        tails=:right if tails==1 or tails==:positive\n        tails=:left if tails==:negative\n        \n        n_tails=case tails\n          when :both then 2\n          else 1\n        end\n        t=-t if t>0 and (tails==:both)\n        cdf=Distribution::T.cdf(t, size-2)\n        if(tails==:right)\n          1.0-(cdf*n_tails)\n        else\n          cdf*n_tails\n        end\n      end\n      \n      \n      # Predicted time for pairwise correlation matrix, in miliseconds\n      # See benchmarks/correlation_matrix.rb to see mode of calculation\n      \n      def prediction_pairwise(vars,cases)\n        ((-0.518111-0.000746*cases+1.235608*vars+0.000740*cases*vars)**2) / 100\n      end\n      # Predicted time for optimized correlation matrix, in miliseconds\n      # See benchmarks/correlation_matrix.rb to see mode of calculation\n      \n      def prediction_optimized(vars,cases)\n        ((4+0.018128*cases+0.246871*vars+0.001169*vars*cases)**2) / 100\n      end\n      # Returns residual score after delete variance\n      # from another variable\n      # \n      def residuals(from,del)\n        r=Statsample::Bivariate.pearson(from,del)\n        froms, dels = from.vector_standarized, del.vector_standarized\n        nv=[]\n        froms.data_with_nils.each_index do |i|\n          if froms[i].nil? or dels[i].nil?\n            nv.push(nil)\n          else\n            nv.push(froms[i]-r*dels[i])\n          end\n        end\n        nv.to_vector(:scale)\n      end\n      # Correlation between v1 and v2, controling the effect of\n      # control on both.\n      def partial_correlation(v1,v2,control)\n        v1a,v2a,cona=Statsample.only_valid_clone(v1,v2,control)\n        rv1v2=pearson(v1a,v2a)\n        rv1con=pearson(v1a,cona)\n        rv2con=pearson(v2a,cona)        \n        (rv1v2-(rv1con*rv2con)).quo(Math::sqrt(1-rv1con**2) * Math::sqrt(1-rv2con**2))\n        \n      end\n      \n      def covariance_matrix_optimized(ds)\n        x=ds.to_gsl\n        n=x.row_size\n        m=x.column_size\n        means=((1/n.to_f)*GSL::Matrix.ones(1,n)*x).row(0)\n        centered=x-(GSL::Matrix.ones(n,m)*GSL::Matrix.diag(means))\n        ss=centered.transpose*centered\n        s=((1/(n-1).to_f))*ss\n        s\n      end\n      \n      # Covariance matrix.\n      # Order of rows and columns depends on Dataset#fields order\n      \n      def covariance_matrix(ds)\n        vars,cases=ds.fields.size,ds.cases\n        if !ds.has_missing_data? and Statsample.has_gsl? and prediction_optimized(vars,cases) < prediction_pairwise(vars,cases)\n          cm=covariance_matrix_optimized(ds)\n        else\n          cm=covariance_matrix_pairwise(ds)\n          \n        end\n        cm.extend(Statsample::CovariateMatrix)\n        cm.fields=ds.fields\n        cm\n      end\n      \n      \n      def covariance_matrix_pairwise(ds)\n        cache={}\n        matrix=ds.collect_matrix do |row,col|\n          if (ds[row].type!=:scale or ds[col].type!=:scale)\n            nil\n          elsif row==col\n            ds[row].variance\n          else\n            if cache[[col,row]].nil?\n              cov=covariance(ds[row],ds[col])\n              cache[[row,col]]=cov\n              cov\n            else\n               cache[[col,row]]\n            end\n          end\n        end\n        matrix\n      end\n      \n      # Correlation matrix.\n      # Order of rows and columns depends on Dataset#fields order\n      def correlation_matrix(ds)\n        vars,cases=ds.fields.size,ds.cases\n        if !ds.has_missing_data? and Statsample.has_gsl? and prediction_optimized(vars,cases) < prediction_pairwise(vars,cases)\n          cm=correlation_matrix_optimized(ds)\n        else\n          cm=correlation_matrix_pairwise(ds)\n        end\n        cm.extend(Statsample::CovariateMatrix)\n        cm.fields=ds.fields\n        cm\n      end\n\n      def correlation_matrix_optimized(ds)\n        s=covariance_matrix_optimized(ds)\n        sds=GSL::Matrix.diagonal(s.diagonal.sqrt.pow(-1))\n        cm=sds*s*sds\n        # Fix diagonal\n        s.row_size.times {|i|\n          cm[i,i]=1.0\n        }\n        cm\n      end\n      def correlation_matrix_pairwise(ds)\n        cache={}\n        cm=ds.collect_matrix do |row,col|\n          if row==col\n            1.0\n          elsif (ds[row].type!=:scale or ds[col].type!=:scale)\n            nil\n          else\n            if cache[[col,row]].nil?\n              r=pearson(ds[row],ds[col])\n              cache[[row,col]]=r\n              r\n            else\n              cache[[col,row]]\n            end \n          end\n        end\n      end\n      \n      # Retrieves the n valid pairwise.\n      def n_valid_matrix(ds)\n        ds.collect_matrix do |row,col|\n          if row==col\n            ds[row].valid_data.size\n          else\n            rowa,rowb=Statsample.only_valid_clone(ds[row],ds[col])\n            rowa.size\n          end\n        end\n      end\n      \n      # Matrix of correlation probabilities.\n      # Order of rows and columns depends on Dataset#fields order\n      \n      def correlation_probability_matrix(ds, tails=:both)\n        rows=ds.fields.collect do |row|\n          ds.fields.collect do |col|\n            v1a,v2a=Statsample.only_valid_clone(ds[row],ds[col])\n            (row==col or ds[row].type!=:scale or ds[col].type!=:scale) ? nil : prop_pearson(t_pearson(ds[row],ds[col]), v1a.size, tails)\n          end\n        end\n        Matrix.rows(rows)\n      end\n      \n      # Spearman ranked correlation coefficient (rho) between 2 vectors\n      def spearman(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        v1r,v2r=v1a.ranked(:scale),v2a.ranked(:scale)\n        pearson(v1r,v2r)\n      end\n      # Calculate Point biserial correlation. Equal to Pearson correlation, with\n      # one dichotomous value replaced by \"0\" and the other by \"1\"\n      def point_biserial(dichotomous,continous)\n        ds={'d'=>dichotomous,'c'=>continous}.to_dataset.dup_only_valid\n        raise(TypeError, \"First vector should be dichotomous\") if ds['d'].factors.size!=2\n        raise(TypeError, \"Second vector should be continous\") if ds['c'].type!=:scale\n        f0=ds['d'].factors.sort[0]\n        m0=ds.filter_field('c') {|c| c['d']==f0}\n        m1=ds.filter_field('c') {|c| c['d']!=f0}\n        ((m1.mean-m0.mean).to_f / ds['c'].sdp) * Math::sqrt(m0.size*m1.size.to_f / ds.cases**2)\n      end\n      # Kendall Rank Correlation Coefficient (Tau a)\n      # Based on Hervé Adbi article\n      def tau_a(v1,v2)\n        v1a,v2a=Statsample.only_valid_clone(v1,v2)\n        n=v1.size\n        v1r,v2r=v1a.ranked(:scale),v2a.ranked(:scale)\n        o1=ordered_pairs(v1r)\n        o2=ordered_pairs(v2r)\n        delta= o1.size*2-(o2  & o1).size*2\n        1-(delta * 2 / (n*(n-1)).to_f)\n      end\n      # Calculates Goodman and Kruskal’s Tau b correlation.\n      # Tb is an asymmetric P-R-E measure of association for nominal scales \n      # (Mielke, X)\n      # \n      # Tau-b defines perfect association as strict monotonicity. Although it\n      # requires strict monotonicity to reach 1.0, it does not penalize ties as\n      # much as some other measures.\n      # == Reference\n      # Mielke, P. GOODMAN–KRUSKAL TAU AND GAMMA. \n      # Source: http://faculty.chass.ncsu.edu/garson/PA765/assocordinal.htm\n      def tau_b(matrix)\n        v=pairs(matrix)\n        ((v['P']-v['Q']).to_f / Math::sqrt((v['P']+v['Q']+v['Y'])*(v['P']+v['Q']+v['X'])).to_f)\n      end\n      # Calculates Goodman and Kruskal's gamma.\n      #\n      # Gamma is the surplus of concordant pairs over discordant pairs, as a\n      # percentage of all pairs ignoring ties.\n      #\n      # Source: http://faculty.chass.ncsu.edu/garson/PA765/assocordinal.htm\n      def gamma(matrix)\n        v=pairs(matrix)\n        (v['P']-v['Q']).to_f / (v['P']+v['Q']).to_f\n      end\n      # Calculate indexes for a matrix the rows and cols has to be ordered\n      def pairs(matrix)\n        # calculate concordant #p matrix\n        rs=matrix.row_size\n        cs=matrix.column_size\n        conc=disc=ties_x=ties_y=0\n        (0...(rs-1)).each do |x|\n          (0...(cs-1)).each do |y|\n            ((x+1)...rs).each do |x2|\n              ((y+1)...cs).each do |y2|\n                # #p sprintf(\"%d:%d,%d:%d\",x,y,x2,y2)\n                conc+=matrix[x,y]*matrix[x2,y2]\n              end\n            end\n          end\n        end\n        (0...(rs-1)).each {|x|\n          (1...(cs)).each{|y|\n            ((x+1)...rs).each{|x2|\n              (0...y).each{|y2|\n                # #p sprintf(\"%d:%d,%d:%d\",x,y,x2,y2)\n                disc+=matrix[x,y]*matrix[x2,y2]\n              }\n            }\n          }\n        }\n        (0...(rs-1)).each {|x|\n          (0...(cs)).each{|y|\n            ((x+1)...(rs)).each{|x2|\n              ties_x+=matrix[x,y]*matrix[x2,y]\n            }\n          }\n        }\n        (0...rs).each {|x|\n          (0...(cs-1)).each{|y|\n            ((y+1)...(cs)).each{|y2|\n              ties_y+=matrix[x,y]*matrix[x,y2]\n            }\n          }\n        }\n        {'P'=>conc,'Q'=>disc,'Y'=>ties_y,'X'=>ties_x}\n      end\n      def ordered_pairs(vector)\n        d=vector.data\n        a=[]\n        (0...(d.size-1)).each{|i|\n          ((i+1)...(d.size)).each {|j|\n            a.push([d[i],d[j]])\n          }\n        }\n        a\n      end\n=begin      \n      def sum_of_codeviated(v1,v2)\n        v1a,v2a=Statsample.only_valid(v1,v2)\n        sum=0\n        (0...v1a.size).each{|i|\n          sum+=v1a[i]*v2a[i]\n        }\n        sum-((v1a.sum*v2a.sum) / v1a.size.to_f)\n      end\n=end\n      # Report the minimum number of cases valid of a covariate matrix\n      # based on a dataset\n      def min_n_valid(ds)\n        min=ds.cases\n        m=n_valid_matrix(ds)\n        for x in 0...m.row_size\n          for y in 0...m.column_size\n            min=m[x,y] if m[x,y] < min\n          end\n        end\n        min\n      end\n      \n      \n    end\n  end\nend\n\n\n"
  },
  {
    "path": "lib/statsample/codification.rb",
    "content": "require 'yaml'\n\nmodule Statsample\n  # This module aids to code open questions\n  # * Select one or more vectors of a dataset, to create a yaml files, on which each vector is a hash, which keys and values are the vector's factors . If data have Statsample::SPLIT_TOKEN on a value, each value will be separated on two or more hash keys.\n  # * Edit the yaml and replace the values of hashes with your codes. If you need to create two or mores codes for an answer, use the separator (default Statsample::SPLIT_TOKEN)\n  # * Recode the vectors, loading the yaml file:\n  #   * recode_dataset_simple!() : The new vectors have the same name of the original plus \"_recoded\"\n  #   * recode_dataset_split!() : Create equal number of vectors as values. See Vector.add_vectors_by_split() for arguments\n  #\n  # Usage:\n  #   recode_file=\"recodification.yaml\"\n  #   phase=:first # flag\n  #   if phase==:first\n  #     File.open(recode_file,\"w\") {|fp|\n  #       Statsample::Codification.create_yaml(ds,%w{vector1 vector2}, \",\",fp)\n  #     }\n  #   # Edit the file recodification.yaml and verify changes\n  #   elsif phase==:second\n  #     File.open(recode_file,\"r\") {|fp|\n  #       Statsample::Codification.verify(fp,['vector1'])\n  #     }\n  #   # Add new vectors to the dataset\n  #   elsif phase==:third\n  #     File.open(recode_file,\"r\") {|fp|\n  #       Statsample::Codification.recode_dataset_split!(ds,fp,\"*\")\n  #     }\n  #   end\n  #\n  module Codification\n    class << self\n      # Create a hash, based on vectors, to create the dictionary.\n      # The keys will be vectors name on dataset and the values\n      # will be hashes, with keys = values, for recodification\n      def create_hash(dataset, vectors, sep=Statsample::SPLIT_TOKEN)\n        raise ArgumentError,\"Array should't be empty\" if vectors.size==0\n        pro_hash=vectors.inject({}){|h,v_name|\n          raise Exception, \"Vector #{v_name} doesn't exists on Dataset\" if !dataset.fields.include? v_name\n          v=dataset[v_name]\n          split_data=v.splitted(sep).flatten.collect {|c| c.to_s}.find_all {|c| !c.nil?}\n\n          factors=split_data.uniq.compact.sort.inject({}) {|ac,val| ac[val]=val;ac }\n          h[v_name]=factors\n          h\n        }\n        pro_hash\n      end\n      # Create a yaml to create a dictionary, based on vectors\n      # The keys will be vectors name on dataset and the values\n      # will be hashes, with keys = values, for recodification\n      #\n      #   v1=%w{a,b b,c d}.to_vector\n      #   ds={\"v1\"=>v1}.to_dataset\n      #   Statsample::Codification.create_yaml(ds,['v1'])\n      #   => \"--- \\nv1: \\n  a: a\\n  b: b\\n  c: c\\n  d: d\\n\"\n      def create_yaml(dataset, vectors, io=nil, sep=Statsample::SPLIT_TOKEN)\n        pro_hash=create_hash(dataset, vectors, sep)\n        YAML.dump(pro_hash,io)\n      end\n      # Create a excel to create a dictionary, based on vectors.\n      # Raises an error if filename exists\n      # The rows will be:\n      # * field: name of vector\n      # * original: original name\n      # * recoded: new code\n\n      def create_excel(dataset, vectors, filename, sep=Statsample::SPLIT_TOKEN)\n        require 'spreadsheet'\n        if File.exist?(filename)\n          raise \"Exists a file named #{filename}. Delete ir before overwrite.\"\n        end\n        book = Spreadsheet::Workbook.new\n        sheet = book.create_worksheet\n        sheet.row(0).concat(%w{field original recoded})\n        i=1\n        create_hash(dataset, vectors, sep).sort.each do |field, inner_hash|\n          inner_hash.sort.each do |k,v|\n            sheet.row(i).concat([field.dup,k.dup,v.dup])\n            i+=1\n          end\n        end\n        book.write(filename)\n      end\n      # From a excel generates a dictionary hash\n      # to use on recode_dataset_simple!() or recode_dataset_split!().\n      #\n      def excel_to_recoded_hash(filename)\n        require 'spreadsheet'\n        h={}\n        book = Spreadsheet.open filename\n        sheet= book.worksheet 0\n        row_i=0\n        sheet.each do |row|\n          row_i+=1\n          next if row_i==1 or row[0].nil? or row[1].nil? or row[2].nil?\n          h[row[0]]={} if h[row[0]].nil?\n          h[row[0]][row[1]]=row[2]\n        end\n        h\n      end\n\n      def inverse_hash(h, sep=Statsample::SPLIT_TOKEN)\n        h.inject({}) do |a,v|\n          v[1].split(sep).each do |val|\n            a[val]||=[]\n            a[val].push(v[0])\n          end\n          a\n        end\n      end\n\n      def dictionary(h, sep=Statsample::SPLIT_TOKEN)\n        h.inject({}) {|a,v| a[v[0]]=v[1].split(sep); a }\n      end\n\n      def recode_vector(v,h,sep=Statsample::SPLIT_TOKEN)\n        dict=dictionary(h,sep)\n        new_data=v.splitted(sep)\n        new_data.collect do |c|\n          if c.nil?\n            nil\n          else\n            c.collect{|value| dict[value] }.flatten.uniq\n          end\n        end\n      end\n      def recode_dataset_simple!(dataset, dictionary_hash ,sep=Statsample::SPLIT_TOKEN)\n        _recode_dataset(dataset,dictionary_hash ,sep,false)\n      end\n      def recode_dataset_split!(dataset, dictionary_hash, sep=Statsample::SPLIT_TOKEN)\n        _recode_dataset(dataset, dictionary_hash, sep,true)\n      end\n\n      def _recode_dataset(dataset, h , sep=Statsample::SPLIT_TOKEN, split=false)\n        v_names||=h.keys\n        v_names.each do |v_name|\n          raise Exception, \"Vector #{v_name} doesn't exists on Dataset\" if !dataset.fields.include? v_name\n          recoded=recode_vector(dataset[v_name], h[v_name],sep).collect { |c|\n            if c.nil?\n              nil\n            else\n              c.join(sep)\n            end\n          }.to_vector\n          if(split)\n            recoded.split_by_separator(sep).each {|k,v|\n              dataset[v_name+\"_\"+k]=v\n            }\n          else\n            dataset[v_name+\"_recoded\"]=recoded\n          end\n        end\n      end\n\n\n      def verify(h, v_names=nil,sep=Statsample::SPLIT_TOKEN,io=$>)\n        require 'pp'\n        v_names||=h.keys\n        v_names.each{|v_name|\n          inverse=inverse_hash(h[v_name],sep)\n          io.puts \"- Field: #{v_name}\"\n          inverse.sort{|a,b| -(a[1].count<=>b[1].count)}.each {|k,v|\n            io.puts \"  - \\\"#{k}\\\" (#{v.count}) :\\n    -'\"+v.join(\"\\n    -'\")+\"'\"\n          }\n        }\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/converter/csv.rb",
    "content": "module Statsample\n  class CSV < SpreadsheetBase\n    if RUBY_VERSION<\"1.9\"\n      require 'fastercsv'\n      CSV_klass=::FasterCSV  \n    else\n      require 'csv'\n      CSV_klass=::CSV  \n    end    \n    class << self\n\n      def read19(filename,ignore_lines=0,csv_opts=Hash.new)\n        #default first line is header\n        csv_opts.merge!(:headers=>true, :header_converters => :symbol)\n        csv = CSV_klass::Table.new(CSV_klass::read(filename,'r',csv_opts))\n        csv_headers = if csv_opts[:headers]\n          csv.headers\n        else\n          #as in R, if no header we name the headers as V1,V2,V3,V4,..\n          1.upto(csv.first.length).collect { |i| \"V#{i}\" }\n        end\n        #we invert row -> column. It means csv[0] is the first column and not row. Similar to R\n        csv.by_col!\n        thash = {}\n        csv_headers.each_with_index do |header,idx|\n          thash[header] = Statsample::Vector.new(csv[idx].drop(ignore_lines))\n        end\n        Statsample::Dataset.new(thash)\n      end\n      # Returns a Dataset  based on a csv file\n      #\n      # USE:\n      #     ds=Statsample::CSV.read(\"test_csv.csv\")\n      def read(filename, empty=[''],ignore_lines=0,csv_opts=Hash.new)        \n        first_row=true\n        fields=[]\n        #fields_data={}\n        ds=nil\n        line_number=0\n        csv=CSV_klass.open(filename,'rb', csv_opts)\n        csv.each do |row|\n          line_number+=1\n          if(line_number<=ignore_lines)\n            #puts \"Skip line\"\n            next\n          end\n          row.collect!{|c| c.to_s }\n          if first_row\n            fields=extract_fields(row)\n            ds=Statsample::Dataset.new(fields)\n            first_row=false\n          else\n            rowa=process_row(row,empty)\n            ds.add_case(rowa,false)\n          end\n        end\n        convert_to_scale_and_date(ds,fields)\n        ds.update_valid_data\n        ds\n      end\n      # Save a Dataset on a csv file\n      #\n      # USE:\n      #     Statsample::CSV.write(ds,\"test_csv.csv\")\n      def write(dataset,filename, convert_comma=false,*opts)\n        \n        writer=CSV_klass.open(filename,'w',*opts)\n        writer << dataset.fields\n        dataset.each_array do|row|\n          if(convert_comma)\n            row.collect!{|v| v.to_s.gsub(\".\",\",\")}\n          end\n          writer << row\n        end\n        writer.close\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/converter/spss.rb",
    "content": "module Statsample\n  module SPSS\n    class << self\n      # Export a SPSS Matrix with tetrachoric correlations .\n      #\n      # Use: \n      #   ds=Statsample::Excel.read(\"my_data.xls\")\n      #   puts Statsample::SPSS.tetrachoric_correlation_matrix(ds)\n      def tetrachoric_correlation_matrix(ds)\n        dsv=ds.dup_only_valid\n        # Delete all vectors doesn't have variation\n        dsv.fields.each{|f|\n          if dsv[f].factors.size==1\n            dsv.delete_vector(f) \n          else\n            dsv[f]=dsv[f].dichotomize\n          end\n        }\n        tcm=Statsample::Bivariate.tetrachoric_correlation_matrix(dsv)\n        n=dsv.fields.collect {|f|\n          sprintf(\"%d\",dsv[f].size)\n        }\n        meanlist=dsv.fields.collect{|f|\n          sprintf(\"%0.3f\", dsv[f].mean)\n        }\n        stddevlist=dsv.fields.collect{|f|\n          sprintf(\"%0.3f\", dsv[f].sd)\n        }\n        out=<<-HEREDOC\nMATRIX DATA VARIABLES=ROWTYPE_ #{dsv.fields.join(\",\")}.\nBEGIN DATA\nN #{n.join(\" \")}\nMEAN\t#{meanlist.join(\" \")}\nSTDDEV #{stddevlist.join(\" \")}\nHEREDOC\ntcm.row_size.times {|i|\n  out +=\"CORR \"\n  (i+1).times {|j|\n    out+=sprintf(\"%0.3f\",tcm[i,j])+\" \"\n  }\n  out +=\"\\n\"\n}\nout+=\"END DATA.\\nEXECUTE.\\n\"\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/converters.rb",
    "content": "require 'statsample/converter/spss'\nmodule Statsample\n    # Create and dumps Datasets on a database\n  module Database\n    class << self\n      # Read a database query and returns a Dataset\n      #\n      # USE:\n      #\n      #  dbh = DBI.connect(\"DBI:Mysql:database:localhost\", \"user\", \"password\")\n      #  Statsample.read(dbh, \"SELECT * FROM test\")\n      #\n      def read(dbh,query)\n        require 'dbi'\n        sth=dbh.execute(query)\n        vectors={}\n        fields=[]\n        sth.column_info.each {|c|\n            vectors[c['name']]=Statsample::Vector.new([])\n            vectors[c['name']].name=c['name']\n            vectors[c['name']].type= (c['type_name']=='INTEGER' or c['type_name']=='DOUBLE') ? :scale : :nominal\n            fields.push(c['name'])\n        }\n        ds=Statsample::Dataset.new(vectors,fields)\n        sth.fetch do |row|\n            ds.add_case(row.to_a, false )\n        end\n        ds.update_valid_data\n        ds\n      end\n      # Insert each case of the Dataset on the selected table\n      #\n      # USE:\n      #        \n      #  ds={'id'=>[1,2,3].to_vector, 'name'=>[\"a\",\"b\",\"c\"].to_vector}.to_dataset\n      #  dbh = DBI.connect(\"DBI:Mysql:database:localhost\", \"user\", \"password\")\n      #  Statsample::Database.insert(ds,dbh,\"test\")\n      #\n      def insert(ds, dbh, table)\n        require 'dbi'            \n        query=\"INSERT INTO #{table} (\"+ds.fields.join(\",\")+\") VALUES (\"+(([\"?\"]*ds.fields.size).join(\",\"))+\")\"\n        sth=dbh.prepare(query)\n        ds.each_array{|c| sth.execute(*c) }\n        return true\n      end\n      # Create a sql, basen on a given Dataset\n      #\n      # USE:\n      #        \n      #  ds={'id'=>[1,2,3,4,5].to_vector,'name'=>%w{Alex Peter Susan Mary John}.to_vector}.to_dataset\n      #  Statsample::Database.create_sql(ds,'names')\n      #   ==>\"CREATE TABLE names (id INTEGER,\\n name VARCHAR (255)) CHARACTER SET=UTF8;\"\n      # \n      def create_sql(ds,table,charset=\"UTF8\")\n        sql=\"CREATE TABLE #{table} (\"\n        fields=ds.fields.collect{|f|\n            v=ds[f]\n            f+\" \"+v.db_type\n        }\n        sql+fields.join(\",\\n \")+\") CHARACTER SET=#{charset};\"\n      end\n    end\n  end\n  module Mondrian\n    class << self\n      def write(dataset,filename)\n        File.open(filename,\"wb\") do |fp|\n          fp.puts dataset.fields.join(\"\\t\")\n          dataset.each_array_with_nils do |row|\n            row2=row.collect{|v| v.nil? ? \"NA\" : v.to_s.gsub(/\\s+/,\"_\") }\n            fp.puts row2.join(\"\\t\")\n          end\n        end\n      end\n    end\n  end\n  class SpreadsheetBase\n    class << self\n      def extract_fields(row)\n        i=0;\n        fields=row.to_a.collect{|c|\n          if c.nil?\n            i+=1\n            \"var%05d\" % i \n          else\n            c.to_s.downcase\n          end        \n        }\n        fields.recode_repeated\n      end\n                                         \n      def process_row(row,empty)\n        row.to_a.map do |c|\n          if empty.include?(c)\n              nil\n          else\n            if c.is_a? String and c.is_number?\n              if c=~/^\\d+$/\n                c.to_i\n              else\n                c.gsub(\",\",\".\").to_f\n              end\n            else\n              c\n            end\n          end\n        end\n      end\n      def convert_to_scale_and_date(ds,fields)\n        fields.each do |f|\n          if ds[f].can_be_scale?\n            ds[f].type=:scale\n          elsif ds[f].can_be_date?\n            ds[f].type=:date\n          end\n        end\n      end\n    \n    end\n  end\n    class PlainText < SpreadsheetBase\n      class << self\n        def read(filename, fields)\n          ds=Statsample::Dataset.new(fields)\n          fp=File.open(filename,\"r\")\n          fp.each_line do |line|\n            row=process_row(line.strip.split(/\\s+/),[\"\"])\n            next if row==[\"\\x1A\"]\n            ds.add_case_array(row)\n          end\n          convert_to_scale_and_date(ds,fields)\n          ds.update_valid_data\n          fields.each {|f|\n            ds[f].name=f\n          }\n          ds\n        end\n      end\n    end\n  class Excel < SpreadsheetBase \n    class << self\n      # Write a Excel spreadsheet based on a dataset\n      # * TODO: Format nicely date values\n      def write(dataset,filename)\n        require 'spreadsheet'\n        book = Spreadsheet::Workbook.new\n        sheet = book.create_worksheet\n        format = Spreadsheet::Format.new :color => :blue,\n                           :weight => :bold\n        sheet.row(0).concat(dataset.fields.map {|i| i.dup}) # Unfreeze strings\n        sheet.row(0).default_format = format\n        i=1\n        dataset.each_array{|row|\n          sheet.row(i).concat(row)\n          i+=1\n        }\n        book.write(filename)\n      end\n      # This should be fixed.\n      # If we have a Formula, should be resolver first\n\n      def preprocess_row(row, dates)\n        i=-1\n        row.collect!{|c|\n          i+=1\n          if c.is_a? Spreadsheet::Formula\n            if(c.value.is_a? Spreadsheet::Excel::Error)\n              nil\n            else\n              c.value\n            end\n          elsif dates.include? i and !c.nil? and c.is_a? Numeric\n              row.date(i)\n          else\n              c\n          end\n        }\n      end\n      private :process_row, :preprocess_row\n      \n      # Returns a dataset based on a xls file\n      # USE:\n      #     ds = Statsample::Excel.read(\"test.xls\")\n      #\n      def read(filename, opts=Hash.new)\n        require 'spreadsheet'\n        raise \"options should be Hash\" unless opts.is_a? Hash\n        opts_default={\n          :worksheet_id=>0, \n          :ignore_lines=>0, \n          :empty=>['']\n        }\n        \n        opts=opts_default.merge opts\n        \n        worksheet_id=opts[:worksheet_id]\n        ignore_lines=opts[:ignore_lines]\n        empty=opts[:empty]\n        \n        first_row=true\n        fields=[]\n        fields_data={}\n        ds=nil\n        line_number=0\n        book = Spreadsheet.open filename\n        sheet= book.worksheet worksheet_id\n        sheet.each do |row|\n          begin\n            dates=[]\n            row.formats.each_index{|i|\n              if !row.formats[i].nil? and row.formats[i].number_format==\"DD/MM/YYYY\"\n                dates.push(i)\n              end\n            }\n            line_number+=1\n            next if(line_number<=ignore_lines)\n            \n            preprocess_row(row,dates)\n            if first_row\n              fields=extract_fields(row)\n              ds=Statsample::Dataset.new(fields)\n              first_row=false\n            else\n              rowa=process_row(row,empty)\n              (fields.size - rowa.size).times {\n                rowa << nil\n              }\n              ds.add_case(rowa,false)\n            end\n          rescue => e\n            error=\"#{e.to_s}\\nError on Line # #{line_number}:#{row.join(\",\")}\"\n            raise\n          end\n        end\n        convert_to_scale_and_date(ds, fields)\n        ds.update_valid_data\n        fields.each {|f|\n          ds[f].name=f\n        }\n        ds.name=filename\n        ds\n      end\n    end\n  end\n  module Mx\n    class << self\n      def write(dataset,filename,type=:covariance)\n        puts \"Writing MX File\"\n        File.open(filename,\"w\") do |fp|\n          fp.puts \"! #{filename}\"\n          fp.puts \"! Output generated by Statsample\"\n          fp.puts \"Data Ninput=#{dataset.fields.size} Nobservations=#{dataset.cases}\"\n          fp.puts \"Labels \"+dataset.fields.join(\" \")\n          case type\n            when :raw\n            fp.puts \"Rectangular\"\n            dataset.each do |row|\n              out=dataset.fields.collect do |f|\n                if dataset[f].is_valid? row[f]\n                  row[f]\n                else\n                  \".\"\n                end\n              end\n              fp.puts out.join(\"\\t\")\n            end\n            fp.puts \"End Rectangular\"\n          when :covariance\n            fp.puts \" CMatrix Full\"\n            cm=Statsample::Bivariate.covariance_matrix(dataset)\n            d=(0...(cm.row_size)).collect {|row|\n              (0...(cm.column_size)).collect{|col|\n                cm[row,col].nil? ? \".\" : sprintf(\"%0.3f\", cm[row,col])\n              }.join(\" \")\n            }.join(\"\\n\")\n            fp.puts d\n          end\n        end\n      end\n    end\n  end\n\tmodule GGobi\n\t\tclass << self\n      def write(dataset,filename,opt={})\n        File.open(filename,\"w\") {|fp|\n          fp.write(self.out(dataset,opt))\n        }\n      end\n\t\t\tdef out(dataset,opt={})\n\t\t\t\trequire 'ostruct'\n\t\t\t\tdefault_opt = {:dataname => \"Default\", :description=>\"\", :missing=>\"NA\"}\n\t\t\t\tdefault_opt.merge! opt\n\t\t\t\tcarrier=OpenStruct.new\n\t\t\t\tcarrier.categorials=[]\n\t\t\t\tcarrier.conversions={}\n\t\t\t\tvariables_def=dataset.fields.collect{|k|\n\t\t\t\t\tvariable_definition(carrier,dataset[k],k)\n\t\t\t\t}.join(\"\\n\")\n\t\t\t\t\n\t\t\t\tindexes=carrier.categorials.inject({}) {|s,c|\n\t\t\t\t\ts[dataset.fields.index(c)]=c\n\t\t\t\t\ts\n\t\t\t\t}\n\t\t\t\trecords=\"\"\n\t\t\t\tdataset.each_array {|c|\n\t\t\t\t\tindexes.each{|ik,iv|\n\t\t\t\t\t\tc[ik]=carrier.conversions[iv][c[ik]]\n\t\t\t\t\t}\n\t\t\t\t\trecords << \"<record>#{values_definition(c, default_opt[:missing])}</record>\\n\"\n\t\t\t\t}\n\t\t\t\t\nout=<<EOC\n<?xml version=\"1.0\"?>\n<!DOCTYPE ggobidata SYSTEM \"ggobi.dtd\">\n<ggobidata count=\"1\">\n<data name=\"#{default_opt[:dataname]}\">\n<description>#{default_opt[:description]}</description>\n<variables count=\"#{dataset.fields.size}\">\n#{variables_def}\n</variables>\n    <records count=\"#{dataset.cases}\" missingValue=\"#{default_opt[:missing]}\">\n#{records}\n</records>\n\n</data>\n</ggobidata>\nEOC\n\nout\n\n\t\t\tend\n      def values_definition(c,missing)\n        c.collect{|v|\n          if v.nil?\n            \"#{missing}\"\n          elsif v.is_a? Numeric\n            \"#{v}\"\n          else\n            \"#{v.gsub(/\\s+/,\"_\")}\"\n          end\n        }.join(\" \")\n      end\n\t\t\t# Outputs a string for a variable definition\n\t\t\t# v = vector\n\t\t\t# name = name of the variable\n\t\t\t# nickname = nickname\n\t\t\tdef variable_definition(carrier,v,name,nickname=nil)\n\t\t\t\tnickname = (nickname.nil? ? \"\" : \"nickname=\\\"#{nickname}\\\"\" )\n\t\t\t\tif v.type==:nominal or v.data.find {|d|  d.is_a? String }\n\t\t\t\t\tcarrier.categorials.push(name)\n\t\t\t\t\tcarrier.conversions[name]={}\n\t\t\t\t\tfactors=v.factors\n\t\t\t\t\tout =\"<categoricalvariable name=\\\"#{name}\\\" #{nickname}>\\n\"\n\t\t\t\t\tout << \"<levels count=\\\"#{factors.size}\\\">\\n\"\n\t\t\t\t\tout << (1..factors.size).to_a.collect{|i|\n\t\t\t\t\t\tcarrier.conversions[name][factors[i-1]]=i\n\t\t\t\t\t\t\"<level value=\\\"#{i}\\\">#{v.labeling(factors[i-1])}</level>\"\n\t\t\t\t\t}.join(\"\\n\")\n\t\t\t\t\tout << \"</levels>\\n</categoricalvariable>\\n\"\n\t\t\t\t\tout\n\t\t\t\telsif v.data.find {|d| d.is_a? Float}\n\t\t\t\t\t\"<realvariable name=\\\"#{name}\\\" #{nickname} />\"\n\t\t\t\telse\n\t\t\t\t\t\"<integervariable name=\\\"#{name}\\\" #{nickname} />\"\n\t\t\t\tend\n\t\t\tend\n\n\t\tend\n\tend\nend\n\nrequire 'statsample/converter/csv.rb'\n\n"
  },
  {
    "path": "lib/statsample/crosstab.rb",
    "content": "module Statsample\n\t# Class to create crosstab of data\n\t# With this, you can create reports and do chi square test\n\t# The first vector will be at rows and the second will the the columns\n\t#\n  class Crosstab\n    include Summarizable\n    attr_reader :v_rows, :v_cols\n    attr_accessor :row_label, :column_label, :name, :percentage_row, :percentage_column, :percentage_total\n    def initialize(v1, v2, opts=Hash.new)\n      #raise ArgumentError, \"Both arguments should be Vectors\" unless v1.is_a? Statsample::Vector and v2.is_a? Statsample::Vector\n      raise ArgumentError, \"Vectors should be the same size\" unless v1.size==v2.size\n      @v_rows, @v_cols=Statsample.only_valid_clone(v1.to_vector,v2.to_vector)\n      @cases=@v_rows.size\n      @row_label=v1.name\n      @column_label=v2.name\n      @name=nil\n      @percentage_row = @percentage_column = @percentage_total=false\n      opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n      }\n      @name||=_(\"Crosstab %s - %s\") % [@row_label, @column_label]\n    end\t\n    def rows_names\n      @v_rows.factors.sort\n    end\n    def cols_names\n      @v_cols.factors.sort\n    end\n    def rows_total\n      @v_rows.frequencies\n    end\n    def cols_total\n      @v_cols.frequencies\n    end\n    \n    def frequencies\n      base=rows_names.inject([]){|s,row| \n        s+=cols_names.collect{|col| [row,col]}\n      }.inject({}) {|s,par|\n        s[par]=0\n        s\n      }\n      base.update(Statsample::vector_cols_matrix(@v_rows,@v_cols).to_a.to_vector.frequencies)\n    end\n    def to_matrix\n      f=frequencies\n      rn=rows_names\n      cn=cols_names\n      Matrix.rows(rn.collect{|row|\n          cn.collect{|col| f[[row,col]]}\n      })\n    end\n    def frequencies_by_row\n    f=frequencies\n    rows_names.inject({}){|sr,row|\n      sr[row]=cols_names.inject({}) {|sc,col| sc[col]=f[[row,col]]; sc}\n      sr\n    }\n    end\n    def frequencies_by_col\n      f=frequencies\n      cols_names.inject({}){|sc,col| \n        sc[col]=rows_names.inject({}) {|sr,row| sr[row]=f[[row,col]]; sr}\n        sc\n      }\n    end\n    # Chi square, based on expected and real matrix\n    def chi_square\n        require 'statsample/test'\n        Statsample::Test.chi_square(self.to_matrix, matrix_expected)\n    end\n    # Useful to obtain chi square\n    def matrix_expected\n      rn=rows_names\n      cn=cols_names\n      rt=rows_total\n      ct=cols_total\n      t=@v_rows.size\n      m=rn.collect{|row|\n        cn.collect{|col|\n          (rt[row]*ct[col]).quo(t) \n          }\n      }\n      Matrix.rows(m)\n    end\n    def cols_empty_hash\n      cols_names.inject({}) {|a,x| a[x]=0;a}\n    end\n    def report_building(builder)\n      builder.section(:name=>@name) do |generator|\n        fq=frequencies\n        rn=rows_names\n        cn=cols_names\n        total=0\n        total_cols=cols_empty_hash\n        generator.text \"Chi Square: #{chi_square}\"\n        generator.text(_(\"Rows: %s\") % @row_label) unless @row_label.nil?\n        generator.text(_(\"Columns: %s\") % @column_label) unless @column_label.nil?\n        \n        t=ReportBuilder::Table.new(:name=>@name+\" - \"+_(\"Raw\"), :header=>[\"\"]+cols_names.collect {|c| @v_cols.labeling(c)}+[_(\"Total\")])\n        rn.each do |row|\n          total_row=0\n          t_row=[@v_rows.labeling(row)]\n          cn.each do |col|\n            data=fq[[row,col]]\n            total_row+=fq[[row,col]]\n            total+=fq[[row,col]]                    \n            total_cols[col]+=fq[[row,col]]                    \n            t_row.push(data)\n          end\n          t_row.push(total_row)\n          t.row(t_row)\n        end\n        t.hr\n        t_row=[_(\"Total\")]\n        cn.each do |v|\n          t_row.push(total_cols[v])\n        end\n        t_row.push(total)\n        t.row(t_row)\n        generator.parse_element(t)\n        \n        if(@percentage_row)\n          table_percentage(generator,:row)\n        end\n        if(@percentage_column)\n        table_percentage(generator,:column)\n        end\n        if(@percentage_total)\n        table_percentage(generator,:total)\n        end\n      end\n    end\n      \n    \n  \n    def table_percentage(generator,type)\n      fq=frequencies\n      cn=cols_names\n      rn=rows_names\n      rt=rows_total\n      ct=cols_total\n      \n      type_name=case type\n        when :row     then  _(\"% Row\")\n        when :column  then  _(\"% Column\")\n        when :total   then  _(\"% Total\")\n      end\n      \n      t=ReportBuilder::Table.new(:name=>@name+\" - \"+_(type_name), :header=>[\"\"]+cols_names.collect {|c| @v_cols.labeling(c) } + [_(\"Total\")])\n        rn.each do |row|\n          t_row=[@v_rows.labeling(row)]\n          cn.each do |col|\n            total=case type\n              when :row     then  rt[row]\n              when :column  then  ct[col]\n              when :total   then  @cases\n            end\n            data = sprintf(\"%0.2f%%\", fq[[row,col]]*100.0/ total )\n            t_row.push(data)\n          end\n          total=case type\n            when :row     then  rt[row]\n            when :column  then  @cases\n            when :total   then  @cases\n          end              \n          t_row.push(sprintf(\"%0.2f%%\", rt[row]*100.0/total))\n          t.row(t_row)\n        end\n        \n        t.hr\n        t_row=[_(\"Total\")]\n        cn.each{|col|\n          total=case type\n            when :row     then  @cases\n            when :column  then  ct[col]\n            when :total   then  @cases\n          end\n          t_row.push(sprintf(\"%0.2f%%\", ct[col]*100.0/total))\n        }\n      t_row.push(\"100%\")\n      t.row(t_row)\n      generator.parse_element(t)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/dataset.rb",
    "content": "require 'statsample/vector'\n\nclass Hash\n  # Creates a Statsample::Dataset based on a Hash \n  def to_dataset(*args)\n    Statsample::Dataset.new(self, *args)\n  end\nend\n\nclass Array\n  def prefix(s) # :nodoc:\n    self.collect{|c| s+c.to_s }\n  end\n  def suffix(s) # :nodoc:\n    self.collect{|c| c.to_s+s }\n  end\nend\n\nmodule Statsample\n  class DatasetException < RuntimeError # :nodoc:\n    attr_reader :ds,:exp\n    def initialize(ds,e)\n      @ds=ds\n      @exp=e\n    end\n    def to_s\n      m=\"Error on iteration: \"+@exp.message+\"\\n\"+@exp.backtrace.join(\"\\n\")\n      m+=\"\\nRow ##{@ds.i}:#{@ds.case_as_hash(@ds.i)}\" unless @ds.i.nil?\n      m\n    end\n  end\n  # Set of cases with values for one or more variables, \n  # analog to a dataframe on R or a standard data file of SPSS.\n  # Every vector has <tt>#field</tt> name, which represent it. By default,\n  # the vectors are ordered by it field name, but you can change it \n  # the fields order manually.\n  # The Dataset work as a Hash, with keys are field names\n  # and values are Statsample::Vector  \n  # \n  # \n  # ==Usage\n  # Create a empty dataset:\n  #   Dataset.new()\n  # Create a dataset with three empty vectors, called <tt>v1</tt>, <tt>v2</tt> and <tt>v3</tt>:\n  #   Dataset.new(%w{v1 v2 v3})\n  # Create a dataset with two vectors, called <tt>v1</tt>\n  # and <tt>v2</tt>:\n  #   Dataset.new({'v1'=>%w{1 2 3}.to_vector, 'v2'=>%w{4 5 6}.to_vector})\n  # Create a dataset with two given vectors (v1 and v2), \n  # with vectors on inverted order:\n  #   Dataset.new({'v2'=>v2,'v1'=>v1},['v2','v1'])\n  #\n  # The fast way to create a dataset uses Hash#to_dataset, with\n  # field order  as arguments\n  #   v1 = [1,2,3].to_scale\n  #   v2 = [1,2,3].to_scale\n  #   ds = {'v1'=>v2, 'v2'=>v2}.to_dataset(%w{v2 v1})  \n  \n  class Dataset\n    include Writable\n    include Summarizable\n    # Hash of Statsample::Vector\n    attr_reader :vectors\n    # Ordered ids of vectors\n    attr_reader :fields\n    # Name of dataset\n    attr_accessor :name\n    # Number of cases\n    attr_reader :cases\n    # Location of pointer on enumerations methods (like #each)\n    attr_reader :i\n\n    # Generates a new dataset, using three vectors\n    # - Rows\n    # - Columns\n    # - Values\n    #\n    # For example, you have these values\n    #\n    #   x   y   v\n    #   a   a   0\n    #   a   b   1\n    #   b   a   1\n    #   b   b   0\n    #\n    # You obtain\n    #   id  a   b\n    #    a  0   1\n    #    b  1   0\n    #\n    # Useful to process outputs from databases\n    def self.crosstab_by_asignation(rows,columns,values)\n      raise \"Three vectors should be equal size\" if rows.size!=columns.size or rows.size!=values.size\n      cols_values=columns.factors\n      cols_n=cols_values.size\n      h_rows=rows.factors.inject({}){|a,v| a[v]=cols_values.inject({}){\n        |a1,v1| a1[v1]=nil; a1\n        }\n        ;a}\n      values.each_index{|i|\n        h_rows[rows[i]][columns[i]]=values[i]\n      }      \n      ds=Dataset.new([\"_id\"]+cols_values)\n      cols_values.each{|c|\n        ds[c].type=values.type\n      }\n      rows.factors.each {|row|\n        n_row=Array.new(cols_n+1)\n        n_row[0]=row\n          cols_values.each_index {|i|\n            n_row[i+1]=h_rows[row][cols_values[i]]\n        }\n        ds.add_case_array(n_row)\n      }\n      ds.update_valid_data\n      ds\n    end\n    # Return true if any vector has missing data\n    def has_missing_data?\n      @vectors.any? {|k,v| v.has_missing_data?}\n    end\n    # Return a nested hash using fields as keys and\n    # an array constructed of hashes with other values.\n    # If block provided, is used to provide the \n    # values, with parameters +row+ of dataset, \n    # +current+ last hash on hierarchy and\n    # +name+ of the key to include\n    def nest(*tree_keys,&block)\n      tree_keys=tree_keys[0] if tree_keys[0].is_a? Array\n      out=Hash.new      \n      each do |row|\n        current=out        \n        # Create tree\n        tree_keys[0,tree_keys.size-1].each do |f|\n          root=row[f]\n          current[root]||=Hash.new\n          current=current[root]\n        end\n        name=row[tree_keys.last]\n        if !block\n          current[name]||=Array.new\n          current[name].push(row.delete_if{|key,value| tree_keys.include? key})\n        else\n          current[name]=block.call(row, current,name)\n        end\n      end\n      out\n    end\n    # Creates a new dataset. A dataset is a set of ordered named vectors\n    # of the same size.\n    #\n    # [vectors] With an array, creates a set of empty vectors named as\n    # values on the array. With a hash, each Vector is assigned as\n    # a variable of the Dataset named as its key\n    # [fields]  Array of names for vectors. Is only used for set the\n    # order of variables. If empty, vectors keys on alfabethic order as\n    # used as fields.\n    def initialize(vectors={}, fields=[])\n      @@n_dataset||=0\n      @@n_dataset+=1\n      @name=_(\"Dataset %d\") % @@n_dataset\n      @cases=0\n      @gsl=nil\n      @i=nil\n      \n      if vectors.instance_of? Array\n        @fields=vectors.dup\n        @vectors=vectors.inject({}){|a,x| a[x]=Statsample::Vector.new(); a}\n      else\n        # Check vectors\n        @vectors=vectors\n        @fields=fields\n        check_order\n        check_length\n      end\n    end\n    # \n    # Creates a copy of the given dataset, deleting all the cases with\n    # missing data on one of the vectors.\n    # \n    # @param array of fields to include. No value include all fields\n    #\n    def dup_only_valid(*fields_to_include)\n      if fields_to_include.size==1 and fields_to_include[0].is_a? Array\n        fields_to_include=fields_to_include[0]\n      end\n      fields_to_include=@fields if fields_to_include.size==0\n      if fields_to_include.any? {|f| @vectors[f].has_missing_data?}\n        ds=Dataset.new(fields_to_include)\n        fields_to_include.each {|f| ds[f].type=@vectors[f].type}\n        each {|row|\n          unless fields_to_include.any? {|f| @vectors[f].has_missing_data? and !@vectors[f].is_valid? row[f]}\n            row_2=fields_to_include.inject({}) {|ac,v| ac[v]=row[v]; ac}\n            ds.add_case(row_2)\n          end\n        }\n      else\n        ds=dup fields_to_include\n      end\n      ds.name= self.name\n      ds\n    end\n    #\n    # Returns a duplicate of the Dataset. \n    # All vectors are copied, so any modification on new\n    # dataset doesn't affect original dataset's vectors.\n    # If fields given as parameter, only include those vectors.\n    #\n    # @param array of fields to include. No value include all fields    \n    # @return {Statsample::Dataset}\n    def dup(*fields_to_include)\n      if fields_to_include.size==1 and fields_to_include[0].is_a? Array\n        fields_to_include=fields_to_include[0]\n      end\n      fields_to_include=@fields if fields_to_include.size==0\n      vectors={}\n      fields=[]\n      fields_to_include.each{|f|\n        raise \"Vector #{f} doesn't exists\" unless @vectors.has_key? f\n        vectors[f]=@vectors[f].dup\n        fields.push(f)\n      }\n      ds=Dataset.new(vectors,fields)\n      ds.name= self.name\n      ds\n    end\n    \n    \n    # Returns an array with the fields from first argumen to last argument\n    def from_to(from,to)\n      raise ArgumentError, \"Field #{from} should be on dataset\" if !@fields.include? from\n      raise ArgumentError, \"Field #{to} should be on dataset\" if !@fields.include? to\n      @fields.slice(@fields.index(from)..@fields.index(to))\n    end\n    \n    # Returns (when possible) a cheap copy of dataset.\n    # If no vector have missing values, returns original vectors.\n    # If missing values presents, uses Dataset.dup_only_valid.\n    #\n    # @param array of fields to include. No value include all fields\n    # @return {Statsample::Dataset}\n    def clone_only_valid(*fields_to_include)\n      if fields_to_include.size==1 and fields_to_include[0].is_a? Array\n        fields_to_include=fields_to_include[0]\n      end\n      fields_to_include=@fields.dup if fields_to_include.size==0\n      if fields_to_include.any? {|v| @vectors[v].has_missing_data?}\n        dup_only_valid(fields_to_include)\n      else\n        clone(fields_to_include)\n      end\n    end\n    # Returns a shallow copy of Dataset.\n    # Object id will be distinct, but @vectors will be the same.\n    # @param array of fields to include. No value include all fields\n    # @return {Statsample::Dataset}    \n    def clone(*fields_to_include)\n      if fields_to_include.size==1 and fields_to_include[0].is_a? Array\n        fields_to_include=fields_to_include[0]\n      end\n      fields_to_include=@fields.dup if fields_to_include.size==0\n      ds=Dataset.new\n      fields_to_include.each{|f|\n        raise \"Vector #{f} doesn't exists\" unless @vectors.has_key? f\n        ds[f]=@vectors[f]\n      }\n      ds.fields=fields_to_include\n      ds.name=@name\n      ds.update_valid_data\n      ds\n    end\n    # Creates a copy of the given dataset, without data on vectors\n    #\n    # @return {Statsample::Dataset}\n    def dup_empty\n      vectors=@vectors.inject({}) {|a,v|\n        a[v[0]]=v[1].dup_empty\n        a\n      }\n      Dataset.new(vectors,@fields.dup)\n    end\n    # Merge vectors from two datasets\n    # In case of name collition, the vectors names are changed to \n    # x_1, x_2 ....\n    #\n    # @return {Statsample::Dataset}\n    def merge(other_ds)\n      raise \"Cases should be equal (this:#{@cases}; other:#{other_ds.cases}\" unless @cases==other_ds.cases\n      types = @fields.collect{|f| @vectors[f].type} + other_ds.fields.collect{|f| other_ds[f].type}\n      new_fields = (@fields+other_ds.fields).recode_repeated\n      ds_new=Statsample::Dataset.new(new_fields)\n      new_fields.each_index{|i|\n        field=new_fields[i]\n        ds_new[field].type=types[i]\n      }\n      @cases.times {|i|\n        row=case_as_array(i)+other_ds.case_as_array(i)\n        ds_new.add_case_array(row)\n      }\n      ds_new.update_valid_data\n      ds_new\n    end\n\n    # Join 2 Datasets by given fields\n    # type is one of :left and :inner, default is :left\n    #\n    # @return {Statsample::Dataset}\n    def join(other_ds,fields_1=[],fields_2=[],type=:left)\n      fields_new = other_ds.fields - fields_2\n      fields = self.fields + fields_new\n\n      other_ds_hash = {}\n      other_ds.each do |row|\n        key = row.select{|k,v| fields_2.include?(k)}.values\n        value = row.select{|k,v| fields_new.include?(k)}\n        if other_ds_hash[key].nil?\n          other_ds_hash[key] = [value]\n        else\n          other_ds_hash[key] << value\n        end\n      end\n\n      new_ds = Dataset.new(fields)\n\n      self.each do |row|\n        key = row.select{|k,v| fields_1.include?(k)}.values\n\n        new_case = row.dup\n\n        if other_ds_hash[key].nil?\n          if type == :left\n            fields_new.each{|field| new_case[field] = nil}\n            new_ds.add_case(new_case)\n          end\n        else\n          other_ds_hash[key].each do |new_values|\n            new_ds.add_case new_case.merge(new_values)\n          end\n        end\n\n      end\n      new_ds\n    end\n    # Returns a dataset with standarized data.\n    #\n    # @return {Statsample::Dataset}\n    def standarize\n      ds=dup()\n      ds.fields.each do |f|\n        ds[f]=ds[f].vector_standarized\n      end\n      ds\n    end\n    # Generate a matrix, based on fields of dataset\n    #\n    # @return {::Matrix}\n    \n    def collect_matrix\n      rows=@fields.collect{|row|\n        @fields.collect{|col|\n          yield row,col\n        }\n      }\n      Matrix.rows(rows)\n    end\n    \n    # We have the same datasets if +vectors+ and +fields+ are the same\n    #\n    # @return {Boolean}\n    def ==(d2)\n      @vectors==d2.vectors and @fields==d2.fields\n    end\n    # Returns vector <tt>c</tt>\n    # \n    # @return {Statsample::Vector}\n    def col(c)\n      @vectors[c]\n    end\n    alias_method :vector, :col\n    # Equal to Dataset[<tt>name</tt>]=<tt>vector</tt>\n    #\n    # @return self\n    def add_vector(name, vector)\n      raise ArgumentError, \"Vector have different size\" if vector.size!=@cases\n      @vectors[name]=vector\n      check_order\n      self\n    end\n    # Returns true if dataset have vector <tt>v</tt>.\n    #\n    # @return {Boolean}\n    def has_vector? (v)\n      return @vectors.has_key?(v)\n    end\n    # Creates a dataset with the random data, of a n size\n    # If n not given, uses original number of cases.\n    #\n    # @return {Statsample::Dataset}\n    def bootstrap(n=nil)\n      n||=@cases\n      ds_boot=dup_empty\n      n.times do\n        ds_boot.add_case_array(case_as_array(rand(n)))\n      end\n      ds_boot.update_valid_data\n      ds_boot\n    end\n    # Fast version of #add_case.\n    # Can only add one case and no error check if performed\n    # You SHOULD use #update_valid_data at the end of insertion cycle\n    #\n    # \n    def add_case_array(v)\n      v.each_index {|i| d=@vectors[@fields[i]].data; d.push(v[i])}\n    end\n    # Insert a case, using:\n    # * Array: size equal to number of vectors and values in the same order as fields\n    # * Hash: keys equal to fields\n    # If uvd is false, #update_valid_data is not executed after \n    # inserting a case. This is very useful if you want to increase the \n    # performance on inserting many cases,  because #update_valid_data \n    # performs check on vectors and on the dataset\n    \n    def add_case(v,uvd=true)\n      case v\n      when Array\n        if (v[0].is_a? Array)\n          v.each{|subv| add_case(subv,false)}\n        else\n          raise ArgumentError, \"Input array size (#{v.size}) should be equal to fields number (#{@fields.size})\" if @fields.size!=v.size\n          v.each_index {|i| @vectors[@fields[i]].add(v[i],false)}\n        end\n      when Hash\n        raise ArgumentError, \"Hash keys should be equal to fields #{(v.keys - @fields).join(\",\")}\" if @fields.sort!=v.keys.sort\n        @fields.each{|f| @vectors[f].add(v[f],false)}\n      else\n        raise TypeError, 'Value must be a Array or a Hash'\n      end\n      if uvd\n        update_valid_data\n      end\n    end\n    # Check vectors and fields after inserting data. Use only \n    # after  #add_case_array or #add_case with second parameter to false\n    def update_valid_data\n      @gsl=nil\n      @fields.each{|f| @vectors[f].set_valid_data}\n      check_length\n    end\n    # Delete vector named +name+. Multiple fields accepted.\n    def delete_vector(*args)\n      if args.size==1 and args[0].is_a? Array\n        names=args[0]\n      else\n        names=args\n      end\n      names.each do |name|\n        @fields.delete(name)\n        @vectors.delete(name)\n      end\n    end\n    \n    def add_vectors_by_split_recode(name_,join='-',sep=Statsample::SPLIT_TOKEN)\n      split=@vectors[name_].split_by_separator(sep)\n      i=1\n      split.each{|k,v|\n        new_field=name_+join+i.to_s\n        v.name=name_+\":\"+k\n        add_vector(new_field,v)\n        i+=1\n      }\n    end\n    def add_vectors_by_split(name,join='-',sep=Statsample::SPLIT_TOKEN)\n      split=@vectors[name].split_by_separator(sep)\n      split.each{|k,v|\n        add_vector(name+join+k,v)\n      }\n    end\n    \n    def vector_by_calculation(type=:scale)\n      a=[]\n      each do |row|\n        a.push(yield(row))\n      end\n      a.to_vector(type)\n    end\n    # Returns a vector with sumatory of fields\n    # if fields parameter is empty, sum all fields \n    def vector_sum(fields=nil)\n      fields||=@fields\n      vector=collect_with_index do |row, i|\n        if(fields.find{|f| !@vectors[f].data_with_nils[i]})\n          nil\n        else\n          fields.inject(0) {|ac,v| ac + row[v].to_f}\n        end\n      end\n      vector.name=_(\"Sum from %s\") % @name\n      vector\n    end\n    # Check if #fields attribute is correct, after inserting or deleting vectors\n    def check_fields(fields)\n      fields||=@fields\n      raise \"Fields #{(fields-@fields).join(\", \")} doesn't exists on dataset\" if (fields-@fields).size>0\n      fields\n    end\n    \n    # Returns a vector with the numbers of missing values for a case\n    def vector_missing_values(fields=nil)\n      fields=check_fields(fields)\n      collect_with_index do |row, i|\n        fields.inject(0) {|a,v|\n          a+ ((@vectors[v].data_with_nils[i].nil?) ? 1: 0)\n        }\n      end\n    end\n    def vector_count_characters(fields=nil)\n      fields=check_fields(fields)\n      collect_with_index do |row, i|\n        fields.inject(0){|a,v|\n          a+((@vectors[v].data_with_nils[i].nil?) ? 0: row[v].to_s.size)\n        }\n      end\n    end\n    # Returns a vector with the mean for a set of fields\n    # if fields parameter is empty, return the mean for all fields\n    # if max invalid parameter > 0, returns the mean for all tuples\n    # with 0 to max_invalid invalid fields\n    def vector_mean(fields=nil, max_invalid=0)\n      a=[]\n      fields=check_fields(fields)\n      size=fields.size\n      each_with_index do |row, i |\n        # numero de invalidos\n        sum=0\n        invalids=0\n        fields.each{|f|\n          if !@vectors[f].data_with_nils[i].nil?\n            sum+=row[f].to_f\n          else\n            invalids+=1\n          end\n        }\n        if(invalids>max_invalid)\n          a.push(nil)\n        else\n          a.push(sum.quo(size-invalids))\n        end\n      end\n      a=a.to_vector(:scale)\n      a.name=_(\"Means from %s\") % @name\n      a\n    end\n    # Check vectors for type and size.\n    def check_length # :nodoc:\n      size=nil\n      @vectors.each do |k,v|\n        raise Exception, \"Data #{v.class} is not a vector on key #{k}\" if !v.is_a? Statsample::Vector\n        if size.nil?\n          size=v.size\n        else\n          if v.size!=size\n            raise Exception, \"Vector #{k} have size #{v.size} and dataset have size #{size}\"\n          end\n        end\n      end\n      @cases=size\n    end\n    # Retrieves each vector as [key, vector]\n    def each_vector # :yield: |key, vector|\n      @fields.each{|k| yield k, @vectors[k]}\n    end\n    \n    if Statsample::STATSAMPLE__.respond_to?(:case_as_hash)\n      def case_as_hash(c) # :nodoc:\n        Statsample::STATSAMPLE__.case_as_hash(self,c)\n      end\n    else\n      # Retrieves case i as a hash\n      def case_as_hash(i)\n        _case_as_hash(i)\n      end\n    end\n\n    if Statsample::STATSAMPLE__.respond_to?(:case_as_array)\n      def case_as_array(c) # :nodoc:\n        Statsample::STATSAMPLE__.case_as_array(self,c)\n      end\n    else\n      # Retrieves case i as a array, ordered on #fields order\n      def case_as_array(i)\n        _case_as_array(i)\n      end\n    end\n    def _case_as_hash(c) # :nodoc:\n      @fields.inject({}) {|a,x| a[x]=@vectors[x][c];a }\n    end\n    def _case_as_array(c) # :nodoc:\n      @fields.collect {|x| @vectors[x][c]}\n    end\n    \n    # Returns each case as a hash\n    def each\n      begin\n        @i=0\n        @cases.times {|i|\n          @i=i\n          row=case_as_hash(i)\n          yield row\n        }\n        @i=nil\n      rescue =>e\n        raise DatasetException.new(self, e)\n      end\n    end\n    \n    # Returns each case as hash and index\n    def each_with_index # :yield: |case, i|\n      begin\n        @i=0\n        @cases.times{|i|\n          @i=i\n          row=case_as_hash(i)\n          yield row, i\n        }\n        @i=nil\n      rescue =>e\n        raise DatasetException.new(self, e)\n      end\n    end\n    \n    # Returns each case as an array, coding missing values as nils\n    def each_array_with_nils\n      m=fields.size\n      @cases.times {|i|\n        @i=i\n        row=Array.new(m)\n        fields.each_index{|j|\n          f=fields[j]\n          row[j]=@vectors[f].data_with_nils[i]\n        }\n        yield row\n      }\n      @i=nil\n    end\n    # Returns each case as an array\n    def each_array\n      @cases.times {|i|\n        @i=i\n        row=case_as_array(i)\n        yield row\n      }\n      @i=nil\n    end\n    # Set fields order. If you omit one or more vectors, they are\n    # ordered by alphabetic order.\n    def fields=(f)\n      @fields=f\n      check_order\n    end\n    # Check congruence between +fields+ attribute\n    # and keys on +vectors\n    def check_order #:nodoc:\n      if(@vectors.keys.sort!=@fields.sort)\n        @fields=@fields&@vectors.keys\n        @fields+=@vectors.keys.sort-@fields\n      end\n    end\n    # Returns the vector named i\n    def[](i)\n      if i.is_a? Range\n        fields=from_to(i.begin,i.end)\n        clone(*fields)\n      elsif i.is_a? Array\n        clone(i)\n      else\n        raise Exception,\"Vector '#{i}' doesn't exists on dataset\" unless @vectors.has_key?(i)\n        @vectors[i]\n      end\n    end\n    # Retrieves a Statsample::Vector, based on the result\n    # of calculation performed on each case.\n    def collect(type=:scale)\n      data=[]\n      each {|row|\n        data.push yield(row)\n      }\n      Statsample::Vector.new(data,type)\n    end\n    # Same as Statsample::Vector.collect, but giving case index as second parameter on yield.\n    def collect_with_index(type=:scale)\n      data=[]\n      each_with_index {|row, i|\n        data.push(yield(row, i))\n      }\n      Statsample::Vector.new(data,type)\n    end\n    # Recode a vector based on a block\n    def recode!(vector_name)\n      0.upto(@cases-1) {|i|\n        @vectors[vector_name].data[i]=yield case_as_hash(i)\n      }\n      @vectors[vector_name].set_valid_data\n    end\n    \n    def crosstab(v1,v2,opts={})\n      Statsample::Crosstab.new(@vectors[v1], @vectors[v2],opts)\n    end\n    def[]=(i,v)\n      if v.instance_of? Statsample::Vector\n        @vectors[i]=v\n        check_order\n      else\n        raise ArgumentError,\"Should pass a Statsample::Vector\"\n      end\n    end\n    # Return data as a matrix. Column are ordered by #fields and \n    # rows by orden of insertion\n    def to_matrix\n      rows=[]\n      self.each_array{|c|\n        rows.push(c)\n      }\n      Matrix.rows(rows)\n    end\n    \n    if Statsample.has_gsl?\n      def clear_gsl\n        @gsl=nil\n      end\n      \n      def to_gsl\n        if @gsl.nil?\n          if cases.nil?\n            update_valid_data\n          end\n          @gsl=GSL::Matrix.alloc(cases,fields.size)\n          self.each_array{|c|\n            @gsl.set_row(@i,c)\n          }\n        end\n        @gsl\n      end\n      \n    end\n    \n    # Return a correlation matrix for fields included as parameters.\n    # By default, uses all fields of dataset\n\tdef correlation_matrix(fields=nil)\n      if fields\n        ds=clone(fields)\n      else\n        ds=self\n      end\n      Statsample::Bivariate.correlation_matrix(ds)\n    end\n   # Return a correlation matrix for fields included as parameters.\n    # By default, uses all fields of dataset\n\tdef covariance_matrix(fields=nil)\n      if fields\n        ds=clone(fields)\n      else\n        ds=self\n      end\n      Statsample::Bivariate.covariance_matrix(ds)\n    end\n    \n    # Create a new dataset with all cases which the block returns true\n    def filter\n      ds=self.dup_empty\n      each {|c|\n        ds.add_case(c, false) if yield c\n      }\n      ds.update_valid_data\n      ds.name=_(\"%s(filtered)\") % @name\n      ds\n    end\n    \n    # creates a new vector with the data of a given field which the block returns true\n    def filter_field(field)\n      a=[]\n      each do |c|\n        a.push(c[field]) if yield c\n      end\n      a.to_vector(@vectors[field].type)\n    end\n    \n    # Creates a Stastample::Multiset, using one or more fields\n    # to split the dataset.\n    \n   \n    def to_multiset_by_split(*fields)\n\t\t\trequire 'statsample/multiset'\n\t\t\tif fields.size==1\n\t\t\t\tto_multiset_by_split_one_field(fields[0])\n\t\t\telse\n\t\t\t\tto_multiset_by_split_multiple_fields(*fields)\n\t\t\tend\n    end\n    # Creates a Statsample::Multiset, using one field\n    \n    def to_multiset_by_split_one_field(field)\n      raise ArgumentError,\"Should use a correct field name\" if !@fields.include? field\n      factors=@vectors[field].factors\n      ms=Multiset.new_empty_vectors(@fields, factors)\n      each {|c|\n        ms[c[field]].add_case(c,false)\n      }\n      #puts \"Ingreso a los dataset\"\n      ms.datasets.each {|k,ds|\n        ds.update_valid_data\n        ds.name=@vectors[field].labeling(k)\n        ds.vectors.each{|k1,v1|\n          #        puts \"Vector #{k1}:\"+v1.to_s\n          v1.type=@vectors[k1].type\n          v1.name=@vectors[k1].name\n          v1.labels=@vectors[k1].labels\n          \n        }\n      }\n      ms\n    end\n    def to_multiset_by_split_multiple_fields(*fields)\n      factors_total=nil\n      fields.each do |f|\n        if factors_total.nil?\n          factors_total=@vectors[f].factors.collect{|c|\n            [c]\n          }\n        else\n          suma=[]\n          factors=@vectors[f].factors\n          factors_total.each{|f1| factors.each{|f2| suma.push(f1+[f2]) } }\n          factors_total=suma\n        end\n      end\n      ms=Multiset.new_empty_vectors(@fields,factors_total)\n\n      p1=eval \"Proc.new {|c| ms[[\"+fields.collect{|f| \"c['#{f}']\"}.join(\",\")+\"]].add_case(c,false) }\"\n      each{|c| p1.call(c)}\n      \n      ms.datasets.each do |k,ds|\n        ds.update_valid_data\n        ds.name=fields.size.times.map {|i|\n          f=fields[i]\n          sk=k[i]\n          @vectors[f].labeling(sk)\n        }.join(\"-\")\n        ds.vectors.each{|k1,v1| \n          v1.type=@vectors[k1].type\n          v1.name=@vectors[k1].name\n          v1.labels=@vectors[k1].labels\n          \n        }\n      end\n      ms\n      \n    end\n    # Returns a vector, based on a string with a calculation based\n    # on vector\n    # The calculation will be eval'ed, so you can put any variable\n    # or expression valid on ruby\n    # For example:\n    #   a=[1,2].to_vector(scale)\n    #   b=[3,4].to_vector(scale)\n    #   ds={'a'=>a,'b'=>b}.to_dataset\n    #   ds.compute(\"a+b\")\n    #   => Vector [4,6]\n    def compute(text)\n      @fields.each{|f|\n        if @vectors[f].type=:scale\n          text.gsub!(f,\"row['#{f}'].to_f\")\n        else\n          text.gsub!(f,\"row['#{f}']\")\n        end\n      }\n      collect_with_index {|row, i|\n        invalid=false\n        @fields.each{|f|\n          if @vectors[f].data_with_nils[i].nil?\n            invalid=true\n          end\n        }\n        if invalid\n          nil\n        else\n          eval(text)\n        end\n      }\n    end\n    # Test each row with one or more tests\n    # each test is a Proc with the form\n    #   Proc.new {|row| row['age']>0}\n    # The function returns an array with all errors\n    def verify(*tests)\n      if(tests[0].is_a? String)\n        id=tests[0]\n        tests.shift\n      else\n        id=@fields[0]\n      end\n      vr=[]\n      i=0\n      each do |row|\n        i+=1\n        tests.each{|test|\n          if ! test[2].call(row)\n            values=\"\"\n            if test[1].size>0\n              values=\" (\"+test[1].collect{|k| \"#{k}=#{row[k]}\"}.join(\", \")+\")\"\n            end\n            vr.push(\"#{i} [#{row[id]}]: #{test[0]}#{values}\")\n          end\n        }\n      end\n      vr\n    end\n    def to_s\n      \"#<\"+self.class.to_s+\":\"+self.object_id.to_s+\" @name=#{@name} @fields=[\"+@fields.join(\",\")+\"] cases=\"+@vectors[@fields[0]].size.to_s\n    end\n    def inspect\n      self.to_s\n    end\n    # Creates a new dataset for one to many relations\n    # on a dataset, based on pattern of field names.\n    # \n    # for example, you have a survey for number of children\n    # with this structure:\n    #   id, name, child_name_1, child_age_1, child_name_2, child_age_2\n    # with \n    #   ds.one_to_many(%w{id}, \"child_%v_%n\"\n    # the field of first parameters will be copied verbatim\n    # to new dataset, and fields which responds to second \n    # pattern will be added one case for each different %n.\n    # For example\n    #   cases=[\n    #     ['1','george','red',10,'blue',20,nil,nil],\n    #     ['2','fred','green',15,'orange',30,'white',20],\n    #     ['3','alfred',nil,nil,nil,nil,nil,nil]\n    #   ]\n    #   ds=Statsample::Dataset.new(%w{id name car_color1 car_value1 car_color2 car_value2 car_color3 car_value3})\n    #   cases.each {|c| ds.add_case_array c }\n    #   ds.one_to_many(['id'],'car_%v%n').to_matrix\n    #   => Matrix[\n    #      [\"red\", \"1\", 10], \n    #      [\"blue\", \"1\", 20],\n    #      [\"green\", \"2\", 15],\n    #      [\"orange\", \"2\", 30],\n    #      [\"white\", \"2\", 20]\n    #      ]\n    # \n    def one_to_many(parent_fields, pattern)\n      #base_pattern=pattern.gsub(/%v|%n/,\"\")\n      re=Regexp.new pattern.gsub(\"%v\",\"(.+?)\").gsub(\"%n\",\"(\\\\d+?)\")\n      ds_vars=parent_fields\n      vars=[]\n      max_n=0\n      h=parent_fields.inject({}) {|a,v| a[v]=Statsample::Vector.new([], @vectors[v].type);a }\n      # Adding _row_id\n      h['_col_id']=[].to_scale\n      ds_vars.push(\"_col_id\")\n      @fields.each do |f|\n        if f=~re\n          if !vars.include? $1\n            vars.push($1) \n            h[$1]=Statsample::Vector.new([], @vectors[f].type)\n          end\n          max_n=$2.to_i if max_n < $2.to_i\n        end\n      end\n      ds=Dataset.new(h,ds_vars+vars)\n      each do |row|\n        row_out={}\n        parent_fields.each do |f|\n          row_out[f]=row[f]\n        end\n        max_n.times do |n1|\n          n=n1+1\n          any_data=false\n          vars.each do |v|\n            data=row[pattern.gsub(\"%v\",v.to_s).gsub(\"%n\",n.to_s)]\n            row_out[v]=data\n            any_data=true if !data.nil?\n          end\n          if any_data\n            row_out[\"_col_id\"]=n\n            ds.add_case(row_out,false)\n          end\n          \n        end\n      end\n      ds.update_valid_data\n      ds\n    end\n    def report_building(b)\n      b.section(:name=>@name) do |g|\n        g.text _\"Cases: %d\"  % cases\n        @fields.each do |f|\n          g.text \"Element:[#{f}]\"\n          g.parse_element(@vectors[f])\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/dominanceanalysis/bootstrap.rb",
    "content": "module Statsample\n  class DominanceAnalysis\n    # == Goal\n    # Generates Bootstrap sample to identity the replicability of a Dominance Analysis. See Azen & Bodescu (2003) for more information.\n    #\n    # == Usage\n    # \n    #  require 'statsample'\n    #  a=100.times.collect {rand}.to_scale\n    #  b=100.times.collect {rand}.to_scale\n    #  c=100.times.collect {rand}.to_scale\n    #  d=100.times.collect {rand}.to_scale\n    #  ds={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n    #  ds['y']=ds.collect{|row| row['a']*5+row['b']*2+row['c']*2+row['d']*2+10*rand()}\n    #  dab=Statsample::DominanceAnalysis::Bootstrap.new(ds2, 'y', :debug=>true)\n    #  dab.bootstrap(100,nil)\n    #  puts dab.summary\n    # <strong>Output</strong>\n    #   Sample size: 100\n    #  t: 1.98421693632958\n    #  \n    #  Linear Regression Engine: Statsample::Regression::Multiple::MatrixEngine\n    #  Table: Bootstrap report\n    #  --------------------------------------------------------------------------------------------\n    #  | pairs                 | sD  | Dij    | SE(Dij) | Pij   | Pji   | Pno   | Reproducibility |\n    #  --------------------------------------------------------------------------------------------\n    #  | Complete dominance    |\n    #  --------------------------------------------------------------------------------------------\n    #  | a - b                 | 1.0 | 0.6150 | 0.454   | 0.550 | 0.320 | 0.130 | 0.550           |\n    #  | a - c                 | 1.0 | 0.9550 | 0.175   | 0.930 | 0.020 | 0.050 | 0.930           |\n    #  | a - d                 | 1.0 | 0.9750 | 0.131   | 0.960 | 0.010 | 0.030 | 0.960           |\n    #  | b - c                 | 1.0 | 0.8800 | 0.276   | 0.820 | 0.060 | 0.120 | 0.820           |\n    #  | b - d                 | 1.0 | 0.9250 | 0.193   | 0.860 | 0.010 | 0.130 | 0.860           |\n    #  | c - d                 | 0.5 | 0.5950 | 0.346   | 0.350 | 0.160 | 0.490 | 0.490           |\n    #  --------------------------------------------------------------------------------------------\n    #  | Conditional dominance |\n    #  --------------------------------------------------------------------------------------------\n    #  | a - b                 | 1.0 | 0.6300 | 0.458   | 0.580 | 0.320 | 0.100 | 0.580           |\n    #  | a - c                 | 1.0 | 0.9700 | 0.156   | 0.960 | 0.020 | 0.020 | 0.960           |\n    #  | a - d                 | 1.0 | 0.9800 | 0.121   | 0.970 | 0.010 | 0.020 | 0.970           |\n    #  | b - c                 | 1.0 | 0.8850 | 0.283   | 0.840 | 0.070 | 0.090 | 0.840           |\n    #  | b - d                 | 1.0 | 0.9500 | 0.181   | 0.920 | 0.020 | 0.060 | 0.920           |\n    #  | c - d                 | 0.5 | 0.5800 | 0.360   | 0.350 | 0.190 | 0.460 | 0.460           |\n    #  --------------------------------------------------------------------------------------------\n    #  | General Dominance     |\n    #  --------------------------------------------------------------------------------------------\n    #  | a - b                 | 1.0 | 0.6500 | 0.479   | 0.650 | 0.350 | 0.000 | 0.650           |\n    #  | a - c                 | 1.0 | 0.9800 | 0.141   | 0.980 | 0.020 | 0.000 | 0.980           |\n    #  | a - d                 | 1.0 | 0.9900 | 0.100   | 0.990 | 0.010 | 0.000 | 0.990           |\n    #  | b - c                 | 1.0 | 0.9000 | 0.302   | 0.900 | 0.100 | 0.000 | 0.900           |\n    #  | b - d                 | 1.0 | 0.9700 | 0.171   | 0.970 | 0.030 | 0.000 | 0.970           |\n    #  | c - d                 | 1.0 | 0.5600 | 0.499   | 0.560 | 0.440 | 0.000 | 0.560           |\n    #  --------------------------------------------------------------------------------------------\n    #  \n    #  Table: General averages\n    #  ---------------------------------------\n    #  | var | mean  | se    | p.5   | p.95  |\n    #  ---------------------------------------\n    #  | a   | 0.133 | 0.049 | 0.062 | 0.218 |\n    #  | b   | 0.106 | 0.048 | 0.029 | 0.199 |\n    #  | c   | 0.035 | 0.032 | 0.002 | 0.106 |\n    #  | d   | 0.023 | 0.019 | 0.002 | 0.062 |\n    #  ---------------------------------------\n    #\n    # == References:\n    # * Azen, R. & Budescu, D.V. (2003). The dominance analysis approach for comparing predictors in multiple regression. <em>Psychological Methods, 8</em>(2), 129-148.\n    class Bootstrap\n      include Writable\n      include Summarizable\n      # Total Dominance results\n      attr_reader :samples_td\n      # Conditional Dominance results\n      attr_reader :samples_cd\n      # General Dominance results\n      attr_reader :samples_gd\n      # General average results \n      attr_reader :samples_ga\n      # Name of fields\n      attr_reader :fields\n      # Regression class used for analysis\n      attr_accessor :regression_class\n      # Dataset\n      attr_accessor :ds\n      # Name of analysis\n      attr_accessor :name\n      # Alpha level of confidence. Default: ALPHA\n      attr_accessor :alpha\n      # Debug?\n      attr_accessor :debug\n      # Default level of confidence for t calculation\n      ALPHA=0.95\n      # Create a new Dominance Analysis Bootstrap Object\n      # \n      # * ds: A Dataset object\n      # * y_var: Name of dependent variable\n      # * opts: Any other attribute of the class \n      def initialize(ds,y_var, opts=Hash.new)\n        @ds=ds\n        @y_var=y_var\n        @n=ds.cases\n        \n        @n_samples=0\n        @alpha=ALPHA\n        @debug=false\n        if y_var.is_a? Array\n          @fields=ds.fields-y_var\n          @regression_class=Regression::Multiple::MultipleDependent\n          \n        else\n          @fields=ds.fields-[y_var]\n          @regression_class=Regression::Multiple::MatrixEngine\n        end\n        @samples_ga=@fields.inject({}){|a,v| a[v]=[];a}\n\n        @name=_(\"Bootstrap dominance Analysis:  %s over %s\") % [ ds.fields.join(\",\") , @y_var]\n        opts.each{|k,v|\n          self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n        create_samples_pairs            \n      end\n      # lr_class deprecated\n      alias_method :lr_class, :regression_class\n      def da\n        if @da.nil?\n          @da=DominanceAnalysis.new(@ds,@y_var, :regression_class => @regression_class)\n        end\n        @da\n      end\n      # Creates n re-samples from original dataset and store result of\n      # each sample on @samples_td, @samples_cd, @samples_gd, @samples_ga\n      # \n      # * number_samples: Number of new samples to add\n      # * n: size of each new sample. If nil, equal to original sample size\n      \n      def bootstrap(number_samples,n=nil)\n        number_samples.times{ |t|\n          @n_samples+=1\n          puts _(\"Bootstrap %d of %d\") % [t+1, number_samples] if @debug\n          ds_boot=@ds.bootstrap(n)\n          da_1=DominanceAnalysis.new(ds_boot, @y_var, :regression_class => @regression_class)\n          \n          da_1.total_dominance.each{|k,v|\n            @samples_td[k].push(v)\n          }\n          da_1.conditional_dominance.each{|k,v|\n            @samples_cd[k].push(v)\n          }\n          da_1.general_dominance.each{|k,v|\n            @samples_gd[k].push(v)\n          }\n          da_1.general_averages.each{|k,v|\n            @samples_ga[k].push(v)\n          }\n        }\n      end\n      def create_samples_pairs\n        @samples_td={}\n        @samples_cd={}\n        @samples_gd={}\n        @pairs=[]\n        c=(0...@fields.size).to_a.combination(2)\n        c.each do |data|\n          p data\n          convert=data.collect {|i| @fields[i] }\n          @pairs.push(convert)\n          [@samples_td, @samples_cd, @samples_gd].each{|s|\n            s[convert]=[]\n          }\n        end\n      end\n      def t\n        Distribution::T.p_value(1-((1-@alpha) / 2), @n_samples - 1)\n      end\n      def report_building(builder) # :nodoc:\n        raise \"You should bootstrap first\" if @n_samples==0\n        builder.section(:name=>@name) do |generator|\n          generator.text _(\"Sample size: %d\\n\") % @n_samples\n          generator.text \"t: #{t}\\n\"\n          generator.text _(\"Linear Regression Engine: %s\") % @regression_class.name\n          \n          table=ReportBuilder::Table.new(:name=>\"Bootstrap report\", :header => [_(\"pairs\"), \"sD\",\"Dij\", _(\"SE(Dij)\"), \"Pij\", \"Pji\", \"Pno\", _(\"Reproducibility\")])\n          table.row([_(\"Complete dominance\"),\"\",\"\",\"\",\"\",\"\",\"\",\"\"])\n          table.hr\n          @pairs.each{|pair|\n            std=@samples_td[pair].to_vector(:scale)\n            ttd=da.total_dominance_pairwise(pair[0],pair[1])\n            table.row(summary_pairs(pair,std,ttd))\n          }\n          table.hr\n          table.row([_(\"Conditional dominance\"),\"\",\"\",\"\",\"\",\"\",\"\",\"\"])\n          table.hr\n          @pairs.each{|pair|\n            std=@samples_cd[pair].to_vector(:scale)\n            ttd=da.conditional_dominance_pairwise(pair[0],pair[1])\n            table.row(summary_pairs(pair,std,ttd))\n          \n          }\n          table.hr\n          table.row([_(\"General Dominance\"),\"\",\"\",\"\",\"\",\"\",\"\",\"\"])\n          table.hr\n          @pairs.each{|pair|\n            std=@samples_gd[pair].to_vector(:scale)\n            ttd=da.general_dominance_pairwise(pair[0],pair[1])\n            table.row(summary_pairs(pair,std,ttd))\n          }\n          generator.parse_element(table)\n          \n          table=ReportBuilder::Table.new(:name=>_(\"General averages\"), :header=>[_(\"var\"), _(\"mean\"), _(\"se\"), _(\"p.5\"), _(\"p.95\")])\n          \n          @fields.each{|f|\n            v=@samples_ga[f].to_vector(:scale)\n            row=[@ds[f].name, sprintf(\"%0.3f\",v.mean), sprintf(\"%0.3f\",v.sd), sprintf(\"%0.3f\",v.percentil(5)),sprintf(\"%0.3f\",v.percentil(95))]\n            table.row(row)\n          \n          }\n          \n          generator.parse_element(table)\n        end\n      end\n      def summary_pairs(pair,std,ttd)\n          freqs=std.proportions\n          [0, 0.5, 1].each{|n|\n              freqs[n]=0 if freqs[n].nil?\n          }\n          name=\"%s - %s\" % [@ds[pair[0]].name, @ds[pair[1]].name]\n          [name,f(ttd,1),f(std.mean,4),f(std.sd),f(freqs[1]), f(freqs[0]), f(freqs[0.5]), f(freqs[ttd])]\n      end\n      def f(v,n=3)\n          prec=\"%0.#{n}f\"\n          sprintf(prec,v)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/dominanceanalysis.rb",
    "content": "module Statsample\n  # Dominance Analysis is a procedure based on an examination of the R<sup>2</sup> values\n  # for all possible subset models, to identify the relevance of one or more \n  # predictors in the prediction of criterium.\n  #\n  # See Budescu(1993), Azen & Budescu (2003, 2006) for more information.\n  #\n  # == Use\n  #\n  #  a=1000.times.collect {rand}.to_scale\n  #  b=1000.times.collect {rand}.to_scale\n  #  c=1000.times.collect {rand}.to_scale\n  #  ds={'a'=>a,'b'=>b,'c'=>c}.to_dataset\n  #  ds['y']=ds.collect{|row| row['a']*5+row['b']*3+row['c']*2+rand()}\n  #  da=Statsample::DominanceAnalysis.new(ds,'y')\n  #  puts da.summary\n  # \n  # === Output:\n  #\n  #  Report: Report 2010-02-08 19:10:11 -0300\n  #  Table: Dominance Analysis result\n  #  ------------------------------------------------------------\n  #  |                  | r2    | sign  | a     | b     | c     |\n  #  ------------------------------------------------------------\n  #  | Model 0          |       |       | 0.648 | 0.265 | 0.109 |\n  #  ------------------------------------------------------------\n  #  | a                | 0.648 | 0.000 | --    | 0.229 | 0.104 |\n  #  | b                | 0.265 | 0.000 | 0.612 | --    | 0.104 |\n  #  | c                | 0.109 | 0.000 | 0.643 | 0.260 | --    |\n  #  ------------------------------------------------------------\n  #  | k=1 Average      |       |       | 0.627 | 0.244 | 0.104 |\n  #  ------------------------------------------------------------\n  #  | a*b              | 0.877 | 0.000 | --    | --    | 0.099 |\n  #  | a*c              | 0.752 | 0.000 | --    | 0.224 | --    |\n  #  | b*c              | 0.369 | 0.000 | 0.607 | --    | --    |\n  #  ------------------------------------------------------------\n  #  | k=2 Average      |       |       | 0.607 | 0.224 | 0.099 |\n  #  ------------------------------------------------------------\n  #  | a*b*c            | 0.976 | 0.000 | --    | --    | --    |\n  #  ------------------------------------------------------------\n  #  | Overall averages |       |       | 0.628 | 0.245 | 0.104 |\n  #  ------------------------------------------------------------\n  #  \n  #  Table: Pairwise dominance\n  #  -----------------------------------------\n  #  | Pairs | Total | Conditional | General |\n  #  -----------------------------------------\n  #  | a - b | 1.0   | 1.0         | 1.0     |\n  #  | a - c | 1.0   | 1.0         | 1.0     |\n  #  | b - c | 1.0   | 1.0         | 1.0     |\n  #  -----------------------------------------\n  #\n  # == Reference:\n  # * Budescu, D. V. (1993). Dominance analysis: a new approach to the problem of relative importance of predictors in multiple regression. <em>Psychological Bulletin, 114</em>, 542-551.\n  # * Azen, R. & Budescu, D.V. (2003). The dominance analysis approach for comparing predictors in multiple regression. <em>Psychological Methods, 8</em>(2), 129-148.\n  # * Azen, R. & Budescu, D.V. (2006). Comparing predictors in Multivariate Regression Models: An extension of Dominance Analysis. <em>Journal of Educational and Behavioral Statistics, 31</em>(2), 157-180.\n  #\n  class DominanceAnalysis\n    include Summarizable\n    # Class to generate the regressions. Default to Statsample::Regression::Multiple::MatrixEngine\n    attr_accessor :regression_class\n    # Name of analysis\n    attr_accessor :name\n    # Set to true if you want to build from dataset, not correlation matrix\n    attr_accessor :build_from_dataset\n    #  Array with independent variables. You could create subarrays, \n    #  to test groups of predictors as blocks\n    attr_accessor  :predictors\n    # If you provide a matrix as input, you should set \n    # the number of cases to define significance of R^2\n    attr_accessor  :cases\n    # Method of :regression_class used to measure association. \n    # \n    # Only necessary to change if you have multivariate dependent.\n    # * :r2yx (R^2_yx), the default option, is the  option when distinction\n    #   between independent and dependents variable is arbitrary\n    # * :p2yx is the option when the distinction between independent and dependents variables is real.\n    #   \n    \n    attr_accessor  :method_association\n    \n    \n    attr_reader :dependent\n    \n    UNIVARIATE_REGRESSION_CLASS=Statsample::Regression::Multiple::MatrixEngine\n    MULTIVARIATE_REGRESSION_CLASS=Statsample::Regression::Multiple::MultipleDependent\n    \n    def self.predictor_name(variable)\n      if variable.is_a? Array\n        sprintf(\"(%s)\", variable.join(\",\"))\n      else\n        variable\n      end\n    end\n    # Creates a new DominanceAnalysis object\n    # Parameters:\n    # * input:    A Matrix or Dataset object\n    # * dependent: Name of dependent variable. Could be an array, if you want to\n    #             do an Multivariate Regression Analysis. If nil, set to all\n    #             fields on input, except criteria\n \n    def initialize(input, dependent, opts=Hash.new)\n      @build_from_dataset=false\n      if dependent.is_a? Array\n        @regression_class= MULTIVARIATE_REGRESSION_CLASS\n        @method_association=:r2yx\n      else\n        @regression_class= UNIVARIATE_REGRESSION_CLASS\n        @method_association=:r2\n      end\n      \n      @name=nil\n      opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n      }\n      @dependent=dependent\n      @dependent=[@dependent] unless @dependent.is_a? Array\n      \n      @predictors ||= input.fields-@dependent\n      \n      @name=_(\"Dominance Analysis:  %s over %s\") % [ @predictors.flatten.join(\",\") , @dependent.join(\",\")] if @name.nil?\n      \n      if input.is_a? Statsample::Dataset\n        @ds=input\n        @matrix=Statsample::Bivariate.correlation_matrix(input)\n        @cases=Statsample::Bivariate.min_n_valid(input)\n      elsif input.is_a? ::Matrix\n        @ds=nil\n        @matrix=input\n      else\n        raise ArgumentError.new(\"You should use a Matrix or a Dataset\")\n      end\n      @models=nil\n      @models_data=nil\n      @general_averages=nil\n    end\n    # Compute models. \n    def compute\n      create_models\n      fill_models\n    end\n    def models\n      if @models.nil?\n        compute\n      end\n      @models\n    end\n    \n    def models_data\n      if @models_data.nil?\n        compute\n      end\n      @models_data\n    end\n    def create_models\n      @models=[]\n      @models_data={}\n      for i in 1..@predictors.size\n        c=(0...@predictors.size).to_a.combination(i)\n        c.each  do |data|\n          \n          independent=data.collect {|i1| @predictors[i1] }\n          @models.push(independent)\n          if (@build_from_dataset)\n            data=@ds.dup(independent.flatten+@dependent)\n          else\n            data=@matrix.submatrix(independent.flatten+@dependent)\n          end\n          \n          modeldata=ModelData.new(independent, data, self)\n          models_data[independent.sort {|a,b| a.to_s<=>b.to_s}]=modeldata\n        end\n      end\n    end\n    def fill_models\n      @models.each do |m|\n        @predictors.each do |f|\n          next if m.include? f\n          base_model=md(m)\n          comp_model=md(m+[f])\n          base_model.add_contribution(f,comp_model.r2)\n        end\n      end\n    end\n    private :create_models, :fill_models\n    \n    def dominance_for_nil_model(i,j)\n      if md([i]).r2>md([j]).r2\n        1\n      elsif md([i]).r2<md([j]).r2\n        0\n      else\n        0.5\n      end           \n    end\n    # Returns 1 if i D k, 0 if j dominates i and 0.5 if undetermined\n    def total_dominance_pairwise(i,j)\n      dm=dominance_for_nil_model(i,j)\n      return 0.5 if dm==0.5\n      dominances=[dm]\n      models_data.each do |k,m|\n        if !m.contributions[i].nil? and !m.contributions[j].nil?\n          if m.contributions[i]>m.contributions[j]\n              dominances.push(1)\n          elsif m.contributions[i]<m.contributions[j]\n              dominances.push(0)\n          else\n            return 0.5\n              #dominances.push(0.5)\n          end\n        end\n      end\n      final=dominances.uniq\n      final.size>1 ? 0.5 : final[0]\n    end\n    \n    # Returns 1 if i cD k, 0 if j cD i and 0.5 if undetermined\n    def conditional_dominance_pairwise(i,j)\n      dm=dominance_for_nil_model(i,j)\n      return 0.5 if dm==0.5\n      dominances=[dm]\n      for k in 1...@predictors.size\n        a=average_k(k)\n        if a[i]>a[j]\n            dominances.push(1)\n        elsif a[i]<a[j]\n            dominances.push(0)\n        else\n          return 0.5\n            #dominances.push(0.5)\n        end                 \n      end\n      final=dominances.uniq\n      final.size>1 ? 0.5 : final[0]            \n    end\n    # Returns 1 if i gD k, 0 if j gD i and 0.5 if undetermined        \n    def general_dominance_pairwise(i,j)\n      ga=general_averages\n      if ga[i]>ga[j]\n        1\n      elsif ga[i]<ga[j]\n        0\n      else\n        0.5\n      end                 \n    end\n    def pairs\n      models.find_all{|m| m.size==2}\n    end\n    def total_dominance\n      pairs.inject({}){|a,pair| a[pair]=total_dominance_pairwise(pair[0], pair[1])\n      a\n      }\n    end\n    def conditional_dominance\n      pairs.inject({}){|a,pair| a[pair]=conditional_dominance_pairwise(pair[0], pair[1])\n      a\n      }\n    end\n    def general_dominance\n      pairs.inject({}){|a,pair| a[pair]=general_dominance_pairwise(pair[0], pair[1])\n      a\n      }\n    end\n    \n    def md(m)\n      models_data[m.sort {|a,b| a.to_s<=>b.to_s}]\n    end\n    # Get all model of size k\n    def md_k(k)\n      out=[]\n      @models.each{|m| out.push(md(m)) if m.size==k }\n      out\n    end\n    \n    # For a hash with arrays of numbers as values\n    # Returns a hash with same keys and \n    # value as the mean of values of original hash\n    \n    def get_averages(averages)\n      out={}\n      averages.each{|key,val| out[key]=val.to_vector(:scale).mean }\n      out\n    end\n    # Hash with average for each k size model.\n    def average_k(k)\n      return nil if k==@predictors.size\n      models=md_k(k)\n      averages=@predictors.inject({}) {|a,v| a[v]=[];a}\n      models.each do |m|\n        @predictors.each do |f|\n          averages[f].push(m.contributions[f]) unless m.contributions[f].nil?\n        end\n      end\n      get_averages(averages)\n    end\n    def general_averages\n      if @general_averages.nil?\n        averages=@predictors.inject({}) {|a,v| a[v]=[md([v]).r2];a}\n        for k in 1...@predictors.size\n          ak=average_k(k)\n          @predictors.each do |f|\n            averages[f].push(ak[f])\n          end\n        end\n        @general_averages=get_averages(averages)\n      end\n      @general_averages\n    end\n    \n\n    def report_building(g)\n      compute if @models.nil?\n      g.section(:name=>@name) do |generator|\n        header=[\"\",\"r2\",_(\"sign\")]+@predictors.collect {|c| DominanceAnalysis.predictor_name(c) }\n        \n        generator.table(:name=>_(\"Dominance Analysis result\"), :header=>header) do |t|\n          row=[_(\"Model 0\"),\"\",\"\"]+@predictors.collect{|f|\n            sprintf(\"%0.3f\",md([f]).r2)\n          }\n          \n          t.row(row)\n          t.hr\n          for i in 1..@predictors.size\n            mk=md_k(i)\n            mk.each{|m|\n              t.row(m.add_table_row)\n            }\n            # Report averages\n            a=average_k(i)\n            if !a.nil?\n                t.hr\n                row=[_(\"k=%d Average\") % i,\"\",\"\"] + @predictors.collect{|f|\n                    sprintf(\"%0.3f\",a[f])\n                }\n                t.row(row)\n                t.hr\n                \n            end\n          end\n          \n          g=general_averages\n          t.hr\n          \n          row=[_(\"Overall averages\"),\"\",\"\"]+@predictors.collect{|f|\n                    sprintf(\"%0.3f\",g[f])\n          }\n          t.row(row)\n        end\n        \n        td=total_dominance\n        cd=conditional_dominance\n        gd=general_dominance\n        generator.table(:name=>_(\"Pairwise dominance\"), :header=>[_(\"Pairs\"),_(\"Total\"),_(\"Conditional\"),_(\"General\")]) do |t|\n          pairs.each{|pair|\n            name=pair.map{|v| v.is_a?(Array) ? \"(\"+v.join(\"-\")+\")\" : v}.join(\" - \")\n            row=[name, sprintf(\"%0.1f\",td[pair]), sprintf(\"%0.1f\",cd[pair]), sprintf(\"%0.1f\",gd[pair])]\n            t.row(row)\n          }\n        end\n      end\n    end\n    class ModelData # :nodoc:\n      attr_reader :contributions\n      def initialize(independent, data, da)\n        @independent=independent\n        @data=data\n        @predictors=da.predictors\n        @dependent=da.dependent\n        @cases=da.cases\n        @method=da.method_association\n        @contributions=@independent.inject({}){|a,v| a[v]=nil;a}\n        \n        r_class=da.regression_class\n        \n        if @dependent.size==1\n          @lr=r_class.new(data, @dependent[0], :cases=>@cases)\n        else\n          @lr=r_class.new(data, @dependent, :cases=>@cases)\n        end\n      end\n      def add_contribution(f, v)\n        @contributions[f]=v-r2\n      end\n      def r2\n        @lr.send(@method)\n      end\n      def name\n        @independent.collect {|variable|\n          DominanceAnalysis.predictor_name(variable)\n        }.join(\"*\")\n      end\n      def add_table_row\n        if @cases\n          sign=sprintf(\"%0.3f\", @lr.probability)\n\t\telse\n\t\tsign=\"???\"\n        end\n      \n        [name, sprintf(\"%0.3f\",r2), sign] + @predictors.collect{|k|\n          v=@contributions[k]\n          if v.nil?\n              \"--\"\n          else\n          sprintf(\"%0.3f\",v)\n          end\n        }\n      end\n      def summary\n        out=sprintf(\"%s: r2=%0.3f(p=%0.2f)\\n\",name, r2, @lr.significance, @lr.sst)\n        out << @predictors.collect{|k|\n          v=@contributions[k]\n          if v.nil?\n              \"--\"\n          else\n            sprintf(\"%s=%0.3f\",k,v)\n          end\n        }.join(\" | \") \n        out << \"\\n\"\n        return out\n      end\n    end # end ModelData\n  end # end Dominance Analysis\nend\n\nrequire 'statsample/dominanceanalysis/bootstrap'\n"
  },
  {
    "path": "lib/statsample/factor/map.rb",
    "content": "module Statsample\n  module Factor\n  # = Velicer's Minimum Average Partial\n  # \n  # \"Velicer’s (1976) MAP test involves a complete princi-\n  # pal components analysis followed by the examination of\n  # a series of matrices of partial correlations. Specifically,\n  # on the first step, the first principal component is par-\n  # tialed out of the correlations between the variables of in-\n  # terest, and the average squared coefficient in the off-\n  # diagonals of the resulting partial correlation matrix is\n  # computed. On the second step, the first two principal\n  # components are partialed out of the original correlation\n  # matrix and the average squared partial correlation is\n  # again computed. These computations are conducted for k\n  # (the number of variables) minus one steps. The average\n  # squared partial correlations from these steps are then\n  # lined up, and the number of components is determined by\n  # the step number in the analyses that resulted in the lowest\n  # average squared partial correlation. The average squared\n  # coefficient in the original correlation matrix is also com-\n  # puted, and if this coefficient happens to be lower than\n  # the lowest average squared partial correlation, then no\n  # components should be extracted from the correlation ma-\n  # trix. Statistically, components are retained as long as the\n  # variance in the correlation matrix represents systematic\n  # variance. Components are no longer retained when there\n  # is proportionately more unsystematic variance than sys-\n  # tematic variance.\" (O'Connor, 2000, p.397).\n  # \n  # Current algorithm is loosely based on SPSS O'Connor algorithm\n  # \n  # == Reference\n  # * O'Connor, B. (2000). SPSS and SAS programs for determining the number of components using parallel analysis and Velicer's MAP test. Behavior Research Methods, Instruments, & Computers, 32(3), 396-402.\n  #\n\n\n\n    class MAP\n      include Summarizable\n      include DirtyMemoize\n      # Name of analysis\n      attr_accessor :name\n      attr_reader :eigenvalues\n      # Number of factors to retain\n      attr_reader :number_of_factors\n      # Average squared correlations\n      attr_reader :fm\n      # Smallest average squared correlation\n      attr_reader :minfm\n      \n      attr_accessor :use_gsl\n      def self.with_dataset(ds,opts=Hash.new)\n        new(ds.correlation_matrix,opts)\n      end\n      def initialize(matrix, opts=Hash.new)\n        @matrix=matrix\n        opts_default={\n          :use_gsl=>true,\n          :name=>_(\"Velicer's MAP\")\n        }\n        @opts=opts_default.merge(opts)\n         opts_default.keys.each {|k| send(\"#{k}=\", @opts[k]) }\n      end\n      def compute\n        gsl_m=(use_gsl and Statsample.has_gsl?) ? @matrix.to_gsl : @matrix\n        klass_m=gsl_m.class\n        eigvect,@eigenvalues=gsl_m.eigenvectors_matrix, gsl_m.eigenvalues\n        eigenvalues_sqrt=@eigenvalues.collect {|v| Math.sqrt(v)}\n        loadings=eigvect*(klass_m.diagonal(*eigenvalues_sqrt))\n        fm=Array.new(@matrix.row_size)\n        ncol=@matrix.column_size\n        \n        fm[0]=(gsl_m.mssq - ncol).quo(ncol*(ncol-1))\n        \n        (ncol-1).times do |m|\n          puts \"MAP:Eigenvalue #{m+1}\" if $DEBUG\n          a=loadings[0..(loadings.row_size-1),0..m]\n          partcov= gsl_m - (a*a.transpose)\n          \n          d=klass_m.diagonal(*(partcov.diagonal.collect {|v| Math::sqrt(1/v)}))\n          pr=d*partcov*d\n          fm[m+1]=(pr.mssq-ncol).quo(ncol*(ncol-1))\n        end\n        minfm=fm[0]\n        nfactors=0\n        @errors=[]\n        fm.each_with_index do |v,s|\n          if defined?(Complex) and v.is_a? ::Complex\n            @errors.push(s)\n          else\n            if v < minfm\n              minfm=v\n              nfactors=s\n            end\n          end\n        end\n        @number_of_factors=nfactors\n        @fm=fm\n        @minfm=minfm\n        \n      end\n      def report_building(g) #:nodoc:\n        g.section(:name=>@name) do |s|\n          s.table(:name=>_(\"Eigenvalues\"),:header=>[_(\"Value\")]) do |t|\n            eigenvalues.each_with_index do |e,i|\n                t.row([@errors.include?(i) ? \"*\" : \"%0.6f\" % e])\n            end\n          end\n          s.table(:name=>_(\"Velicer's Average Squared Correlations\"), :header=>[_(\"number of components\"),_(\"average square correlation\")]) do |t|\n            fm.each_with_index do |v,i|\n              t.row([\"%d\" % i, @errors.include?(i) ? \"*\" : \"%0.6f\" % v])\n            end\n          end\n          s.text(_(\"The smallest average squared correlation is : %0.6f\" % minfm))\n          s.text(_(\"The number of components is : %d\" % number_of_factors))\n        end\n      end\n      dirty_memoize :number_of_factors, :fm, :minfm, :eigenvalues\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/factor/parallelanalysis.rb",
    "content": "module Statsample\n  module Factor\n    # Performs Horn's 'parallel analysis' to a principal components analysis\n    # to adjust for sample bias in the retention of components. \n    # Can create the bootstrap samples using random data, using number\n    # of cases and variables, parameters for actual data (mean and standard\n    # deviation of each variable) or bootstrap sampling for actual data.\n    # == Description\n    # \"PA involves the construction of a number of correlation matrices of random variables based on the same sample size and number of variables in the real data set. The average eigenvalues from the random correlation matrices are then compared to the eigenvalues from the real data correlation matrix, such that the first observed eigenvalue is compared to the first random eigenvalue, the second observed eigenvalue is compared to the second random eigenvalue, and so on.\" (Hayton, Allen & Scarpello, 2004, p.194)\n    # == Usage\n    # *With real dataset*\n    #   # ds should be any valid dataset\n    #   pa=Statsample::Factor::ParallelAnalysis.new(ds, :iterations=>100, :bootstrap_method=>:data)\n    #\n    # *With number of cases and variables*\n    #   pa=Statsample::Factor::ParallelAnalysis.with_random_data(100,8)\n    # \n    # == Reference\n    # * Hayton, J., Allen, D. & Scarpello, V.(2004). Factor Retention Decisions in Exploratory Factor Analysis: a Tutorial on Parallel Analysis. <i>Organizational Research Methods, 7</i> (2), 191-205.\n    # * O'Connor, B. (2000). SPSS and SAS programs for determining the number of components using parallel analysis and Velicer's MAP test. Behavior Research Methods, Instruments, & Computers, 32(3), 396-402.\n    # * Liu, O., & Rijmen, F. (2008). A modified procedure for parallel analysis of ordered categorical data. Behavior Research Methods, 40(2), 556-562.\n\n    class ParallelAnalysis\n      def self.with_random_data(cases,vars,opts=Hash.new)\n        require 'ostruct'\n        ds=OpenStruct.new\n        ds.fields=vars.times.map {|i| \"v#{i+1}\"}\n        ds.cases=cases\n        opts=opts.merge({:bootstrap_method=> :random, :no_data=>true})\n        new(ds, opts)\n      end\n      include DirtyMemoize\n      include Summarizable\n      # Number of random sets to produce. 50 by default\n      attr_accessor :iterations\n      # Name of analysis\n      attr_accessor :name\n      # Dataset. You could use mock vectors when use bootstrap method\n      attr_reader :ds\n      # Bootstrap method. <tt>:random</tt> used by default\n      # * <tt>:random</tt>: uses number of variables and cases for the dataset\n      # * <tt>:data</tt> : sample with replacement from actual data.\n      attr_accessor :bootstrap_method\n      # Uses smc on diagonal of matrixes, to perform simulation\n      # of a Principal Axis analysis.\n      # By default, false.\n      attr_accessor :smc\n      # Percentil over bootstrap eigenvalue should be accepted. 95 by default\n      attr_accessor :percentil\n      # Correlation matrix used with :raw_data . <tt>:correlation_matrix</tt> used by default\n      attr_accessor :matrix_method\n      # Number of eigenvalues to calculate. Should be set for \n      # Principal Axis Analysis.\n      attr_accessor :n_variables\n      # Dataset with bootstrapped eigenvalues\n      attr_reader :ds_eigenvalues\n      # Perform analysis without actual data. \n      attr_accessor :no_data\n      # Show extra information if true\n      attr_accessor :debug\n      attr_accessor :use_gsl\n      def initialize(ds, opts=Hash.new)\n        @ds=ds\n        @fields=@ds.fields\n        @n_variables=@fields.size\n        @n_cases=ds.cases\n        opts_default={\n          :name=>_(\"Parallel Analysis\"),\n          :iterations=>50, # See Liu and Rijmen (2008)\n          :bootstrap_method => :random,\n          :smc=>false,\n          :percentil=>95, \n          :debug=>false,\n          :no_data=>false,\n          :matrix_method=>:correlation_matrix\n        }\n        @use_gsl=Statsample.has_gsl?\n        @opts=opts_default.merge(opts)\n        @opts[:matrix_method]==:correlation_matrix if @opts[:bootstrap_method]==:parameters\n        opts_default.keys.each {|k| send(\"#{k}=\", @opts[k]) }\n      end\n      # Number of factor to retent\n      def number_of_factors\n        total=0\n        ds_eigenvalues.fields.each_with_index do |f,i|\n          if (@original[i]>0 and @original[i]>ds_eigenvalues[f].percentil(percentil))\n            total+=1\n          else\n            break\n          end\n        end\n        total\n      end\n      def report_building(g) #:nodoc:\n        g.section(:name=>@name) do |s|\n          s.text _(\"Bootstrap Method: %s\") % bootstrap_method\n          s.text _(\"Uses SMC: %s\") % (smc ? _(\"Yes\") : _(\"No\"))\n          s.text _(\"Correlation Matrix type : %s\") % matrix_method\n          s.text _(\"Number of variables: %d\") % @n_variables\n          s.text _(\"Number of cases: %d\") % @n_cases\n          s.text _(\"Number of iterations: %d\") % @iterations\n          if @no_data\n            s.table(:name=>_(\"Eigenvalues\"), :header=>[_(\"n\"), _(\"generated eigenvalue\"), \"p.#{percentil}\"]) do |t|\n              ds_eigenvalues.fields.each_with_index do |f,i|\n                v=ds_eigenvalues[f]\n                t.row [i+1, \"%0.4f\" %  v.mean, \"%0.4f\" %  v.percentil(percentil), ]\n              end\n            end\n          else\n            s.text _(\"Number or factors to preserve: %d\") % number_of_factors \n            s.table(:name=>_(\"Eigenvalues\"), :header=>[_(\"n\"), _(\"data eigenvalue\"), _(\"generated eigenvalue\"),\"p.#{percentil}\",_(\"preserve?\")]) do |t|\n              ds_eigenvalues.fields.each_with_index do |f,i|\n                v=ds_eigenvalues[f]\n                t.row [i+1, \"%0.4f\" % @original[i], \"%0.4f\" %  v.mean, \"%0.4f\" %  v.percentil(percentil), (v.percentil(percentil)>0 and @original[i] > v.percentil(percentil)) ? \"Yes\":\"\"]\n              end\n            end\n          end\n          \n        end\n      end\n      # Perform calculation. Shouldn't be called directly for the user\n      def compute\n        \n        \n        @original=Statsample::Bivariate.send(matrix_method, @ds).eigenvalues unless no_data        \n        @ds_eigenvalues=Statsample::Dataset.new((1..@n_variables).map{|v| \"ev_%05d\" % v})\n        @ds_eigenvalues.fields.each {|f| @ds_eigenvalues[f].type=:scale}\n        if bootstrap_method==:parameter or bootstrap_method==:random\n          rng = Distribution::Normal.rng\n        end\n        \n        @iterations.times do |i|\n          begin\n            puts \"#{@name}: Iteration #{i}\" if $DEBUG or debug\n            # Create a dataset of dummy values\n            ds_bootstrap=Statsample::Dataset.new(@ds.fields)\n            \n            @fields.each do |f|\n              if bootstrap_method==:random\n                ds_bootstrap[f]=@n_cases.times.map {|c| rng.call}.to_scale\n              elsif bootstrap_method==:data\n                ds_bootstrap[f]=ds[f].sample_with_replacement(@n_cases)\n              else\n                raise \"bootstrap_method doesn't recogniced\"\n              end\n            end\n            ds_bootstrap.update_valid_data\n            \n            matrix=Statsample::Bivariate.send(matrix_method, ds_bootstrap)\n            matrix=matrix.to_gsl if @use_gsl\n            if smc\n                smc_v=matrix.inverse.diagonal.map{|ii| 1-(1.quo(ii))}\n                smc_v.each_with_index do |v,ii| \n                  matrix[ii,ii]=v\n                end\n            end\n            ev=matrix.eigenvalues\n            @ds_eigenvalues.add_case_array(ev)\n          rescue Statsample::Bivariate::Tetrachoric::RequerimentNotMeet => e\n            puts \"Error: #{e}\" if $DEBUG\n            redo\n          end\n        end\n        @ds_eigenvalues.update_valid_data\n      end\n      dirty_memoize :number_of_factors, :ds_eigenvalues\n      dirty_writer :iterations, :bootstrap_method, :percentil, :smc\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/factor/pca.rb",
    "content": "# encoding: UTF-8\nmodule Statsample\nmodule Factor\n  # Principal Component Analysis (PCA) of a covariance or \n  # correlation matrix.. \n  #\n  # NOTE: Sign of second and later eigenvalues could be different\n  # using Ruby or GSL, so values for PCs and component matrix\n  # should differ, because extendmatrix and gsl's methods to calculate\n  # eigenvectors are different. Using R is worse, cause first \n  # eigenvector could have negative values!\n  # For Principal Axis Analysis, use Statsample::Factor::PrincipalAxis\n  # \n  # == Usage:\n  #   require 'statsample'\n  #   a=[2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2.0, 1.0, 1.5, 1.1].to_scale\n  #   b=[2.4,0.7,2.9,2.2,3.0,2.7,1.6,1.1,1.6,0.9].to_scale\n  #   ds={'a'=>a,'b'=>b}.to_dataset\n  #   cor_matrix=Statsample::Bivariate.correlation_matrix(ds)\n  #   pca=Statsample::Factor::PCA.new(cor_matrix)\n  #   pca.m\n  #   => 1\n  #   pca.eigenvalues\n  #   => [1.92592927269225, 0.0740707273077545]\n  #   pca.component_matrix\n  #   => GSL::Matrix\n  #   [  9.813e-01 \n  #     9.813e-01 ]\n  #   pca.communalities\n  #   => [0.962964636346122, 0.962964636346122]\n  #\n  # == References:\n  # * SPSS Manual\n  # * Smith, L. (2002). A tutorial on Principal Component Analysis. Available on http://courses.eas.ualberta.ca/eas570/pca_tutorial.pdf \n  # * Härdle, W. & Simar, L. (2003). Applied Multivariate Statistical Analysis. Springer\n  # \n  class PCA\n    include Summarizable\n    # Name of analysis\n    attr_accessor :name\n\n    # Number of factors. Set by default to the number of factors\n    # with eigen values > 1\n    attr_accessor :m\n    # Use GSL if available\n    attr_accessor :use_gsl\n    # Add to the summary a rotation report\n    attr_accessor :summary_rotation\n    # Add to the summary a parallel analysis report\n    attr_accessor :summary_parallel_analysis\n    # Type of rotation. By default, Statsample::Factor::Rotation::Varimax\n    attr_accessor :rotation_type\n    attr_accessor :matrix_type\n    def initialize(matrix, opts=Hash.new)\n      @use_gsl=nil\n      @name=_(\"Principal Component Analysis\")\n      @matrix=matrix\n      @n_variables=@matrix.column_size      \n      @variables_names=(@matrix.respond_to? :fields) ? @matrix.fields : @n_variables.times.map {|i| _(\"VAR_%d\") % (i+1)}\n      \n      @matrix_type = @matrix.respond_to?(:_type) ? @matrix._type : :correlation\n      \n      @m=nil\n      \n      @rotation_type=Statsample::Factor::Varimax\n      \n      opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n      }\n      if @use_gsl.nil?\n        @use_gsl=Statsample.has_gsl?\n      end\n      if @matrix.respond_to? :fields\n        @variables_names=@matrix.fields\n      else\n        @variables_names=@n_variables.times.map {|i| \"V#{i+1}\"}\n      end\n      calculate_eigenpairs\n      \n      if @m.nil?\n        # Set number of factors with eigenvalues > 1\n        @m=@eigenpairs.find_all {|ev,ec| ev>=1.0}.size\n      end\n      \n    end\n    def rotation\n      @rotation_type.new(component_matrix)\n    end\n    def total_eigenvalues\n      eigenvalues.inject(0) {|ac,v| ac+v}\n    end\n    def create_centered_ds\n      h={}\n      @original_ds.factors.each {|f|\n        mean=@original_ds[f].mean\n        h[f]=@original_ds[f].recode {|c| c-mean}\n      }\n      @ds=h.to_dataset\n    end\n    \n    # Feature matrix for +m+ factors\n    # Returns +m+ eigenvectors as columns.\n    # So, i=variable, j=component\n    def feature_matrix(m=nil)\n      m||=@m\n      if @use_gsl\n        omega_m=GSL::Matrix.zeros(@n_variables,m)\n        ev=eigenvectors\n        m.times do |i|\n          omega_m.set_column(i,ev[i])\n        end\n        omega_m\n      else\n        omega_m=::Matrix.build(@n_variables, m) {0}\n        m.times do |i|\n          omega_m.column= i, @eigenpairs[i][1]\n        end\n        omega_m\n      end\n    end\n    # Returns Principal Components for +input+ matrix or dataset\n    # The number of PC to return is equal to parameter +m+. \n    # If +m+ isn't set, m set to number of PCs selected at object creation.\n    # Use covariance matrix\n    \n    def principal_components(input, m=nil)\n      if @use_gsl\n        data_matrix=input.to_gsl\n      else\n        data_matrix=input.to_matrix\n      end\n      m||=@m\n      \n      raise \"data matrix variables<>pca variables\" if data_matrix.column_size!=@n_variables\n      \n      fv=feature_matrix(m)\n      pcs=(fv.transpose*data_matrix.transpose).transpose\n      \n      pcs.extend Statsample::NamedMatrix\n      pcs.fields_y=m.times.map {|i| \"PC_%d\" % (i+1)}\n      pcs.to_dataset\n    end\n    def component_matrix(m=nil)\n      var=\"component_matrix_#{matrix_type}\"\n      send(var,m)\n    end\n    # Matrix with correlations between components and\n    # variables. Based on Härdle & Simar (2003, p.243)\n    def component_matrix_covariance(m=nil)\n      m||=@m\n      raise \"m should be > 0\" if m<1\n      ff=feature_matrix(m)\n      cm=::Matrix.build(@n_variables, m) {0}\n      @n_variables.times {|i|\n        m.times {|j|\n          cm[i,j]=ff[i,j] * Math.sqrt(eigenvalues[j] / @matrix[i,i])\n        }\n      }\n      cm.extend NamedMatrix\n      cm.name=_(\"Component matrix (from covariance)\")\n      cm.fields_x = @variables_names\n      cm.fields_y = m.times.map {|i| \"PC_%d\" % (i+1)}\n      \n      cm\n    end\n    # Matrix with correlations between components and\n    # variables\n    def component_matrix_correlation(m=nil)\n      m||=@m\n      raise \"m should be > 0\" if m<1\n      omega_m=::Matrix.build(@n_variables, m) {0}\n      gammas=[]\n      m.times {|i|\n        omega_m.column=i, @eigenpairs[i][1]\n        gammas.push(Math::sqrt(@eigenpairs[i][0]))\n      }\n      gamma_m=::Matrix.diagonal(*gammas)\n      cm=(omega_m*(gamma_m)).to_matrix\n      \n      cm.extend CovariateMatrix\n      cm.name=_(\"Component matrix\")\n      cm.fields_x = @variables_names\n      cm.fields_y = m.times.map {|i| \"PC_%d\" % (i+1)}\n      cm\n    end\n    def communalities(m=nil)\n      \n      m||=@m\n      h=[]\n      @n_variables.times do |i|\n        sum=0\n        m.times do |j|\n          sum+=(@eigenpairs[j][0].abs*@eigenpairs[j][1][i]**2)\n        end\n        h.push(sum)\n      end\n      h\n    end\n    # Array with eigenvalues\n    def eigenvalues\n      @eigenpairs.collect {|c| c[0] }\n    end\n    def eigenvectors\n      @eigenpairs.collect {|c| \n        @use_gsl ? c[1].to_gsl : c[1].to_vector\n      }\n    end\n    def calculate_eigenpairs\n      @eigenpairs= @use_gsl ? @matrix.to_gsl.eigenpairs : @matrix.to_matrix.eigenpairs_ruby \n    end\n  \n    \n    def report_building(builder) # :nodoc:\n      builder.section(:name=>@name) do |generator|\n        generator.text _(\"Number of factors: %d\") % m\n        generator.table(:name=>_(\"Communalities\"), :header=>[_(\"Variable\"),_(\"Initial\"),_(\"Extraction\"), _(\"%\")]) do |t|\n          communalities(m).each_with_index {|com, i|\n            perc=com*100.quo(@matrix[i,i])\n            t.row([@variables_names[i], \"%0.3f\" % @matrix[i,i]  , \"%0.3f\" % com, \"%0.3f\" % perc])\n          }\n        end\n        te=total_eigenvalues\n        generator.table(:name=>_(\"Total Variance Explained\"), :header=>[_(\"Component\"), _(\"E.Total\"), _(\"%\"), _(\"Cum. %\")]) do |t|\n          ac_eigen=0\n          eigenvalues.each_with_index {|eigenvalue,i|\n            ac_eigen+=eigenvalue\n            t.row([_(\"Component %d\") % (i+1), sprintf(\"%0.3f\",eigenvalue), sprintf(\"%0.3f%%\", eigenvalue*100.quo(te)), sprintf(\"%0.3f\",ac_eigen*100.quo(te))])\n          }\n        end\n        \n        generator.parse_element(component_matrix(m))\n                  \n        if (summary_rotation)\n          generator.parse_element(rotation)\n        end\n      end\n    end\n    private :calculate_eigenpairs, :create_centered_ds\n  end\nend\nend\n"
  },
  {
    "path": "lib/statsample/factor/principalaxis.rb",
    "content": "module Statsample\nmodule Factor\n  # Principal Axis Analysis for a covariance or correlation matrix. \n  #\n  # For PCA, use Statsample::Factor::PCA\n  # \n  # == Usage:\n  #   require 'statsample'\n  #   a=[2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2.0, 1.0, 1.5, 1.1].to_scale\n  #   b=[2.4,0.7,2.9,2.2,3.0,2.7,1.6,1.1,1.6,0.9].to_scale\n  #   ds={'a'=>a,'b'=>b}.to_dataset\n  #   cor_matrix=Statsample::Bivariate.correlation_matrix(ds)\n  #   pa=Statsample::Factor::PrincipalAxis.new(cor_matrix)\n  #   pa.iterate(1)\n  #   pa.m\n  #   => 1\n  #   pca.component_matrix\n  #   => GSL::Matrix\n  #   [  9.622e-01 \n  #      9.622e-01 ]\n  #   pca.communalities\n  #   => [0.962964636346122, 0.962964636346122]\n  #\n  # == References:\n  # * SPSS Manual\n  # * Smith, L. (2002). A tutorial on Principal Component Analysis. Available on http://courses.eas.ualberta.ca/eas570/pca_tutorial.pdf \n  #   \n  class PrincipalAxis\n    include DirtyMemoize\n    include Summarizable\n    # Name of analysis\n    attr_accessor :name\n\n    # Number of factors. Set by default to the number of factors\n    # with eigenvalues > 1 (Kaiser criterion).\n    # \n    # _Warning:_ Kaiser criterion overfactors! Give yourself some time\n    # and use Horn's Parallel Analysis.\n    #\n    attr_accessor :m\n    \n    # Number of iterations required to converge\n    attr_reader :iterations\n    \n    # Initial eigenvalues \n    attr_reader :initial_eigenvalues\n    \n    # Tolerance for iterations\n    attr_accessor :epsilon\n    \n    # Use SMC(squared multiple correlations) as diagonal. If false, use 1\n    attr_accessor :smc\n    \n    # Maximum number of iterations\n    attr_accessor :max_iterations\n    \n    # Eigenvalues of factor analysis\n    attr_reader :eigenvalues\n    \n    # Minimum difference between succesive iterations on sum of communalities\n    DELTA=1e-3\n    # Maximum number of iterations\n    MAX_ITERATIONS=25\n    \n    def initialize(matrix, opts=Hash.new)\n      @matrix=matrix\n      if @matrix.respond_to? :fields\n        @fields=@matrix.fields\n      else\n        @fields=@matrix.row_size.times.map {|i| _(\"Variable %d\") % (i+1)}\n      end\n      @n_variables=@matrix.row_size\n      @name=\"\"\n      @m=nil\n      @initial_eigenvalues=nil\n      @initial_communalities=nil\n      @component_matrix=nil\n      @delta=DELTA\n      @smc=true\n      @max_iterations=MAX_ITERATIONS\n      opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n      }\n      if @matrix.respond_to? :fields\n        @variables_names=@matrix.fields\n      else\n        @variables_names=@n_variables.times.map {|i| \"V#{i+1}\"}\n      end\n      if @m.nil?\n        pca=PCA.new(::Matrix.rows(@matrix.to_a))\n        @m=pca.m\n      end\n      \n      @clean=true\n    end\n    # Communality for all variables given m factors\n    def communalities(m=nil)\n      if m!=@m or @clean\n        iterate(m)\n        raise \"Can't calculate comunality\" if @communalities.nil?\n      end\n      @communalities\n    end\n    # Component matrix for m factors\n    def component_matrix(m=nil)\n      if m!=@m  or @clean\n        iterate(m)\n      end\n      @component_matrix\n    end\n    # Iterate to find the factors\n    def iterate(m=nil)\n      @clean=false\n      m||=@m\n      @m=m\n      t = @max_iterations\n      work_matrix=@matrix.to_a\n      \n      prev_com=initial_communalities\n      \n      pca=PCA.new(::Matrix.rows(work_matrix))\n      @initial_eigenvalues=pca.eigenvalues\n      prev_sum=prev_com.inject(0) {|ac,v| ac+v}\n      @iterations=0\n      t.times do |i|\n        \"#{@name}: Iteration #{i}\" if $DEBUG\n        @iterations+=1\n        prev_com.each_with_index{|v,it|\n          work_matrix[it][it]=v\n        }\n        pca=PCA.new(::Matrix.rows(work_matrix))\n        @communalities=pca.communalities(m)\n        @eigenvalues=pca.eigenvalues\n        com_sum = @communalities.inject(0) {|ac,v| ac+v}\n        #jump=true\n        \n        break if (com_sum-prev_sum).abs < @delta\n        @communalities.each_with_index do |v2,i2|\n          raise \"Variable #{i2} with communality > 1\" if v2>1.0\n        end\n        prev_sum=com_sum\n        prev_com=@communalities\n        \n      end\n      @component_matrix=pca.component_matrix(m)\n      @component_matrix.extend CovariateMatrix\n      @component_matrix.name=_(\"Factor Matrix\")\n      @component_matrix.fields_x = @variables_names\n      @component_matrix.fields_y = m.times.map {|i| \"factor_#{i+1}\"}\n      \n    end\n    alias :compute :iterate \n    \n    def initial_communalities\n      if @initial_communalities.nil?\n        \n        if @smc\n          # Based on O'Connors(2000)\n          @initial_communalities=@matrix.inverse.diagonal.map{|i| 1-(1.quo(i))}\n=begin\n        @initial_communalities=@matrix.column_size.times.collect {|i|\n          rxx , rxy = PrincipalAxis.separate_matrices(@matrix,i)\n          matrix=(rxy.t*rxx.inverse*rxy)\n          matrix[0,0]\n        }\n=end\n        else\n          @initial_communalities=[1.0]*@matrix.column_size\n        end\n      end      \n      @initial_communalities\n    end\n    \n    \n    # Returns two matrixes from a correlation matrix\n    # with regressors correlation matrix and criteria xy\n    # matrix.\n    def self.separate_matrices(matrix, y)\n      ac=[]\n      matrix.column_size.times do |i|\n        ac.push(matrix[y,i]) if i!=y\n      end\n      rxy=Matrix.columns([ac])\n      rows=[]\n      matrix.row_size.times do |i|\n        if i!=y\n          row=[]\n          matrix.row_size.times do |j|\n            row.push(matrix[i,j]) if j!=y\n          end\n          rows.push(row)\n        end\n      end\n      rxx=Matrix.rows(rows)\n      [rxx,rxy]\n    end\n    def report_building(generator)\n      iterate if @clean\n      generator.section(:name=>@name) do |s|\n        s.text _(\"Number of factors: %d\") % m\n        s.text _(\"Iterations: %d\") % @iterations\n        s.table(:name=>_(\"Communalities\"), :header=>[_(\"Variable\"),_(\"Initial\"),_(\"Extraction\")]) do |t|\n          communalities(m).each_with_index {|com,i|\n            t.row([@fields[i], sprintf(\"%0.4f\", initial_communalities[i]), sprintf(\"%0.3f\", com)])\n          }\n        end\n        s.table(:name=>_(\"Total Variance\"), :header=>[_(\"Factor\"), _(\"I.E.Total\"), _(\"I.E. %\"), _(\"I.E.Cum. %\"),\n        _(\"S.L.Total\"), _(\"S.L. %\"), _(\"S.L.Cum. %\")\n          ]) do |t|\n        ac_eigen,ac_i_eigen=0,0\n          @initial_eigenvalues.each_with_index {|eigenvalue,i|\n            ac_i_eigen+=eigenvalue\n            ac_eigen+=@eigenvalues[i]\n            new_row=[\n            _(\"Factor %d\") % (i+1), \n            sprintf(\"%0.3f\",eigenvalue),\n            sprintf(\"%0.3f%%\", eigenvalue*100.quo(@n_variables)),\n            sprintf(\"%0.3f\",ac_i_eigen*100.quo(@n_variables))\n            ]\n            if i<@m\n              new_row.concat [\n                sprintf(\"%0.3f\", @eigenvalues[i]),\n                sprintf(\"%0.3f%%\", @eigenvalues[i]*100.quo(@n_variables)),\n                sprintf(\"%0.3f\",ac_eigen*100.quo(@n_variables))              \n              ]\n            else\n              new_row.concat [\"\",\"\",\"\"]\n            end\n            \n            t.row new_row\n          }\n        end\n        s.parse_element(component_matrix)\n      end\n    end\n    \n    dirty_writer :max_iterations, :epsilon, :smc\n    dirty_memoize :eigenvalues, :iterations, :initial_eigenvalues\n\n  end\n  \nend\nend\n"
  },
  {
    "path": "lib/statsample/factor/rotation.rb",
    "content": "module Statsample\nmodule Factor\n  # Base class for component matrix rotation.\n  #\n  # == Reference:\n  # * SPSS Manual\n  # * Lin, J. (2007). VARIMAX_K58 [Source code]. [http://www.johnny-lin.com/idl_code/varimax_k58.pro]\n  # \n  # Use subclasses Varimax, Equimax or Quartimax for desired type of rotation\n  #   Use:\n  #   a = Matrix[ [ 0.4320,  0.8129,  0.3872] \n  #     , [ 0.7950, -0.5416,  0.2565]  \n  #     , [ 0.5944,  0.7234, -0.3441]  \n  #     , [ 0.8945, -0.3921, -0.1863] ]\n  #   rotation = Statsample::Factor::Varimax(a)\n  #   rotation.iterate\n  #   p rotation.rotated\n  #   p rotation.component_transformation_matrix\n  # \n  class Rotation\n    EPSILON=1e-15\n    MAX_ITERATIONS=25\n    include Summarizable\n    include DirtyMemoize\n    attr_reader :iterations, :rotated, :component_transformation_matrix, :h2\n    # Maximum number of iterations    \n    attr_accessor :max_iterations\n    # Maximum precision    \n    attr_accessor :epsilon\n    attr_accessor :use_gsl\n    dirty_writer :max_iterations, :epsilon\n    dirty_memoize :iterations, :rotated, :component_transformation_matrix, :h2\n    \n    def initialize(matrix, opts=Hash.new)\n      @name=_(\"%s rotation\") % rotation_name\n      @matrix=matrix\n      @n=@matrix.row_size # Variables, p on original\n      @m=@matrix.column_size # Factors, r on original\n      @component_transformation_matrix=nil\n      @max_iterations=MAX_ITERATIONS\n      @epsilon=EPSILON\n      @rotated=nil\n      @h2=(@matrix.collect {|c| c**2} * Matrix.column_vector([1]*@m)).column(0).to_a\n      @use_gsl=Statsample.has_gsl?\n      opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n      }\n    end\n    def report_building(g)\n      g.section(:name=>@name) do |s|\n        s.parse_element(rotated)\n        s.parse_element(component_transformation_matrix)\n      end\n    end\n    alias_method :communalities, :h2\n    alias_method :rotated_component_matrix, :rotated\n    def compute\n      iterate\n    end\n    # Start iteration \n    def iterate\n      k_matrix=@use_gsl ? GSL::Matrix : ::Matrix\n      t=k_matrix.identity(@m)\n      b=(@use_gsl ? @matrix.to_gsl : @matrix.dup)\n      h=k_matrix.diagonal(*@h2).collect {|c| Math::sqrt(c)}\n      h_inverse=h.collect {|c| c!=0 ? 1/c : 0 }\n      bh=h_inverse * b\n      @not_converged=true\n      @iterations=0\n      while @not_converged\n        break if @iterations>@max_iterations\n        @iterations+=1\n        #puts \"Iteration #{iterations}\"\n        num_pairs=@m*(@m-1).quo(2)\n        (0..(@m-2)).each do |i| #+ go through factor index 0:r-1-1 (begin)\n          ((i+1)..(@m-1)).each do |j| #+ pair i to \"rest\" of factors (begin)\n            \n            xx = bh.column(i)\n            yy = bh.column(j)\n            tx = t.column(i)\n            ty = t.column(j)\n            \n            uu = @n.times.collect {|var_i| xx[var_i]**2-yy[var_i]**2}\n            vv = @n.times.collect {|var_i| 2*xx[var_i]*yy[var_i]}\n            \n            a  = @n.times.inject(0) {|ac,var_i| ac+ uu[var_i] }\n            b  = @n.times.inject(0) {|ac,var_i| ac+ vv[var_i] }\n            c  = @n.times.inject(0) {|ac,var_i| ac+ (uu[var_i]**2 - vv[var_i]**2) }\n            d  = @n.times.inject(0) {|ac,var_i| ac+ (2*uu[var_i]*vv[var_i]) }\n            num=x(a,b,c,d)\n            den=y(a,b,c,d)\n            phi=Math::atan2(num,den) / 4.0\n            # puts \"#{i}-#{j}: #{phi}\"\n            \n            if(Math::sin(phi.abs) >= @epsilon)\n              xx_rot=( Math::cos(phi)*xx)+(Math::sin(phi)*yy)\n              yy_rot=((-Math::sin(phi))*xx)+(Math::cos(phi)*yy)\n              \n              \n              tx_rot=( Math::cos(phi)*tx)+(Math::sin(phi)*ty)\n              ty_rot=((-Math::sin(phi))*tx)+(Math::cos(phi)*ty)\n\n              \n              bh=bh.to_a\n\n              @n.times {|row_i|\n                bh[row_i][i] = xx_rot[row_i]\n                bh[row_i][j] = yy_rot[row_i]\n              }\n              t=t.to_a\n              @m.times {|row_i|\n                t[row_i][i]=tx_rot[row_i]\n                t[row_i][j]=ty_rot[row_i]\n              }\n              #if @use_gsl\n                bh=k_matrix.[](*bh)\n                t=k_matrix.[](*t)\n              #else\n              #  bh=Matrix.rows(bh)\n              #  t=Matrix.rows(t)\n                \n              #end\n            else\n              num_pairs=num_pairs-1\n              @not_converged=false if num_pairs==0\n            end # if\n          end #j\n        end #i\n      end # while\n      @rotated=h*bh\n      @rotated.extend CovariateMatrix\n      @rotated.name=_(\"Rotated Component matrix\")\n      \n      if @matrix.respond_to? :fields_x\n        @rotated.fields_x = @matrix.fields_x\n      else\n        @rotated.fields_x = @n.times.map {|i| \"var_#{i+1}\"}\n      end\n      if @matrix.respond_to? :fields_y\n        @rotated.fields_y = @matrix.fields_y\n      else\n        @rotated.fields_y = @m.times.map {|i| \"var_#{i+1}\"}\n      end\n      \n      \n      \n      @component_transformation_matrix=t\n      @component_transformation_matrix.extend CovariateMatrix\n      @component_transformation_matrix.name=_(\"Component transformation matrix\")\n      \n      if @matrix.respond_to? :fields_y\n        @component_transformation_matrix.fields = @matrix.fields_y\n        \n      else\n        @component_transformation_matrix.fields = @m.times.map {|i| \"var_#{i+1}\"}\n      end\n      \n      @rotated\n    end\n\n  end\n  class Varimax < Rotation\n    def x(a,b,c,d)\n      d-(2*a*b / @n.to_f)\n    end\n    def y(a,b,c,d)\n      c-((a**2-b**2) / @n.to_f)\n    end\n    def rotation_name\n      \"Varimax\"\n    end\n  end\n  class Equimax < Rotation\n    def x(a,b,c,d)\n      d-(@m*a*b / @n.to_f)\n    end\n    def y(a,b,c,d)\n      c-@m*((a**2-b**2) / (2*@n.to_f))\n    end\n    def rotation_name\n      \"Equimax\"\n    end\n\n  end\n  class Quartimax < Rotation\n    def x(a,b,c,d)\n      d\n    end\n    def y(a,b,c,d)\n      c\n    end\n    def rotation_name\n      \"Quartimax\"\n    end\n    \n  end\nend\nend\n"
  },
  {
    "path": "lib/statsample/factor.rb",
    "content": "require 'statsample/factor/rotation'\nrequire 'statsample/factor/pca'\nrequire 'statsample/factor/principalaxis'\nrequire 'statsample/factor/parallelanalysis'\nrequire 'statsample/factor/map'\n\nmodule Statsample\n  # Factor Analysis toolbox.\n  # * Classes for Extraction of factors: \n  #   * Statsample::Factor::PCA\n  #   * Statsample::Factor::PrincipalAxis\n  # * Classes for Rotation of factors: \n  #   * Statsample::Factor::Varimax\n  #   * Statsample::Factor::Equimax\n  #   * Statsample::Factor::Quartimax\n  # * Classes for determining the number of components\n  #   * Statsample::Factor::MAP\n  #   * Statsample::Factor::ParallelAnalysis\n  #\n  # About number of components, O'Connor(2000) said:\n  #  The two procedures [PA and MAP ] complement each other nicely,\n  #  in that the MAP tends to err (when it does err) in the direction\n  #  of underextraction, whereas parallel analysis tends to err\n  #  (when it does err) in the direction of overextraction.\n  #  Optimal decisions are thus likely to be made after considering\n  #  the results of both analytic procedures. (p.10)\n\n  module Factor\n    # Anti-image covariance matrix.\n    # Useful for inspection of desireability of data for factor analysis.\n    # According to Dziuban  & Shirkey (1974, p.359): \n    #   \"If this matrix does not exhibit many zero off-diagonal elements,\n    #   the investigator has evidence that the correlation\n    #   matrix is not appropriate for factor analysis.\"\n    # \n    def self.anti_image_covariance_matrix(matrix)\n      s2=Matrix.diag(*(matrix.inverse.diagonal)).inverse\n      aicm=(s2)*matrix.inverse*(s2)\n      aicm.extend(Statsample::CovariateMatrix)\n      aicm.fields=matrix.fields if matrix.respond_to? :fields\n      aicm\n    end\n    def self.anti_image_correlation_matrix(matrix)\n      matrix=matrix.to_matrix\n      s=Matrix.diag(*(matrix.inverse.diagonal)).sqrt.inverse\n      aicm=s*matrix.inverse*s\n      \n      aicm.extend(Statsample::CovariateMatrix)\n      aicm.fields=matrix.fields if matrix.respond_to? :fields\n      aicm\n      \n    end\n      \n    # Kaiser-Meyer-Olkin measure of sampling adequacy for correlation matrix.\n    # \n    # Kaiser's (1974, cited on Dziuban  & Shirkey, 1974) present calibration of the index is as follows :\n    # * .90s—marvelous\n    # * .80s— meritorious\n    # * .70s—middling\n    # * .60s—mediocre\n    # * .50s—miserable\n    # * .50 •—unacceptable\n    def self.kmo(matrix)\n      q=anti_image_correlation_matrix(matrix)\n      n=matrix.row_size\n      sum_r,sum_q=0,0\n      n.times do |j|\n        n.times do |k|\n          if j!=k\n            sum_r+=matrix[j,k]**2\n            sum_q+=q[j,k]**2\n          end\n        end\n      end\n      sum_r.quo(sum_r+sum_q)\n    end\n    # Kaiser-Meyer-Olkin measure of sampling adequacy for one variable.\n    # \n    def self.kmo_univariate(matrix, var)\n      if var.is_a? String\n        if matrix.respond_to? :fields\n          j=matrix.fields.index(var)\n          raise \"Matrix doesn't have field #{var}\" if j.nil?\n        else\n          raise \"Matrix doesn't respond to fields\"\n        end\n      else\n        j=var\n      end\n      \n      q=anti_image_correlation_matrix(matrix)\n      n=matrix.row_size\n      \n      sum_r,sum_q=0,0\n      \n      n.times do |k|\n        if j!=k\n          sum_r+=matrix[j,k]**2\n          sum_q+=q[j,k]**2\n        end\n      end\n      sum_r.quo(sum_r+sum_q)\n    end\n    \n  end\nend\n"
  },
  {
    "path": "lib/statsample/graph/boxplot.rb",
    "content": "require 'rubyvis'\nmodule Statsample\n  module Graph\n    # = Boxplot\n    # \n    # From Wikipedia:\n    # In descriptive statistics, a box plot or boxplot (also known as a box-and-whisker diagram or plot) is a convenient way of graphically depicting groups of numerical data through their five-number summaries: the smallest observation (sample minimum), lower quartile (Q1), median (Q2), upper quartile (Q3), and largest observation (sample maximum). A boxplot may also indicate which observations, if any, might be considered outliers.\n    # \n    # == Usage\n    # === Svg output\n    #  a=[1,2,3,4].to_scale\n    #  b=[3,4,5,6].to_scale\n    #  puts Statsample::Graph::Boxplot.new(:vectors=>[a,b]).to_svg\n    # === Using ReportBuilder\n    #  a=[1,2,3,4].to_scale\n    #  b=[3,4,5,6].to_scale\n    #  rb=ReportBuilder.new\n    #  rb.add(Statsample::Graph::Boxplot.new(:vectors=>[a,b]))\n    #  rb.save_html('boxplot.html')\n    \n    class Boxplot\n      include Summarizable\n      attr_accessor :name\n      # Total width of Boxplot\n      attr_accessor :width\n      # Total height of Boxplot\n      attr_accessor :height\n      # Top margin\n      attr_accessor :margin_top\n      # Bottom margin\n      attr_accessor :margin_bottom\n      # Left margin\n      attr_accessor :margin_left\n      # Right margin\n      attr_accessor :margin_right\n      # Array with assignation to groups of bars\n      # For example, for four vectors, \n      #   boxplot.groups=[1,2,1,3]\n      # Assign same color to first and third element, and different to\n      # second and fourth\n      attr_accessor :groups\n      # Minimum value on y-axis. Automaticly defined from data\n      attr_accessor :minimum\n      # Maximum value on y-axis. Automaticly defined from data\n      attr_accessor :maximum\n      # Vectors to box-ploting\n      attr_accessor :vectors\n      # The rotation angle, in radians. Text is rotated clockwise relative \n      # to the anchor location. For example, with the default left alignment, \n      # an angle of Math.PI / 2 causes text to proceed downwards. The default angle is zero.      \n      attr_accessor :label_angle\n      attr_reader :x_scale, :y_scale\n      # Create a new Boxplot.\n      # Parameters: Hash of options\n      # * :vectors: Array of vectors\n      # * :groups: Array of same size as :vectors:, with name of groups\n      #           to colorize vectors\n      def initialize(opts=Hash.new)\n        @vectors=opts.delete :vectors\n        raise \"You should define vectors\" if @vectors.nil?\n        \n        opts_default={\n          :name=>_(\"Boxplot\"),\n          :groups=>nil,\n          :width=>400,\n          :height=>300,\n          :margin_top=>10,\n          :margin_bottom=>20,\n          :margin_left=>20,\n          :margin_right=>20,\n          :minimum=>nil,\n          :maximum=>nil,\n          :label_angle=>0\n        }\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k| send(\"#{k}=\", @opts[k]) }\n      end\n      \n      # Returns a Rubyvis panel with scatterplot\n      def rubyvis_panel # :nodoc:\n        that=self\n        \n        min,max=@minimum, @maximum\n        \n        min||=@vectors.map {|v| v.min}.min\n        max||=@vectors.map {|v| v.max}.max\n        \n        \n        \n        margin_hor=margin_left + margin_right\n        margin_vert=margin_top  + margin_bottom\n        x_scale = pv.Scale.ordinal(@vectors.size.times.map.to_a).split_banded(0, width-margin_hor, 4.0/5)\n        y_scale=Rubyvis::Scale.linear(min,max).range(0,height-margin_vert)\n        y_scale.nice\n        # cache data\n        \n        colors=Rubyvis::Colors.category10\n        \n        data=@vectors.map {|v|\n          out={:percentil_25=>v.percentil(25), :median=>v.median, :percentil_75=>v.percentil(75), :name=>v.name}\n          out[:iqr]=out[:percentil_75] - out[:percentil_25]\n          \n          irq_max=out[:percentil_75] + out[:iqr]\n          irq_min=out[:percentil_25] - out[:iqr]\n          \n          # Find the last data inside the margin\n          min = out[:percentil_25]\n          max = out[:percentil_75]\n          \n          v.each {|d|\n            min=d if d < min and d > irq_min\n            max=d if d > max and d < irq_max\n          }\n          # Whiskers!\n          out[:low_whisker]=min\n          out[:high_whisker]=max\n          # And now, data outside whiskers\n          out[:outliers]=v.data_with_nils.find_all {|d| d < min or d > max }\n          out\n        }\n        \n\n        \n        vis=Rubyvis::Panel.new do |pan| \n          pan.width  width  - margin_hor\n          pan.height height - margin_vert\n          pan.bottom margin_bottom\n          pan.left   margin_left\n          pan.right  margin_right\n          pan.top    margin_top\n           # Y axis\n          pan.rule do\n            data y_scale.ticks\n            bottom y_scale\n            stroke_style {|d| d!=0 ? \"#eee\" : \"#000\"}\n            label(:anchor=>'left') do\n              text y_scale.tick_format\n            end\n          end\n          pan.rule do\n            bottom 0\n            stroke_style 'black'\n          end\n          \n          # Labels\n          \n          pan.label  do |l|\n            l.data data\n            l.text_angle that.label_angle\n            l.left  {|v| x_scale[index] }\n            l.bottom(-15)\n            l.text {|v,x| v[:name]}\n          end\n          \n          pan.panel do |bp|\n            bp.data data\n            bp.left {|v|  x_scale[index]}\n            bp.width x_scale.range_band\n            \n            \n            # Bar\n            bp.bar do |b|\n              b.bottom {|v| y_scale[v[:percentil_25]]}\n              b.height {|v| y_scale[v[:percentil_75]] - y_scale[v[:percentil_25]] }\n              b.line_width 1\n              b.stroke_style  {|v| \n                if that.groups\n                  colors.scale(that.groups[parent.index]).darker\n                else\n                  colors.scale(index).darker\n                end\n              \n              \n              }\n              b.fill_style {|v| \n                if that.groups\n                  colors.scale(that.groups[parent.index])\n                else\n                  colors.scale(index)\n                end\n              }\n            end\n            # Median\n            bp.rule do |r|\n              r.bottom {|v| y_scale[v[:median]]}\n              r.width x_scale.range_band\n              r.line_width 2\n            end\n            ##\n            # Whiskeys\n            ##\n            # Low whiskey\n            bp.rule do |r|\n              r.visible {|v| v[:percentil_25] > v[:low_whisker]}\n              r.bottom {|v| y_scale[v[:low_whisker]]}              \n            end\n            \n            bp.rule do |r|\n              r.visible {|v| v[:percentil_25] > v[:low_whisker]}\n              r.bottom {|v| y_scale[v[:low_whisker]]}              \n              r.left {|v| x_scale.range_band / 2.0}\n              r.height {|v| y_scale.scale(v[:percentil_25]) - y_scale.scale(v[:low_whisker])}\n            end\n            # High whiskey\n\n            bp.rule do |r|\n              r.visible {|v| v[:percentil_75] < v[:high_whisker]}\n              r.bottom {|v| y_scale.scale(v[:high_whisker])}              \n            end\n            \n             bp.rule do |r|\n              r.visible {|v| v[:percentil_75] < v[:high_whisker]}\n              r.bottom {|v| y_scale.scale(v[:percentil_75])}              \n              r.left {|v| x_scale.range_band / 2.0}\n              r.height {|v| y_scale.scale(v[:high_whisker]) - y_scale.scale(v[:percentil_75])}\n            end\n            # Outliers\n            bp.dot do |dot|\n              dot.shape_size 4\n              dot.data {|v| v[:outliers]}\n              dot.left {|v| x_scale.range_band / 2.0}\n              dot.bottom {|v| y_scale.scale(v)}\n              dot.title {|v| v}\n            end\n          end\n        end\n        vis\n      end\n      \n      # Returns SVG with scatterplot\n      def to_svg\n        rp=rubyvis_panel\n        rp.render\n        rp.to_svg\n      end\n      def report_building(builder) # :nodoc:\n        builder.section(:name=>name) do |b|\n          b.image(to_svg, :type=>'svg', :width=>width, :height=>height)\n        end\n        \n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/graph/histogram.rb",
    "content": "require 'rubyvis'\nmodule Statsample\n  module Graph\n    \n    # In statistics, a histogram is a graphical representation, showing a visual impression of the distribution of experimental data. It is an estimate of the probability distribution of a continuous variable and was first introduced by Karl Pearson [1]. A histogram consists of tabular frequencies, shown as adjacent rectangles, erected over discrete intervals (bins), with an area equal to the frequency of the observations in the interval. The height of a rectangle is also equal to the frequency density of the interval, i.e., the frequency divided by the width of the interval. The total area of the histogram is equal to the number of data.\n    # \n    # == Usage\n    # === Svg output\n    #  a=[1,2,3,4].to_scale\n    #  puts Statsample::Graph::Histogram.new(a).to_svg\n    # === Using ReportBuilder\n    #  a=[1,2,3,4].to_scale\n    #  rb=ReportBuilder.new\n    #  rb.add(Statsample::Graph::Histogram.new(a))\n    #  rb.save_html('histogram.html')\n    \n    class Histogram\n      include Summarizable\n      # Histogram name\n      attr_accessor :name\n      # Total width\n      attr_accessor :width\n      # Total height\n      attr_accessor :height\n      # Top margin\n      attr_accessor :margin_top\n      # Bottom margin\n      attr_accessor :margin_bottom\n      # Left margin\n      attr_accessor :margin_left\n      # Right margin\n      attr_accessor :margin_right\n      attr_reader :hist\n      # Could be an array of ranges or number of bins\n      attr_accessor :bins\n      # Minimum value on x axis. Calculated automaticly from data if not set\n      attr_accessor :minimum_x\n      # Maximum value on x axis. Calculated automaticly from data if not set\n      attr_accessor :maximum_x\n      # Minimum value on y axis. Set to 0 if not set\n      attr_accessor :minimum_y\n      # Maximum value on y axis. Calculated automaticly from data if not set.\n      attr_accessor :maximum_y\n      # Add a line showing normal distribution\n      attr_accessor :line_normal_distribution\n      # data could be a vector or a histogram\n      def initialize(data, opts=Hash.new)\n        prov_name=(data.respond_to?(:name)) ? data.name : \"\"\n        opts_default={\n          :name=>_(\"Histograma (%s)\") % prov_name,\n          :width=>400,\n          :height=>300,\n          :margin_top=>10,\n          :margin_bottom=>20,\n          :margin_left=>30,\n          :margin_right=>20,\n          :minimum_x=>nil,\n          :maximum_x=>nil,\n          :minimum_y=>nil,\n          :maximum_y=>nil,\n          :bins=>nil,\n          :line_normal_distribution=>false\n        }\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k| send(\"#{k}=\", @opts[k]) }\n        @data=data\n      end\n      def pre_vis # :nodoc:\n        if @data.is_a? Statsample::Histogram\n          @hist=@data\n          @mean=@hist.estimated_mean\n          @sd=@hist.estimated_standard_deviation\n        elsif @data.is_a? Statsample::Vector\n          @mean=@data.mean\n          @sd=@data.sd\n          @bins||=Math::sqrt(@data.size).floor\n          @hist=@data.histogram(@bins)\n        end\n      end\n      def rubyvis_normal_distribution(pan)\n        x_scale=@x_scale\n        y_scale=@y_scale\n        \n        wob = @hist.get_range(0)[1] - @hist.get_range(0)[0]\n        \n        nob = ((@maximum_x-@minimum_x) / wob.to_f).floor\n        sum=@hist.sum\n        \n        data=nob.times.map {|i|\n          l=@minimum_x+i*wob\n          r=@minimum_x+(i+1)*wob          \n          middle=(l+r) / 2.0\n          pi=Distribution::Normal.cdf((r-@mean) / @sd) - Distribution::Normal.cdf((l-@mean) / @sd)\n          {:x=>middle, :y=>pi*sum}\n        }\n        pan.line do |l|\n          l.data data\n          l.interpolate \"cardinal\"\n          l.stroke_style \"black\"\n          l.bottom {|d| y_scale[d[:y]]}\n          l.left {|d| x_scale[d[:x]]}\n        end\n        \n      end\n      # Returns a Rubyvis panel with scatterplot\n      def rubyvis_panel # :nodoc:\n        pre_vis\n        #that=self\n        \n        @minimum_x||=@hist.min\n        @maximum_x||=@hist.max\n        @minimum_y||=0\n        @maximum_y||=@hist.max_val\n        \n        margin_hor=margin_left + margin_right\n        margin_vert=margin_top  + margin_bottom\n      \n        x_scale = pv.Scale.linear(@minimum_x, @maximum_x).range(0, width - margin_hor)\n      \n        y_scale=Rubyvis::Scale.linear(@minimum_y, @maximum_y).range(0, height - margin_vert)\n        \n        y_scale.nice\n        \n        bins=@hist.bins.times.map {|i|\n          {\n           :low =>@hist.get_range(i)[0],\n           :high=>@hist.get_range(i)[1],\n           :value=>@hist.bin[i]\n          }\n        }\n        @x_scale=x_scale\n        @y_scale=y_scale\n        # cache data\n        vis=Rubyvis::Panel.new do |pan| \n          pan.width  width  - margin_hor\n          pan.height height - margin_vert\n          pan.bottom margin_bottom\n          pan.left   margin_left\n          pan.right  margin_right\n          pan.top    margin_top\n           # Y axis\n          pan.rule do\n            data y_scale.ticks\n            bottom y_scale\n            stroke_style {|d| d!=0 ? \"#eee\" : \"#000\"}\n            label(:anchor=>'left') do\n              text y_scale.tick_format\n            end\n          end\n          # X axis\n          pan.rule do\n            data x_scale.ticks\n            left x_scale\n            stroke_style \"black\"\n            height 5\n            bottom(-5)\n            label(:anchor=>'bottom') do\n              text x_scale.tick_format\n            end\n          end\n         \n          pan.bar do |bar|\n            bar.data(bins)\n            bar.left {|v| x_scale[v[:low]]}\n            bar.width {|v| x_scale[v[:high]] - x_scale[v[:low]]}\n            bar.bottom 0\n            bar.height {|v| y_scale[v[:value]]}\n            bar.stroke_style \"black\"\n            bar.line_width 1\n          end\n           rubyvis_normal_distribution(pan) if @line_normal_distribution\n        end\n        vis\n      end\n      # Returns SVG with scatterplot\n      def to_svg\n        rp=rubyvis_panel\n        rp.render\n        rp.to_svg\n      end\n      def report_building(builder) # :nodoc:\n        builder.section(:name=>name) do |b|\n          b.image(to_svg, :type=>'svg', :width=>width, :height=>height)\n        end\n      end\n      def report_building_text(generator)\n        pre_vis\n        #anchor=generator.toc_entry(_(\"Histogram %s\") % [@name])\n        step=  @hist.max_val > 40 ? ( @hist.max_val / 40).ceil : 1\n          \n        @hist.range.each_with_index do |r,i|\n          next if i==@hist.bins\n          generator.text(sprintf(\"%5.2f : %s\", r, \"*\" * (@hist.bin[i] / step).floor ))\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/graph/scatterplot.rb",
    "content": "require 'rubyvis'\nmodule Statsample\n  module Graph\n    # = Scatterplot\n    # \n    # From Wikipedia:\n    # A scatter plot or scattergraph is a type of mathematical diagram using\n    # Cartesian coordinates to display values for two variables for a set of data.\n    # \n    # The data is displayed as a collection of points, each having the value of one variable determining the position on the horizontal axis and the value of the other variable determining the position on the vertical axis.[2] This kind of plot is also called a scatter chart, scatter diagram and scatter graph.\n    # == Usage\n    # === Svg output\n    #  a=[1,2,3,4].to_scale\n    #  b=[3,4,5,6].to_scale\n    #  puts Statsample::Graph::Scatterplot.new(a,b).to_svg\n    # === Using ReportBuilder\n    #  a=[1,2,3,4].to_scale\n    #  b=[3,4,5,6].to_scale\n    #  rb=ReportBuilder.new\n    #  rb.add(Statsample::Graph::Scatterplot.new(a,b))\n    #  rb.save_html('scatter.html')\n    \n    class Scatterplot\n      include Summarizable\n      attr_accessor :name\n      # Total width of Scatterplot\n      attr_accessor :width\n      # Total height of Scatterplot\n      attr_accessor :height\n      attr_accessor :dot_alpha\n      # Add a line on median of x and y axis \n      attr_accessor :line_median\n      # Top margin\n      attr_accessor :margin_top\n      # Bottom margin\n      attr_accessor :margin_bottom\n      # Left margin\n      attr_accessor :margin_left\n      # Right margin\n      attr_accessor :margin_right\n      \n      attr_reader   :data\n      attr_reader :v1,:v2\n      \n      # Array with assignation to groups of bars\n      # For example, for four vectors, \n      #   boxplot.groups=[1,2,1,3]\n      # Assign same color to first and third element, and different to\n      # second and fourth\n      attr_accessor :groups\n\n      \n      attr_reader :x_scale, :y_scale\n      # Minimum value on x axis. Calculated automaticly from data if not set\n      attr_accessor :minimum_x\n      # Maximum value on x axis. Calculated automaticly from data if not set\n      attr_accessor :maximum_x\n      # Minimum value on y axis. Set to 0 if not set\n      attr_accessor :minimum_y\n      # Maximum value on y axis. Calculated automaticly from data if not set.\n      attr_accessor :maximum_y\n\n      # Create a new Scatterplot.\n      # Params:\n      # * v1: Vector on X axis\n      # * v2: Vector on Y axis\n      # * opts: Hash of options. See attributes of Scatterplot\n      def initialize(v1,v2,opts=Hash.new)\n        @v1_name,@v2_name = v1.name,v2.name\n        @v1,@v2           = Statsample.only_valid_clone(v1,v2)\n        opts_default={\n          :name=>_(\"Scatterplot (%s - %s)\") % [@v1_name, @v2_name],\n          :width=>400,\n          :height=>300,\n          :dot_alpha=>0.5,\n          :line_median=>false,\n          :margin_top=>10,\n          :margin_bottom=>20,\n          :margin_left=>20,\n          :margin_right=>20,\n          :minimum_x=>nil,\n          :maximum_x=>nil,\n          :minimum_y=>nil,\n          :maximum_y=>nil,\n          :groups=>nil\n        }\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k| send(\"#{k}=\", @opts[k]) }\n        @data=[]\n        @v1.each_with_index {|d1,i|\n          @data.push({:x=>d1, :y=>@v2[i]})\n        }\n      end\n      # Add a rule on median of X and Y axis\n      def add_line_median(vis) # :nodoc:\n        that=self\n        x=@x_scale\n        y=@y_scale\n        vis.execute {\n          rule do\n            data [that.v1.median]\n            left x\n            stroke_style Rubyvis.color(\"#933\").alpha(0.5)\n            label(:anchor=>\"top\") do\n              text x.tick_format\n            end\n          end\n          rule do\n            data [that.v2.median]\n            bottom y\n            stroke_style Rubyvis.color(\"#933\").alpha(0.5)\n            label(:anchor=>\"right\") do\n              text y.tick_format\n            end\n          end  \n        }\n        \n      end\n      # Returns a Rubyvis panel with scatterplot\n      def rubyvis_panel # :nodoc:\n        that=self\n        #p @v1.map {|v| v}\n        \n        @minimum_x||=@v1.min\n        @maximum_x||=@v1.max\n        @minimum_y||=@v2.min\n        @maximum_y||=@v2.max\n        \n        colors=Rubyvis::Colors.category10\n        \n        margin_hor=margin_left + margin_right\n        margin_vert=margin_top  + margin_bottom\n        \n        x=Rubyvis::Scale.linear(@minimum_x, @maximum_x).range(0, width - margin_hor)\n        y=Rubyvis::Scale.linear(@minimum_y, @maximum_y).range(0, height - margin_vert)\n        @x_scale=x\n        @y_scale=y\n        vis=Rubyvis::Panel.new do |pan| \n          pan.width  width  - margin_hor\n          pan.height height - margin_vert\n          pan.bottom margin_bottom\n          pan.left   margin_left\n          pan.right  margin_right\n          pan.top    margin_top\n          # X axis\n          pan.rule do\n            data y.ticks\n            bottom y\n            stroke_style {|d| d!=0 ? \"#eee\" : \"#000\"}\n            label(:anchor=>'left') do\n              visible {|d| d!=0 and  d < that.width}\n              text y.tick_format\n            end\n          end\n          \n          # Y axis\n          pan.rule do\n            data x.ticks\n            left x\n            stroke_style {|d| d!=0 ? \"#eee\" : \"#000\"}\n            label(:anchor=>'bottom') do\n              visible {|d| d>0 and d < that.height}\n              text x.tick_format\n            end\n          end\n          # Add lines on median\n          add_line_median(pan) if line_median\n\n          pan.panel do\n            data(that.data)\n            dot do\n              left   {|d| x[d[:x]]}\n              bottom {|d| y[d[:y]]}\n              \n              fill_style {|v| \n                alpha=(that.dot_alpha-0.3<=0) ? 0.1 : that.dot_alpha-0.3\n                if that.groups\n                  \n                  colors.scale(that.groups[index]).alpha(alpha)\n                else\n                  colors.scale(0).alpha(alpha)\n                end\n              }\n              \n              stroke_style {|v|\n                if that.groups\n                  colors.scale(that.groups[parent.index]).alpha(that.dot_alpha)\n                else\n                  colors.scale(0).alpha(that.dot_alpha)\n                end\n              }\n              shape_radius 2\n            end\n          end\n        end\n        vis\n      end\n      # Returns SVG with scatterplot\n      def to_svg\n        rp=rubyvis_panel\n        rp.render\n        rp.to_svg\n      end\n      def report_building(builder) # :nodoc:\n        builder.section(:name=>name) do |b|\n          b.image(to_svg, :type=>'svg', :width=>width, :height=>height)\n        end\n        \n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/graph.rb",
    "content": "require 'statsample/graph/scatterplot'\nrequire 'statsample/graph/boxplot'\nrequire 'statsample/graph/histogram'\nmodule Statsample\n  # Several Graph, based on Rubyvis\n  # * Statsample::Graph::Boxplot\n  # * Statsample::Graph::Histogram  \n  # * Statsample::Graph::Scatterplot\n  module Graph\n  end\nend\n"
  },
  {
    "path": "lib/statsample/histogram.rb",
    "content": "module Statsample\n  # A histogram consists of a set of bins which count the \n  # number of events falling into a given range of a continuous variable x. \n  # \n  # This implementations follows convention of GSL\n  # for specification.\n  # \n  #  * Verbatim: *\n  #\n  #  The range for bin[i] is given by range[i] to range[i+1]. \n  #  For n bins there are n+1 entries in the array range. \n  #  Each bin is inclusive at the lower end and exclusive at the upper end. \n  #  Mathematically this means that the bins are defined \n  #  by the following inequality,\n  # \n  #   bin[i] corresponds to range[i] <= x < range[i+1]\n  # \n  #  Here is a diagram of the correspondence between ranges and bins\n  #  on the number-line for x,\n  # \n  # \n  #      [ bin[0] )[ bin[1] )[ bin[2] )[ bin[3] )[ bin[4] )\n  #   ---|---------|---------|---------|---------|---------|---  x\n  #    r[0]      r[1]      r[2]      r[3]      r[4]      r[5]\n  # \n  # \n  #  In this picture the values of the range array are denoted by r. \n  #  On the left-hand side of each bin the square bracket ‘[’ denotes \n  #  an inclusive lower bound ( r <= x), and the round parentheses ‘)’ \n  #  on the right-hand side denote an exclusive upper bound (x < r). \n  #  Thus any samples which fall on the upper end of the histogram are \n  #  excluded. \n  #  If you want to include this value for the last bin you will need to \n  #  add an extra bin to your histogram. \n  #\n  #\n  # == Reference:\n  # * http://www.gnu.org/software/gsl/manual/html_node/The-histogram-struct.html\n  \n    class Histogram\n      include Enumerable\n      class << self\n        # Alloc +n_bins+, using +range+ as ranges of bins\n        def alloc(n_bins, range=nil, opts=Hash.new)\n          Histogram.new(n_bins, range, opts)\n          \n        end\n        # Alloc +n_bins+ bins, using +p1+ as minimum and +p2+\n        # as maximum\n        def alloc_uniform(n_bins, p1=nil,p2=nil)\n          if p1.is_a? Array\n            min,max=p1\n          else\n            min,max=p1,p2\n          end\n          range=max - min\n          step=range / n_bins.to_f\n          range=(n_bins+1).times.map {|i| min + (step*i)}\n          Histogram.new(range)\n        end\n      end\n      attr_accessor :name\n      attr_reader :bin\n      attr_reader :range\n      include GetText\n      bindtextdomain(\"statsample\")\n      def initialize(p1, min_max=false, opts=Hash.new)\n        \n        if p1.is_a? Array\n          range=p1\n          @n_bins=p1.size-1\n        elsif p1.is_a? Integer\n          @n_bins=p1\n        end\n        \n        @bin=[0.0]*(@n_bins)\n        if(min_max)\n          min, max=min_max[0], min_max[1]\n          range=Array.new(@n_bins+1)\n          (@n_bins+1).times {|i| range[i]=min+(i*(max-min).quo(@n_bins)) }\n        end\n        range||=[0.0]*(@n_bins+1)\n        set_ranges(range)\n        @name=\"\"\n        opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n      end\n      # Number of bins\n      def bins\n        @n_bins\n      end\n      # \n      def increment(x, w=1)\n        if x.respond_to? :each\n          x.each{|y| increment(y,w) }\n        elsif x.is_a? Numeric\n          (range.size-1).times do |i|\n            if x>=range[i] and x<range[i+1]\n              @bin[i]+=w\n              break\n            end\n          end\n        end\n      end\n      def set_ranges(range)\n        raise \"Range size should be bin+1\" if range.size!=@bin.size+1\n        @range=range\n      end\n      def get_range(i)\n        [@range[i],@range[i+1]]\n      end\n      def max\n        @range.last\n      end\n      def min\n        @range.first\n      end\n      def max_val\n        @bin.max\n      end\n      def min_val\n        @bin.min\n      end\n      def each\n        bins.times.each do |i|\n          r=get_range(i)\n          arg={:i=>i, :low=>r[0],:high=>r[1], :middle=>(r[0]+r[1]) / 2.0,  :value=>@bin[i]}\n          yield arg\n        end\n      end\n      def estimated_variance\n        sum,n=0,0\n        mean=estimated_mean\n        each do |v|\n          sum+=v[:value]*(v[:middle]-mean)**2\n          n+=v[:value]\n        end\n        sum / (n-1)\n      end\n      def estimated_standard_deviation\n        Math::sqrt(estimated_variance)\n      end\n      def estimated_mean\n        sum,n=0,0\n        each do |v|\n          sum+= v[:value]* v[:middle]\n          n+=v[:value]\n        end\n        sum / n\n      end\n      alias :mean :estimated_mean\n      alias :sigma :estimated_standard_deviation\n      \n      def sum(start=nil,_end=nil)\n        start||=0\n        _end||=@n_bins-1\n        (start.._end).inject(0) {|ac,i| ac+@bin[i]}\n      end\n      def report_building(generator)\n        hg=Statsample::Graph::Histogram.new(self)\n        generator.parse_element(hg)\n      end\n      def report_building_text(generator)\n        @range.each_with_index do |r,i|\n          next if i==@bin.size\n          generator.text(sprintf(\"%5.2f : %d\", r, @bin[i]))\n        end\n      end\n    end\nend\n"
  },
  {
    "path": "lib/statsample/matrix.rb",
    "content": "class ::Vector\n  def to_matrix\n    ::Matrix.columns([self.to_a])\n  end\n  def to_vector\n    self\n  end\nend\nclass ::Matrix\n  def to_matrix\n    self\n  end\n  def to_dataset\n    f = (self.respond_to? :fields_y) ? fields_y : column_size.times.map {|i| _(\"VAR_%d\") % (i+1) }\n    ds=Statsample::Dataset.new(f)\n    f.each do |ff|\n      ds[ff].type=:scale\n      ds[ff].name=ff\n    end\n    row_size.times {|i|\n      ds.add_case_array(self.row(i).to_a)\n    }\n    ds.update_valid_data\n    ds.name=self.name if self.respond_to? :name\n    ds\n  end\n  if defined? :eigenpairs\n    alias_method :eigenpairs_ruby, :eigenpairs\n  end\n  \n  if Statsample.has_gsl?\n    # Optimize eigenpairs of extendmatrix module using gsl\n    def eigenpairs\n      to_gsl.eigenpairs\n    end\n  end\n  \n  def eigenvalues\n    eigenpairs.collect {|v| v[0]}\n  end\n  def eigenvectors\n    eigenpairs.collect {|v| v[1]}\n  end\n  def eigenvectors_matrix\n    Matrix.columns(eigenvectors)\n  end\n  \n  \n\n  \n  \n  def to_gsl\n    out=[]\n    self.row_size.times{|i|\n      out[i]=self.row(i).to_a\n    }\n    GSL::Matrix[*out]\n  end\nend\n\nmodule GSL\n  class Vector\n    class Col\n      def to_matrix\n      ::Matrix.columns([self.size.times.map {|i| self[i]}])\n      end\n      def to_ary\n        to_a\n      end\n      def to_gsl\n        self\n      end\n    end\n  end\n  class Matrix\n    def to_gsl\n      self\n    end\n    \n    def to_dataset\n      f = (self.respond_to? :fields_y) ? fields_y : column_size.times.map {|i| _(\"VAR_%d\") % (i+1) }\n      ds=Statsample::Dataset.new(f)\n      f.each do |ff|\n        ds[ff].type=:scale\n        ds[ff].name=ff\n      end\n      row_size.times {|i|\n        ds.add_case_array(self.row(i).to_a)\n      }\n      ds.update_valid_data\n      ds.name=self.name if self.respond_to? :name\n      ds\n    end\n    \n    def row_size\n      size1\n    end\n    def column_size\n      size2\n    end\n    def determinant\n      det\n    end\n    def inverse\n      GSL::Linalg::LU.invert(self)\n    end\n    def eigenvalues\n      eigenpairs.collect {|v| v[0]}\n    end\n    def eigenvectors\n      eigenpairs.collect {|v| v[1]}\n    end\n    \n    # Matrix sum of squares\n    def mssq\n      sum=0\n      to_v.each {|i| sum+=i**2}\n      sum\n    end\n    \n    def eigenvectors_matrix\n      eigval, eigvec= GSL::Eigen.symmv(self)\n      GSL::Eigen::symmv_sort(eigval, eigvec, GSL::Eigen::SORT_VAL_DESC)\n      eigvec \n    end\n    def eigenpairs\n      eigval, eigvec= GSL::Eigen.symmv(self)\n      GSL::Eigen::symmv_sort(eigval, eigvec, GSL::Eigen::SORT_VAL_DESC)\n      @eigenpairs=eigval.size.times.map {|i|\n        [eigval[i],eigvec.get_col(i)]\n      }\n    end\n    \n    #def eigenpairs_ruby\n    #  self.to_matrix.eigenpairs_ruby\n    #end\n    def square?\n      size1==size2\n    end\n    def to_matrix\n      rows=self.size1\n      cols=self.size2\n      out=(0...rows).collect{|i| (0...cols).collect {|j| self[i,j]} }\n      ::Matrix.rows(out)\n    end\n    def total_sum\n      sum=0\n      size1.times {|i|\n        size2.times {|j|\n          sum+=self[i,j]\n        }\n      }\n      sum\n    end\n  end\nend\n\nmodule Statsample\n  # Module to add names to X and Y fields\n  module NamedMatrix\n    include Summarizable  \n\n    def fields\n    raise \"Should be square\" if !square?\n    fields_x\n    end\n    def fields=(v)\n    raise \"Matrix should be square\" if !square?\n    @fields_x=v\n    @fields_y=v\n    end\n    def fields_x=(v)\n    raise \"Size of fields != row_size\" if v.size!=row_size\n    @fields_x=v\n    end\n    def fields_y=(v)\n    raise \"Size of fields != column_size\" if v.size!=column_size\n    @fields_y=v\n    end\n    def fields_x\n    @fields_x||=row_size.times.collect {|i| _(\"X%d\") % i} \n    end\n    def fields_y\n    @fields_y||=column_size.times.collect {|i| _(\"Y%d\") % i} \n    end\n\n    def name\n      @name||=get_new_name\n    end\n    def name=(v)\n      @name=v\n    end\n    def get_new_name\n      @@named_matrix||=0\n      @@named_matrix+=1\n      _(\"Matrix %d\") % @@named_matrix\n    end\n    \n  end\n  # Module to add method for variance/covariance and correlation matrices\n  # == Usage\n  #  matrix=Matrix[[1,2],[2,3]]\n  #  matrix.extend CovariateMatrix\n  # \n  module CovariateMatrix\n    include NamedMatrix\n    @@covariatematrix=0\n\n    # Get type of covariate matrix. Could be :covariance or :correlation\n    def _type\n      if row_size==column_size\n        if row_size.times.find {|i| self[i,i]!=1.0}\n          :covariance\n        else\n          :correlation\n        end\n      else\n        @type\n      end\n      \n    end\n    def _type=(t)\n      @type=t\n    end\n    def correlation\n      if(_type==:covariance)\n        matrix=Matrix.rows(row_size.times.collect { |i|\n          column_size.times.collect { |j|\n            if i==j\n              1.0\n            else\n              self[i,j].quo(Math::sqrt(self[i,i])*Math::sqrt(self[j,j]))\n            end\n          }\n        })\n        matrix.extend CovariateMatrix \n        matrix.fields_x=fields_x\n        matrix.fields_y=fields_y\n        matrix._type=:correlation\n        matrix\n      else\n        self\n      end\n    end\n    \n    \n    # Get variance for field k\n    # \n    def variance(k)\n      submatrix([k])[0,0]\n    end\n    \n    def get_new_name\n      @@covariatematrix+=1\n      _(\"Covariate matrix %d\") % @@covariatematrix\n    end\n    \n    # Select a submatrix of factors. If you have a correlation matrix\n    # with a, b and c, you could obtain a submatrix of correlations of\n    # a and b, b and c or a and b\n    #\n    # You could use labels or index to select the factors.\n    # If you don't specify columns, its will be equal to rows.\n    #\n    # Example:\n    #   a=Matrix[[1.0, 0.3, 0.2],\n    #            [0.3, 1.0, 0.5], \n    #            [0.2, 0.5, 1.0]]\n    #   a.extend CovariateMatrix\n    #   a.fields=%w{a b c}\n    #   a.submatrix(%w{c a}, %w{b})\n    #   => Matrix[[0.5],[0.3]]\n    #   a.submatrix(%w{c a})\n    #   => Matrix[[1.0, 0.2] , [0.2, 1.0]]\n    def submatrix(rows,columns=nil)\n      raise ArgumentError, \"rows shouldn't be empty\" if rows.respond_to? :size and rows.size==0\n      columns||=rows\n      # Convert all fields on index\n      row_index=rows.collect {|v| \n        r=v.is_a?(Numeric) ? v : fields_x.index(v)\n        raise \"Index #{v} doesn't exists on matrix\" if r.nil?\n        r\n      }\n      column_index=columns.collect {|v| \n        r=v.is_a?(Numeric) ? v : fields_y.index(v)\n        raise \"Index #{v} doesn't exists on matrix\" if r.nil?\n        r\n      }\n      \n      \n      fx=row_index.collect {|v| fields_x[v]}\n      fy=column_index.collect {|v| fields_y[v]}\n        \n      matrix= Matrix.rows(row_index.collect {|i|\n        row=column_index.collect {|j| self[i,j]}})\n      matrix.extend CovariateMatrix \n      matrix.fields_x=fx\n      matrix.fields_y=fy\n      matrix._type=_type\n      matrix\n    end\n    def report_building(generator)\n      @name||= (_type==:correlation ? _(\"Correlation\"):_(\"Covariance\"))+_(\" Matrix\")\n      generator.table(:name=>@name, :header=>[\"\"]+fields_y) do |t|\n        row_size.times {|i|\n          t.row([fields_x[i]]+row(i).to_a.collect {|i1|\n              i1.nil? ? \"--\" : sprintf(\"%0.3f\",i1).gsub(\"0.\",\".\")\n          })\n        }\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/multiset.rb",
    "content": "module Statsample\n  # Multiset joins multiple dataset with the same fields and vectors\n  # but with different number of cases. \n  # This is the base class for stratified and cluster sampling estimation\n  class Multiset\n    # Name of fields\n    attr_reader :fields\n    # Array with Statsample::Dataset\n    attr_reader :datasets\n    # To create a multiset\n    # * Multiset.new(%w{f1 f2 f3}) # define only fields\n    def initialize(fields)\n        @fields=fields\n        @datasets={}\n    end\n    def self.new_empty_vectors(fields,ds_names) \n        ms=Multiset.new(fields)\n        ds_names.each{|d|\n            ms.add_dataset(d,Dataset.new(fields))\n        }\n        ms\n    end\n    # Generate a new dataset as a union of partial dataset\n    # If block given, this is applied to each dataset before union\n    def union(&block)\n      union_field={}\n      types={}\n      names={}\n      labels={}\n      each do |k,ds|\n        if block\n          ds=ds.dup\n          yield k,ds\n        end\n        @fields.each do |f|\n          union_field[f]||=Array.new\n          union_field[f].concat(ds[f].data)\n          types[f]||=ds[f].type\n          names[f]||=ds[f].name\n          labels[f]||=ds[f].labels\n        end\n      end\n      \n      @fields.each do |f|\n        union_field[f]=union_field[f].to_vector(types[f])\n        union_field[f].name=names[f]\n        union_field[f].labels=labels[f]\n      end\n      ds_union=union_field.to_dataset\n      ds_union.fields=@fields\n      ds_union\n    end\n    def datasets_names\n        @datasets.keys.sort\n    end\n    def n_datasets\n        @datasets.size\n    end\n    def add_dataset(key,ds)\n      if(ds.fields!=@fields)\n       raise ArgumentError, \"Dataset(#{ds.fields.to_s})must have the same fields of the Multiset(#{@fields})\"\n      else\n          @datasets[key]=ds\n      end\n    end\n    def sum_field(field)\n      @datasets.inject(0) {|a,da|\n        stratum_name=da[0]\n        vector=da[1][field]\n        val=yield stratum_name,vector\n        a+val\n      }\n    end\n    def collect_vector(field)\n      @datasets.collect {|k,v|\n        yield k, v[field]\n      }\n    end\n    \n    def each_vector(field)\n      @datasets.each {|k,v|\n        yield k, v[field]\n      }\n    end\n    def[](i)\n      @datasets[i]\n    end\n    def each(&block)\n      @datasets.each {|k,ds|\n        next if ds.cases==0\n        block.call(k,ds)\n      }\n    end\n  end\n  class StratifiedSample\n    class << self\n      # mean for an array of vectors\n      def mean(*vectors)\n        n_total=0\n        means=vectors.inject(0){|a,v|\n          n_total+=v.size\n          a+v.sum\n        }\n        means.to_f/n_total\n      end\n      \n      def standard_error_ksd_wr(es)\n        n_total=0\n        sum=es.inject(0){|a,h|\n            n_total+=h['N']\n            a+((h['N']**2 * h['s']**2) / h['n'].to_f)\n        }\n        (1.to_f / n_total)*Math::sqrt(sum)\n      end\n      \n      \n      def variance_ksd_wr(es)\n        standard_error_ksd_wr(es)**2\n      end\n      def calculate_n_total(es)\n        es.inject(0) {|a,h| a+h['N'] }\n      end\n      # Source : Cochran (1972)\n      \n      def variance_ksd_wor(es)\n      n_total=calculate_n_total(es)\n      es.inject(0){|a,h|\n        val=((h['N'].to_f / n_total)**2) * (h['s']**2 / h['n'].to_f) * (1 - (h['n'].to_f / h['N']))\n        a+val\n      }\n      end\n      def standard_error_ksd_wor(es)\n        Math::sqrt(variance_ksd_wor(es))\n      end\n      \n      \n      \n      def variance_esd_wor(es)\n        n_total=calculate_n_total(es)\n        sum=es.inject(0){|a,h|\n          val=h['N']*(h['N']-h['n'])*(h['s']**2 / h['n'].to_f)\n          a+val\n        }\n        (1.0/(n_total**2))*sum\n      end\n      \n      \n      def standard_error_esd_wor(es)\n        Math::sqrt(variance_ksd_wor(es))\n      end\n      # Based on http://stattrek.com/Lesson6/STRAnalysis.aspx\n      def variance_esd_wr(es)\n        n_total=calculate_n_total(es)\n          sum=es.inject(0){|a,h|\n            val= ((h['s']**2 * h['N']**2) / h['n'].to_f)\n            a+val\n          }\n          (1.0/(n_total**2))*sum\n      end\n      def standard_error_esd_wr(es)\n        Math::sqrt(variance_esd_wr(es))\n      end\n      \n      def proportion_variance_ksd_wor(es)\n        n_total=calculate_n_total(es)\n          es.inject(0){|a,h|\n            val= (((h['N'].to_f / n_total)**2 * h['p']*(1-h['p'])) / (h['n'])) * (1- (h['n'].to_f / h['N']))\n            a+val\n          }\n      end\n      def proportion_sd_ksd_wor(es)\n          Math::sqrt(proportion_variance_ksd_wor(es))\n      end\n      \n      \n      def proportion_sd_ksd_wr(es)\n        n_total=calculate_n_total(es)\n        sum=es.inject(0){|a,h|\n          val= (h['N']**2 * h['p']*(1-h['p'])) / h['n'].to_f\n          a+val\n        }\n        Math::sqrt(sum) * (1.0/n_total)\n      end\n      def proportion_variance_ksd_wr(es)\n          proportion_variance_ksd_wor(es)**2\n      end\n      \n      def proportion_variance_esd_wor(es)\n        n_total=n_total=calculate_n_total(es)\n        \n        sum=es.inject(0){|a,h|\n          a=(h['N']**2 * (h['N']-h['n']) * h['p']*(1.0-h['p'])) / ((h['n']-1)*(h['N']-1))\n          a+val\n        }\n        Math::sqrt(sum) * (1.0/n_total**2)\n      end\n      def proportion_sd_esd_wor(es)\n          Math::sqrt(proportion_variance_ksd_wor(es))\n      end\n    end\n    \n    def initialize(ms,strata_sizes)\n      raise TypeError,\"ms should be a Multiset\" unless ms.is_a? Statsample::Multiset\n      @ms=ms\n      raise ArgumentError,\"You should put a strata size for each dataset\" if strata_sizes.keys.sort!=ms.datasets_names\n      @strata_sizes=strata_sizes\n      @population_size=@strata_sizes.inject(0) {|a,x| a+x[1]}\n      @strata_number=@ms.n_datasets\n      @sample_size=@ms.datasets.inject(0) {|a,x| a+x[1].cases}\n    end\n    # Number of strata\n    def strata_number\n      @strata_number\n    end\n    # Population size. Equal to sum of strata sizes\n    # Symbol: N<sub>h</sub>\n    def population_size\n      @population_size\n    end\n    # Sample size. Equal to sum of sample of each stratum\n    def sample_size\n      @sample_size\n    end\n    # Size of stratum x\n    def stratum_size(h)\n      @strata_sizes[h]\n    end\n    def vectors_by_field(field)\n      @ms.datasets.collect{|k,ds|\n        ds[field]\n      }\n    end\n    # Population proportion based on strata\n    def proportion(field, v=1)\n      @ms.sum_field(field) {|s_name,vector|\n      stratum_ponderation(s_name)*vector.proportion(v)\n      }\n    end\n    # Stratum ponderation.\n    # Symbol: W\\<sub>h\\</sub>\n    def stratum_ponderation(h)\n      @strata_sizes[h].to_f / @population_size\n    end\n    alias_method :wh, :stratum_ponderation\n    \n    # Population mean based on strata\n    def mean(field)\n      @ms.sum_field(field) {|s_name,vector|\n      stratum_ponderation(s_name)*vector.mean\n      }\n    end\n    # Standard error with estimated population variance and without replacement.\n    # Source: Cochran (1972)\n    def standard_error_wor(field)\n      es=@ms.collect_vector(field) {|s_n, vector|\n        {'N'=>@strata_sizes[s_n],'n'=>vector.size, 's'=>vector.sds}\n      }\n      \n      StratifiedSample.standard_error_esd_wor(es)\n    end\n    \n    # Standard error with estimated population variance and without replacement.\n    # Source: http://stattrek.com/Lesson6/STRAnalysis.aspx\n    \n    def standard_error_wor_2(field)\n      sum=@ms.sum_field(field) {|s_name,vector|\n        s_size=@strata_sizes[s_name]\n      (s_size**2 * (1-(vector.size.to_f / s_size)) * vector.variance_sample / vector.size.to_f)\n      }\n      (1/@population_size.to_f)*Math::sqrt(sum)\n    end\n    \n    def standard_error_wr(field)\n      es=@ms.collect_vector(field) {|s_n, vector|\n        {'N'=>@strata_sizes[s_n],'n'=>vector.size, 's'=>vector.sds}\n      }\n      \n      StratifiedSample.standard_error_esd_wr(es)\n    end\n    def proportion_sd_esd_wor(field,v=1)\n      es=@ms.collect_vector(field) {|s_n, vector|\n        {'N'=>@strata_sizes[s_n],'n'=>vector.size, 'p'=>vector.proportion(v)}\n      }\n      \n      StratifiedSample.proportion_sd_esd_wor(es)\n    end\n    \n    def proportion_standard_error(field,v=1)\n      prop=proportion(field,v)\n      sum=@ms.sum_field(field) {|s_name,vector|\n        nh=vector.size\n        s_size=@strata_sizes[s_name]\n        (s_size**2 * (1-(nh / s_size)) * prop * (1-prop) / (nh - 1 ))\n      }\n      (1.quo(@population_size)) * Math::sqrt(sum)\n    end\n    # Cochran(1971), p. 150 \n    def variance_pst(field,v=1)\n      sum=@ms.datasets.inject(0) {|a,da|\n        stratum_name=da[0]\n        ds=da[1]\n        nh=ds.cases.to_f\n        s_size=@strata_sizes[stratum_name]\n        prop=ds[field].proportion(v)\n        a + (((s_size**2 * (s_size-nh)) / (s_size-1))*(prop*(1-prop) / (nh-1)))\n      }\n      (1/@population_size.to_f ** 2)*sum\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/regression/multiple/alglibengine.rb",
    "content": "if HAS_ALGIB\nmodule Statsample\nmodule Regression\nmodule Multiple\n# Class for Multiple Regression Analysis\n# Requires Alglib gem and uses a listwise aproach.\n# Faster than GslEngine on massive prediction use, because process is c-based.\n# Prefer GslEngine if you need good memory use.\n# If you need pairwise, use RubyEngine\n# Example:\n#\n#   @a=[1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n#   @b=[3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n#   @c=[11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n#   @y=[3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n#   ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n#   lr=Statsample::Regression::Multiple::AlglibEngine.new(ds,'y')\n#            \nclass AlglibEngine < BaseEngine\n  def initialize(ds,y_var, opts=Hash.new)\n    super    \n    @ds=ds.dup_only_valid\n    @ds_valid=@ds\n    @dy=@ds[@y_var]\n    @ds_indep=ds.dup(ds.fields-[y_var])\n    # Create a custom matrix\n    columns=[]\n    @fields=[]\n    @ds.fields.each{|f|\n        if f!=@y_var\n            columns.push(@ds[f].to_a)\n            @fields.push(f)\n        end\n    }\n    @dep_columns=columns.dup\n    columns.push(@ds[@y_var])\n    matrix=Matrix.columns(columns)\n    @lr_s=nil\n    @lr=::Alglib::LinearRegression.build_from_matrix(matrix)\n    @coeffs=assign_names(@lr.coeffs)\n    \n  end\n    \n    def _dump(i)\n        Marshal.dump({'ds'=>@ds,'y_var'=>@y_var})\n    end\n    def self._load(data)\n        h=Marshal.load(data)\n        self.new(h['ds'], h['y_var'])\n    end\n    \n    def coeffs\n        @coeffs\n    end\n    # Coefficients using a constant\n    # Based on http://www.xycoon.com/ols1.htm\n    def matrix_resolution\n        mse_p=mse\n        columns=@dep_columns.dup.map {|xi| xi.map{|i| i.to_f}}\n        columns.unshift([1.0]*@ds.cases)\n        y=Matrix.columns([@dy.data.map  {|i| i.to_f}])\n        x=Matrix.columns(columns)\n        xt=x.t\n        matrix=((xt*x)).inverse*xt\n        matrix*y\n    end\n    def r2\n        r**2\n    end\n    def r\n        Bivariate::pearson(@dy,predicted)\n    end  \n    def sst\n        @dy.ss\n    end\n    def constant\n        @lr.constant\n    end\n    def standarized_coeffs\n        l=lr_s\n        assign_names(l.coeffs)\n    end\n    def lr_s\n        if @lr_s.nil?\n            build_standarized\n        end\n        @lr_s\n    end\n    def build_standarized\n        @ds_s=@ds.standarize\n        columns=[]\n        @ds_s.fields.each{|f|\n            columns.push(@ds_s[f].to_a) unless f==@y_var\n        }\n        @dep_columns_s=columns.dup\n        columns.push(@ds_s[@y_var])\n        matrix=Matrix.columns(columns)\n        @lr_s=Alglib::LinearRegression.build_from_matrix(matrix)\n    end\n    def process(v)\n        @lr.process(v)\n    end\n    def process_s(v)\n        lr_s.process(v)\n    end\n    # ???? Not equal to SPSS output\n    def standarized_residuals\n        res=residuals\n        red_sd=residuals.sds\n        res.collect {|v|\n            v.quo(red_sd)\n        }.to_vector(:scale)\n    end\nend\nend\nend\nend # for Statsample\nend # for if\n\n        \n\n"
  },
  {
    "path": "lib/statsample/regression/multiple/baseengine.rb",
    "content": "module Statsample\n  module Regression\n    module Multiple\n      # Base class for Multiple Regression Engines\n      class BaseEngine\n        include Statsample::Summarizable\n        # Name of analysis\n        attr_accessor :name\n        # Minimum number of  valid case for pairs of correlation\n        attr_reader :cases\n        # Number of valid cases (listwise)\n        attr_reader :valid_cases\n        # Number of total cases (dataset.cases)\n        attr_reader :total_cases\n        \n        attr_accessor :digits\n        def self.univariate?\n          true\n        end\n        def initialize(ds, y_var, opts = Hash.new)\n          @ds=ds\n          @predictors_n=@ds.fields.size-1\n          @total_cases=@ds.cases\n          @cases=@ds.cases\n          @y_var=y_var\n          @r2=nil\n          @name=_(\"Multiple Regression:  %s over %s\") % [ ds.fields.join(\",\") , @y_var]\n          \n          \n          opts_default={:digits=>3}\n          @opts=opts_default.merge opts\n          \n          @opts.each{|k,v|\n            self.send(\"#{k}=\",v) if self.respond_to? k\n          }\n          \n        end\n        # Calculate F Test\n        def anova\n          @anova||=Statsample::Anova::OneWay.new(:ss_num=>ssr, :ss_den=>sse, :df_num=>df_r, :df_den=>df_e, :name_numerator=>_(\"Regression\"), :name_denominator=>_(\"Error\"), :name=>\"ANOVA\")\n        end\n        # Standard error of estimate\n        def se_estimate\n          Math::sqrt(sse.quo(df_e))\n        end\n        # Retrieves a vector with predicted values for y\n        def predicted\n          @total_cases.times.collect { |i|\n            invalid=false\n            vect=@dep_columns.collect {|v| invalid=true if v[i].nil?; v[i]}\n            if invalid\n              nil\n            else\n              process(vect)\n            end\n          }.to_vector(:scale)\n        end\n        # Retrieves a vector with standarized values for y\n        def standarized_predicted\n          predicted.standarized\n        end\n        # Retrieves a vector with residuals values for y\n        def residuals\n          (0...@total_cases).collect{|i|\n            invalid=false\n            vect=@dep_columns.collect{|v| invalid=true if v[i].nil?; v[i]}\n            if invalid or @ds[@y_var][i].nil?\n              nil\n            else\n              @ds[@y_var][i] - process(vect)\n            end\n          }.to_vector(:scale)\n        end\n        # R Multiple\n        def r\n          raise \"You should implement this\"\n        end\n        # Sum of squares Total\n        def sst\n          raise \"You should implement this\"\n        end\n        # R^2 Adjusted.\n        # Estimate Population R^2 usign Ezequiel formula.\n        # Always lower than sample R^2\n        # == Reference:\n        # * Leach, L. & Henson, R. (2007). The Use and Impact of Adjusted R2 Effects in Published Regression Research. Multiple Linear Regression Viewpoints, 33(1), 1-11.\n        def r2_adjusted\n          r2-((1-r2)*@predictors_n).quo(df_e)\n        end\n        # Sum of squares (regression)\n        def ssr\n          r2*sst\n        end\n        # Sum of squares (Error)\n        def sse\n          sst - ssr\n        end\n        # T values for coeffs\n        def coeffs_t\n          out={}\n          se=coeffs_se\n          coeffs.each do |k,v|\n            out[k]=v / se[k]\n          end\n          out\n        end\n        # Mean square Regression\n        def msr\n          ssr.quo(df_r)\n        end\n        # Mean Square Error\n        def mse\n          sse.quo(df_e)\n        end\n        # Degrees of freedom for regression\n        def df_r\n          @predictors_n\n        end\n        # Degrees of freedom for error\n        def df_e\n          @valid_cases-@predictors_n-1\n        end\n        # Fisher for Anova\n        def f\n          anova.f\n        end\n        # p-value of Fisher\n        def probability\n          anova.probability\n        end\n        # Tolerance for a given variable\n        # http://talkstats.com/showthread.php?t=5056\n        def tolerance(var)\n          ds=assign_names(@dep_columns)\n          ds.each{|k,v|\n          ds[k]=v.to_vector(:scale)\n          }\n          lr=self.class.new(ds.to_dataset,var)\n          1-lr.r2\n        end\n        # Tolerances for each coefficient\n        def coeffs_tolerances\n          @fields.inject({}) {|a,f|\n          a[f]=tolerance(f);\n            a\n          }\n        end\n        # Standard Error for coefficients\n        def coeffs_se\n          out={}\n          mse=sse.quo(df_e)\n          coeffs.each {|k,v|\n            out[k]=Math::sqrt(mse/(@ds[k].sum_of_squares * tolerance(k)))\n          }\n          out\n        end\n        # Estandar error of R^2\n        # ????\n        def se_r2\n          Math::sqrt((4*r2*(1-r2)**2*(df_e)**2).quo((@cases**2-1)*(@cases+3)))\n        end\n         \n        # Estimated Variance-Covariance Matrix\n        # Used for calculation of se of constant\n        def estimated_variance_covariance_matrix\n          #mse_p=mse\n          columns=[]\n          @ds_valid.fields.each{|k|\n            v=@ds_valid[k]\n            columns.push(v.data) unless k==@y_var\n          }\n          columns.unshift([1.0]*@valid_cases)\n          x=Matrix.columns(columns)\n          matrix=((x.t*x)).inverse * mse\n          matrix.collect {|i| Math::sqrt(i) if i>=0 }\n        end\n        # T for constant\n        def constant_t\n          constant.to_f/constant_se\n        end\n        # Standard error for constant\n        def constant_se\n          estimated_variance_covariance_matrix[0,0]\n        end\n        def report_building(b)\n          di=\"%0.#{digits}f\"\n          b.section(:name=>@name) do |g|\n            c=coeffs\n            g.text _(\"Engine: %s\") % self.class\n            g.text(_(\"Cases(listwise)=%d(%d)\") % [@total_cases, @valid_cases])\n            g.text _(\"R=\")+(di % r)\n            g.text _(\"R^2=\")+(di % r2)\n            g.text _(\"R^2 Adj=\")+(di % r2_adjusted)\n            g.text _(\"Std.Error R=\")+ (di % se_estimate)\n            \n            g.text(_(\"Equation\")+\"=\"+ sprintf(di,constant) +\" + \"+ @fields.collect {|k| sprintf(\"#{di}%s\",c[k],k)}.join(' + ') )\n            \n            g.parse_element(anova)\n            sc=standarized_coeffs\n            \n            cse=coeffs_se\n            g.table(:name=>_(\"Beta coefficients\"), :header=>%w{coeff b beta se t}.collect{|field| _(field)} ) do |t|\n\t\t\t\tt.row([_(\"Constant\"), sprintf(di, constant), \"-\", constant_se.nil? ? \"\": sprintf(di, constant_se), constant_t.nil? ? \"\" : sprintf(di, constant_t)])\n              @fields.each do |f|\n                t.row([f, sprintf(di, c[f]), sprintf(di, sc[f]), sprintf(di, cse[f]), sprintf(di, c[f].quo(cse[f]))])\n              end  \n            end\n          end\n        end\n        \n        \n        def assign_names(c)\n          a={}\n          @fields.each_index {|i|\n            a[@fields[i]]=c[i]\n          }\n          a\n        end\n\n        # Sum of squares of regression\n        # using the predicted value minus y mean\n        def ssr_direct\n          mean=@dy.mean\n          cases=0\n          ssr=(0...@ds.cases).inject(0) {|a,i|\n            invalid=false\n            v=@dep_columns.collect{|c| invalid=true if c[i].nil?; c[i]}\n            if !invalid\n              cases+=1\n              a+((process(v)-mean)**2)\n            else\n              a\n            end\n          }\n          ssr\n        end\n        def sse_direct\n          sst-ssr\n        end\n        def process(v)\n          c=coeffs\n          total=constant\n          @fields.each_index{|i|\n            total+=c[@fields[i]]*v[i]\n          }\n          total\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/statsample/regression/multiple/gslengine.rb",
    "content": "if Statsample.has_gsl?\n  module Statsample\n    module Regression\n      module Multiple\n        # Class for Multiple Regression Analysis\n        # Requires rbgsl and uses a listwise aproach.\n        # Slower on prediction of values than Alglib, because predict is ruby based.\n        # Better memory management on multiple (+1000) series of regression.\n        # If you need pairwise, use RubyEngine\n        # Example:\n        #\n        #   @a=[1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n        #   @b=[3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n        #   @c=[11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n        #   @y=[3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n        #   ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n        #   lr=Statsample::Regression::Multiple::GslEngine.new(ds,'y')\n        #\n        class GslEngine < BaseEngine\n          def initialize(ds,y_var, opts=Hash.new)\n            super\n            @ds=ds.dup_only_valid\n            @ds_valid=@ds\n            @valid_cases=@ds_valid.cases\n            @dy=@ds[@y_var]\n            @ds_indep=ds.dup(ds.fields-[y_var])\n            # Create a custom matrix\n            columns=[]\n            @fields=[]\n            max_deps = GSL::Matrix.alloc(@ds.cases, @ds.fields.size)\n            constant_col=@ds.fields.size-1\n            for i in 0...@ds.cases\n              max_deps.set(i,constant_col,1)\n            end\n            j=0\n            @ds.fields.each{|f|\n              if f!=@y_var\n                @ds[f].each_index{|i1|\n                  max_deps.set(i1,j,@ds[f][i1])\n                }\n                columns.push(@ds[f].to_a)\n                @fields.push(f)\n                j+=1\n              end\n            }\n            @dep_columns=columns.dup\n            @lr_s=nil\n            c, @cov, @chisq, @status = GSL::MultiFit.linear(max_deps, @dy.gsl)\n            @constant=c[constant_col]\n            @coeffs_a=c.to_a.slice(0...constant_col)\n            @coeffs=assign_names(@coeffs_a)\n            c=nil\n          end\n\n          def _dump(i)\n            Marshal.dump({'ds'=>@ds,'y_var'=>@y_var})\n          end\n          def self._load(data)\n            h=Marshal.load(data)\n            self.new(h['ds'], h['y_var'])\n          end\n\n          def coeffs\n            @coeffs\n          end\n          # Coefficients using a constant\n          # Based on http://www.xycoon.com/ols1.htm\n          def matrix_resolution\n            columns=@dep_columns.dup.map {|xi| xi.map{|i| i.to_f}}\n            columns.unshift([1.0]*@ds.cases)\n            y=Matrix.columns([@dy.data.map  {|i| i.to_f}])\n            x=Matrix.columns(columns)\n            xt=x.t\n            matrix=((xt*x)).inverse*xt\n            matrix*y\n          end\n          def r2\n            r**2\n          end\n          def r\n            Bivariate::pearson(@dy, predicted)\n          end\n          def sst\n            @dy.ss\n          end\n          def constant\n            @constant\n          end\n          def standarized_coeffs\n            l=lr_s\n            l.coeffs\n          end\n          def lr_s\n            if @lr_s.nil?\n              build_standarized\n            end\n            @lr_s\n          end\n          def build_standarized\n            @ds_s=@ds.standarize\n            @lr_s=GslEngine.new(@ds_s,@y_var)\n          end\n          def process_s(v)\n            lr_s.process(v)\n          end\n          # ???? Not equal to SPSS output\n          def standarized_residuals\n            res=residuals\n            red_sd=residuals.sds\n            res.collect {|v|\n              v.quo(red_sd)\n            }.to_vector(:scale)\n          end\n\n          # Standard error for coeffs\n          def coeffs_se\n            out={}\n            evcm=estimated_variance_covariance_matrix\n            @ds_valid.fields.each_with_index do |f,i|\n\n              mi=i+1\n              next if f==@y_var\n              out[f]=evcm[mi,mi]\n            end\n            out\n          end\n\n        end\n      end\n    end\n  end # for Statsample\nend # for if\n"
  },
  {
    "path": "lib/statsample/regression/multiple/matrixengine.rb",
    "content": "module Statsample\nmodule Regression\nmodule Multiple\n  # Pure Ruby Class for Multiple Regression Analysis, based on a covariance or correlation matrix.\n  #\n  # Use Statsample::Regression::Multiple::RubyEngine if you have a \n  # Dataset, to avoid setting all details.\n  # \n  # <b>Remember:</b> NEVER use a Covariance data if you have missing data. Use only correlation matrix on that case.\n  #\n  # \n  # Example:\n  #\n  #   matrix=[[1.0, 0.5, 0.2], [0.5, 1.0, 0.7], [0.2, 0.7, 1.0]]\n  #   \n  #   lr=Statsample::Regression::Multiple::MatrixEngine.new(matrix,2)\n\nclass MatrixEngine < BaseEngine \n  # Hash of standard deviation of predictors. \n  # Only useful for Correlation Matrix, because by default is set to 1\n  attr_accessor :x_sd\n  # Standard deviation of criterion\n  # Only useful for Correlation Matrix, because by default is set to 1\n  attr_accessor :y_sd\n  # Hash of mean for predictors. By default, set to 0\n  attr_accessor :x_mean\n  \n  # Mean for criteria. By default, set to 0\n  attr_accessor :y_mean\n  \n  # Number of cases\n  attr_writer :cases\n  attr_writer :digits\n  # Create object\n  #\n  def initialize(matrix,y_var, opts=Hash.new)\n    matrix.extend Statsample::CovariateMatrix\n    raise \"#{y_var} variable should be on data\" unless matrix.fields.include? y_var\n    if matrix._type==:covariance\n      @matrix_cov=matrix\n      @matrix_cor=matrix.correlation\n      @no_covariance=false\n    else\n      @matrix_cor=matrix\n      @matrix_cov=matrix\n      @no_covariance=true\n    end\n    \n    @y_var=y_var\n    @fields=matrix.fields-[y_var]\n    \n    @n_predictors=@fields.size\n    @predictors_n=@n_predictors\n    @matrix_x= @matrix_cor.submatrix(@fields)\n    @matrix_x_cov= @matrix_cov.submatrix(@fields)\n    raise LinearDependency, \"Regressors are linearly dependent\" if @matrix_x.determinant<1e-15\n\n    \n    @matrix_y = @matrix_cor.submatrix(@fields, [y_var])\n    @matrix_y_cov = @matrix_cov.submatrix(@fields, [y_var])\n    \n\n    \n    @y_sd=Math::sqrt(@matrix_cov.submatrix([y_var])[0,0])\n    \n    @x_sd=@n_predictors.times.inject({}) {|ac,i|\n      ac[@matrix_x_cov.fields[i]]=Math::sqrt(@matrix_x_cov[i,i])\n      ac;\n    }\n    \n    @cases=nil\n    @x_mean=@fields.inject({}) {|ac,f|\n      ac[f]=0.0\n      ac;\n    }\n    \n    @y_mean=0.0\n    @name=_(\"Multiple reggresion of %s on %s\") % [@fields.join(\",\"), @y_var]\n    \n    opts_default={:digits=>3}\n    opts=opts_default.merge opts\n    opts.each{|k,v|\n        self.send(\"#{k}=\",v) if self.respond_to? k\n    }\n      result_matrix=@matrix_x_cov.inverse * @matrix_y_cov\n\n    if matrix._type==:covariance\n      @coeffs=result_matrix.column(0).to_a\n      @coeffs_stan=coeffs.collect {|k,v|\n        coeffs[k]*@x_sd[k].quo(@y_sd)\n      }\n    else\n      @coeffs_stan=result_matrix.column(0).to_a\n      @coeffs=standarized_coeffs.collect {|k,v|\n        standarized_coeffs[k]*@y_sd.quo(@x_sd[k])\n      } \n    end\n    @total_cases=@valid_cases=@cases\n  end\n  def cases\n    raise \"You should define the number of valid cases first\" if @cases.nil?\n    @cases\n  end\n  # Get R^2 for the regression\n  # For fixed models is the coefficient of determination.\n  # On random models, is the 'squared-multiple correlation'\n  # Equal to \n  # * 1-(|R| / |R_x|) or\n  # * Sum(b_i*r_yi) <- used\n  def r2\n    @n_predictors.times.inject(0) {|ac,i| ac+@coeffs_stan[i]* @matrix_y[i,0]} \n  end\n  # Multiple correlation, on random models.\n  def r\n    Math::sqrt(r2)\n  end\n  # Value of constant\n  def constant\n    c=coeffs\n    @y_mean - @fields.inject(0){|a,k| a + (c[k] * @x_mean[k])}\n  end\n  # Hash of b or raw coefficients\n  def coeffs\n    assign_names(@coeffs)    \n  end\n  # Hash of beta or standarized coefficients\n\n  def standarized_coeffs\n    assign_names(@coeffs_stan)\n  end\n  # Total sum of squares\n  def sst\n    @y_sd**2*(cases-1.0)\n  end\n  \n  # Degrees of freedom for regression\n  def df_r\n    @n_predictors\n  end\n  # Degrees of freedom for error\n  def df_e\n    cases-@n_predictors-1\n  end\n  # Tolerance for a given variable\n  # defined as (1-R^2) of regression of other independent variables\n  # over the selected\n  # == Reference:\n  # * http://talkstats.com/showthread.php?t=5056\n  def tolerance(var)\n    return 1 if @matrix_x.column_size==1\n    lr=Statsample::Regression::Multiple::MatrixEngine.new(@matrix_x, var)\n    1-lr.r2\n  end\n  # Standard Error for coefficients.\n  # Standard error of a coefficients depends on\n  # * Tolerance of the coeffients: Higher tolerances implies higher error\n  # * Higher r2 implies lower error\n  # == Reference:\n  # * Cohen et al. (2003). Applied Multiple Reggression / Correlation Analysis for the Behavioral Sciences\n  #\n  def coeffs_se\n    out={}\n    #mse=sse.quo(df_e)\n    coeffs.each {|k,v|\n      out[k]=@y_sd.quo(@x_sd[k])*Math::sqrt( 1.quo(tolerance(k)))*Math::sqrt((1-r2).quo(df_e))\n    }\n    out\n  end\n  # t value for constant\n  def constant_t\n    return nil if constant_se.nil?\n    constant.to_f / constant_se\n  end\n  # Standard error for constant.\n  # This method recreates the estimaded variance-covariance matrix\n  # using means, standard deviation and covariance matrix.\n  # So, needs the covariance matrix.\n  def constant_se\n    return nil if @no_covariance\n    means=@x_mean\n    #means[@y_var]=@y_mean\n    means[:constant]=1\n    sd=@x_sd\n    #sd[@y_var]=@y_sd\n    sd[:constant]=0\n    fields=[:constant]+@matrix_cov.fields-[@y_var]\n    # Recreate X'X using the variance-covariance matrix\n    xt_x=Matrix.rows(fields.collect {|i|\n      fields.collect {|j|\n        if i==:constant or j==:constant\n          cov=0\n        elsif i==j\n          cov=sd[i]**2\n        else\n          cov=@matrix_cov.submatrix(i..i,j..j)[0,0]\n        end\n        cov*(@cases-1)+@cases*means[i]*means[j]\n      }\n    })\n    matrix=xt_x.inverse * mse\n    matrix.collect {|i| Math::sqrt(i) if i>0 }[0,0]\n  end\n  \nend\nend\nend\nend\n"
  },
  {
    "path": "lib/statsample/regression/multiple/rubyengine.rb",
    "content": "module Statsample\nmodule Regression\nmodule Multiple\n# Pure Ruby Class for Multiple Regression Analysis.\n# Slower than AlglibEngine, but is pure ruby and can use a pairwise aproach for missing values. \n# Coeffient calculation uses correlation matrix between the vectors\n# If you need listwise aproach for missing values, use AlglibEngine, because is faster.\n# \n# Example:\n#\n#   @a=[1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n#   @b=[3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n#   @c=[11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n#   @y=[3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n#   ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n#   lr=Statsample::Regression::Multiple::RubyEngine.new(ds,'y')\n\nclass RubyEngine < MatrixEngine\n  def initialize(ds,y_var, opts=Hash.new)\n    matrix=ds.correlation_matrix\n    fields_indep=ds.fields-[y_var]\n    default={\n      :y_mean=>ds[y_var].mean,\n      :x_mean=>fields_indep.inject({}) {|ac,f|  ac[f]=ds[f].mean; ac},\n      :y_sd=>ds[y_var].sd,\n      :x_sd=>fields_indep.inject({}) {|ac,f|  ac[f]=ds[f].sd; ac},\n      :cases=>Statsample::Bivariate.min_n_valid(ds)\n    }\n    opts=opts.merge(default)\n    super(matrix, y_var, opts)\n    @ds=ds\n    @dy=ds[@y_var]\n    @ds_valid=ds.dup_only_valid\n    @total_cases=@ds.cases\n    @valid_cases=@ds_valid.cases\n    @ds_indep = ds.dup(ds.fields-[y_var])\n    set_dep_columns\n  end\n  \n  def set_dep_columns\n    @dep_columns=[]\n    @ds_indep.each_vector{|k,v|\n      @dep_columns.push(v.data_with_nils)\n    }                \n  end\n\n  def fix_with_mean\n    i=0\n    @ds_indep.each do |row|\n      empty=[]\n      row.each do |k,v|\n        empty.push(k) if v.nil?\n      end\n      if empty.size==1\n        @ds_indep[empty[0]][i]=@ds[empty[0]].mean\n      end\n      i+=1\n    end\n    @ds_indep.update_valid_data\n    set_dep_columns\n  end\n  def fix_with_regression\n    i=0\n    @ds_indep.each{|row|\n      empty=[]\n      row.each{|k,v|\n          empty.push(k) if v.nil?\n      }\n      if empty.size==1\n        field=empty[0]\n        lr=MultipleRegression.new(@ds_indep,field)\n        fields=[]\n        @ds_indep.fields.each{|f|\n            fields.push(row[f]) unless f==field\n        }\n        @ds_indep[field][i]=lr.process(fields)\n      end\n      i+=1\n    }\n    @ds_indep.update_valid_data\n    set_dep_columns\n  end\n  # Standard error for constant\n  def constant_se\n    estimated_variance_covariance_matrix[0,0]\n  end\nend\nend\nend\nend\n"
  },
  {
    "path": "lib/statsample/regression/multiple.rb",
    "content": "require 'statsample/regression/multiple/baseengine'\nmodule Statsample\n  module Regression\n    # Module for OLS Multiple Regression Analysis.\n    # \n    #  Use:.\n    #\n    #  require 'statsample'\n    #  a=1000.times.collect {rand}.to_scale\n    #  b=1000.times.collect {rand}.to_scale\n    #  c=1000.times.collect {rand}.to_scale\n    #  ds={'a'=>a,'b'=>b,'c'=>c}.to_dataset\n    #  ds['y']=ds.collect{|row| row['a']*5+row['b']*3+row['c']*2+rand()}\n    #  lr=Statsample::Regression.multiple(ds,'y')\n    #  puts lr.summary\n    #  Summary for regression of a,b,c over y\n    #  *************************************************************\n    #  Engine: Statsample::Regression::Multiple::AlglibEngine\n    #  Cases(listwise)=1000(1000)\n    #  r=0.986\n    #  r2=0.973\n    #  Equation=0.504+5.011a + 2.995b + 1.988c\n    #  ----------------------------\n    #  ANOVA TABLE\n    #  --------------------------------------------------------------\n    #  |  source     | ss       | df  | ms      | f         | s     |\n    #  --------------------------------------------------------------\n    #  |  Regression | 2979.321 | 3   | 993.107 | 12040.067 | 0.000 |\n    #  |  Error      | 82.154   | 996 | 0.082   |           |       |\n    #  |  Total      | 3061.475 | 999 |         |           |       |\n    #  --------------------------------------------------------------\n    #  Beta coefficientes\n    #  -----------------------------------------------\n    #  |  coeff    | b     | beta  | se    | t       |\n    #  -----------------------------------------------\n    #  |  Constant | 0.504 | -     | 0.030 | 16.968  |\n    #  |  a        | 5.011 | 0.832 | 0.031 | 159.486 |\n    #  |  b        | 2.995 | 0.492 | 0.032 | 94.367  |\n    #  |  c        | 1.988 | 0.323 | 0.032 | 62.132  |\n    #  -----------------------------------------------\n    # \n    module Multiple\n      # Obtain r2 for regressors\n      def self.r2_from_matrices(rxx,rxy)\n        matrix=(rxy.transpose*rxx.inverse*rxy)\n        matrix[0,0]\n      end\n      \n      class MultipleDependent\n        def significance\n          0.0\n        end\n        def initialize(matrix,y_var, opts=Hash.new)\n          matrix.extend Statsample::CovariateMatrix\n          @matrix=matrix\n          @fields=matrix.fields-y_var\n          @y_var=y_var\n          @q=@y_var.size\n          @matrix_cor=matrix.correlation\n          @matrix_cor_xx = @matrix_cor.submatrix(@fields)\n          @matrix_cor_yy = @matrix_cor.submatrix(y_var, y_var)\n          \n          @sxx = @matrix.submatrix(@fields)\n          @syy = @matrix.submatrix(y_var, y_var)\n          @sxy = @matrix.submatrix(@fields, y_var)\n          @syx = @sxy.t\n        end\n        \n        def r2yx\n          1- (@matrix_cor.determinant.quo(@matrix_cor_yy.determinant * @matrix_cor_xx.determinant))\n        end\n        # Residual covariance of Y after accountin with lineal relation with x\n        def syyx\n          @syy-@syx*@sxx.inverse*@sxy\n        end\n        def r2yx_covariance\n          1-(syyx.determinant.quo(@syy.determinant))\n        end\n        \n        def vxy\n          @q-(@syy.inverse*syyx).trace\n        end\n        def p2yx\n          vxy.quo(@q)\n        end\n      end\n      \n      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/regression/simple.rb",
    "content": "module Statsample\n  module Regression\n    # Class for calculation of linear regressions with form\n    #   y = a+bx\n    # To create a Statsample::Regression::Simple object:\n    # * <tt> Statsample::Regression::Simple.new_from_dataset(ds,x,y)</tt>\n    # * <tt> Statsample::Regression::Simple.new_from_vectors(vx,vy)</tt>\n    # * <tt> Statsample::Regression::Simple.new_from_gsl(gsl) </tt>\n    #\n    class Simple\n      include Summarizable\n      attr_accessor :a,:b,:cov00, :cov01, :covx1, :chisq, :status\n      attr_accessor :name\n      attr_accessor :digits\n      def initialize(init_method, *argv)\n        self.send(init_method, *argv)\n      end\n      private_class_method :new\n      # Obtain y value given x value\n      # x=a+bx\n\n      def y(val_x)\n        @a+@b*val_x\n      end\n      # Obtain x value given y value\n      # x=(y-a)/b\n      def x(val_y)\n        (val_y-@a) / @b.to_f\n      end\n      # Sum of square error\n      def sse\n        (0...@vx.size).inject(0) {|acum,i| acum+((@vy[i]-y(@vx[i]))**2)\n        }\n      end\n      def standard_error\n        Math::sqrt(sse / (@vx.size-2).to_f)\n      end\n      # Sum of square regression\n      def ssr\n        vy_mean=@vy.mean\n        (0...@vx.size).inject(0) {|a,i|\n          a+((y(@vx[i])-vy_mean)**2)\n        }\n\n      end\n      # Sum of square total\n      def sst\n        @vy.sum_of_squared_deviation\n      end\n      # Value of r\n      def r\n        @b * (@vx.sds / @vy.sds)\n      end\n      # Value of r^2\n      def r2\n        r**2\n      end\n      class << self\n        # Create a regression object giving an array with following parameters:\n        # <tt>a,b,cov00, cov01, covx1, chisq, status</tt>\n        # Useful to obtain x and y values with a and b values.\n        def new_from_gsl(ar)\n          new(:init_gsl, *ar)\n        end\n        # Create a simple regression using two vectors\n        def new_from_vectors(vx,vy, opts=Hash.new)\n          new(:init_vectors,vx,vy, opts)\n        end\n        # Create a simple regression using a dataset and two vector names.\n        def new_from_dataset(ds,x,y, opts=Hash.new)\n          new(:init_vectors,ds[x],ds[y], opts)\n        end\n      end\n      def init_vectors(vx,vy, opts=Hash.new)\n        @vx,@vy=Statsample.only_valid_clone(vx,vy)\n        x_m=@vx.mean\n        y_m=@vy.mean\n        num=den=0\n        (0...@vx.size).each {|i|\n          num+=(@vx[i]-x_m)*(@vy[i]-y_m)\n          den+=(@vx[i]-x_m)**2\n        }\n        @b=num.to_f/den\n        @a=y_m - @b*x_m\n        \n        opts_default={\n        :digits=>3, \n        :name=>_(\"Regression of %s over %s\") % [@vx.name, @vy.name]\n         }\n        @opts=opts_default.merge opts\n\n        @opts.each{|k,v|\n          self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n        \n      end\n      def init_gsl(a,b,cov00, cov01, covx1, chisq, status)\n        @a=a\n        @b=b\n        @cov00=cov00\n        @cov01=cov01\n        @covx1=covx1\n        @chisq=chisq\n        @status=status\n      end\n      def report_building(gen)\n      f=\"%0.#{digits}f\"\n        gen.section(:name=>name) do |s|\n          s.table(:header=>[_(\"Variable\"), _(\"Value\")]) do |t|\n            t.row [_(\"r\"), f % r]\n            t.row [_(\"r^2\"), f % r2]\n            t.row [_(\"a\"), f % a]\n            t.row [_(\"b\"), f % b]\n            t.row [_(\"s.e\"), f % standard_error]\n          end\n        end\n      end\n      private :init_vectors, :init_gsl\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/regression.rb",
    "content": "require 'statsample/regression/simple'\nrequire 'statsample/regression/multiple'\n\nrequire 'statsample/regression/multiple/matrixengine'\nrequire 'statsample/regression/multiple/rubyengine'\nrequire 'statsample/regression/multiple/gslengine'\n\nmodule Statsample\n    # = Module for regression procedures.\n    # Use the method on this class to generate\n    # analysis.\n    # If you need more control, you can\n    # create and control directly the objects who computes\n    # the regressions.\n    # \n    # * Simple Regression :  Statsample::Regression::Simple\n    # * Multiple Regression: Statsample::Regression::Multiple\n    # * Logit Regression:    Statsample::Regression::Binomial::Logit\n    # * Probit Regression:    Statsample::Regression::Binomial::Probit\n    module Regression\n      \n      LinearDependency=Class.new(Exception)\n      \n      # Create a Statsample::Regression::Simple object, for simple regression\n      # * x: independent Vector\n      # * y: dependent Vector\n      # <b>Usage:</b>\n      #   x=100.times.collect {|i| rand(100)}.to_scale\n      #   y=100.times.collect {|i| 2+x[i]*2+rand()}.to_scale\n      #   sr=Statsample::Regression.simple(x,y)\n      #   sr.a\n      #   => 2.51763295177808\n      #   sr.b\n      #   => 1.99973746599856\n      #   sr.r\n      #   => 0.999987881153254\n      def self.simple(x,y)\n        Statsample::Regression::Simple.new_from_vectors(x,y)\n      end\n      \n      # Creates one of the Statsample::Regression::Multiple object,\n      # for OLS multiple regression.\n      # Parameters:\n      # * <tt>ds</tt>: Dataset.\n      # * y: Name of dependent variable.\n      # * opts: A hash with options\n      #   * missing_data: Could be\n      #     * :listwise: delete cases with one or more empty data (default).\n      #     * :pairwise: uses correlation matrix. Use with caution.\n      # \n      # <b>Usage:</b>\n      #   lr=Statsample::Regression::multiple(ds,'y')\n      def self.multiple(ds,y_var, opts=Hash.new)\n        missing_data= (opts[:missing_data].nil? ) ? :listwise : opts.delete(:missing_data)\n        if missing_data==:pairwise\n           Statsample::Regression::Multiple::RubyEngine.new(ds,y_var, opts)\n        else\n          if Statsample.has_gsl? and false\n            Statsample::Regression::Multiple::GslEngine.new(ds, y_var, opts)\n          else\n            ds2=ds.dup_only_valid\n            Statsample::Regression::Multiple::RubyEngine.new(ds2,y_var, opts)\n          end\n        end\n      end\n    end\nend\n"
  },
  {
    "path": "lib/statsample/reliability/icc.rb",
    "content": "module Statsample\n  module Reliability\n    # = Intra-class correlation\n    # According to Shrout & Fleiss (1979, p.422): \"ICC is the correlation \n    # between one measurement (either a single rating or a mean of \n    # several ratings) on a target and another measurement obtained on that target\"\n    # == Usage\n    #   require 'statsample'\n    #   size=1000\n    #   a = size.times.map {rand(10)}.to_scale\n    #   b = a.recode{|i|i+rand(4)-2}\n    #   c  =a.recode{|i|i+rand(4)-2}\n    #   d = a.recode{|i|i+rand(4)-2}\n    #   ds={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n    #   # Use :type attribute to set type to summarize\n    #   icc=Statsample::Reliability::ICC.new(ds, :type=>:icc_1_k)\n    #   puts icc.summary\n    # \n    # == Reference\n    # * Shrout,P. & Fleiss, J. (1979). Intraclass Correlation: Uses in assessing rater reliability. Psychological Bulletin, 86(2), 420-428\n    # * McGraw, K. & Wong, S.P. (1996). Forming Inferences About Some Intraclass Correlation Coefficients. Psychological methods, 1(1), 30-46.\n\n    class ICC\n      include Summarizable\n      \n      # Create a ICC analysis for a given dataset\n      # Each vector is a different measurement. Only uses complete data \n      # (listwise deletion).\n      #\n      \n      attr_reader :df_bt\n      attr_reader :df_wt\n      attr_reader :df_bj\n      attr_reader :df_residual\n\n      attr_reader :ms_bt\n      attr_reader :ms_wt\n      attr_reader :ms_bj\n      attr_reader :ms_residual\n\n      alias :bms :ms_bt\n      alias :wms :ms_wt\n      alias :jms :ms_bj\n      alias :ems :ms_residual\n      \n      alias :msr :ms_bt\n      alias :msw :ms_wt\n      alias :msc :ms_bj\n      alias :mse :ms_residual\n      \n      # :section: Shrout and Fleiss ICC denominations\n      attr_reader :icc_1_1\n      attr_reader :icc_2_1\n      attr_reader :icc_3_1\n      attr_reader :icc_1_k\n      attr_reader :icc_2_k\n      attr_reader :icc_3_k\n\n      # :section: McGraw and Wong ICC denominations\n      \n      attr_reader :icc_1\n      attr_reader :icc_c_1\n      attr_reader :icc_a_1\n      attr_reader :icc_k\n      attr_reader :icc_c_k\n      attr_reader :icc_a_k\n      \n      \n      attr_reader :n, :k\n      attr_reader :total_mean\n      # Type of analysis, for easy summarization\n      # By default, set to :icc_1\n      # * Shrout & Fleiss(1979) denominations\n      #   * :icc_1_1\n      #   * :icc_2_1\n      #   * :icc_3_1\n      #   * :icc_1_k\n      #   * :icc_2_k\n      #   * :icc_3_k\n      # * McGraw & Wong (1996) denominations\n      #   * :icc_1\n      #   * :icc_k\n      #   * :icc_c_1\n      #   * :icc_c_k\n      #   * :icc_a_1\n      #   * :icc_a_k\n\n      attr_reader :type\n      # ICC value, set with :type\n      attr_reader :r\n      attr_reader :f\n      attr_reader :lbound\n      attr_reader :ubound\n      \n      attr_accessor :g_rho\n      attr_accessor :alpha\n      attr_accessor :name\n      def initialize(ds, opts=Hash.new)\n        @ds=ds.dup_only_valid\n        @vectors=@ds.vectors.values\n        @n=@ds.cases\n        @k=@ds.fields.size\n        compute\n        @g_rho=0\n        @alpha=0.05\n        @icc_name=nil\n        opts_default={:name=>\"Intra-class correlation\", :type=>:icc_1}\n        @opts=opts_default.merge(opts)\n        @opts.each{|k,v| self.send(\"#{k}=\",v) if self.respond_to? k }\n      end\n      def type=(v)\n        case v\n          when :icc_1_1\n            @icc_name=_(\"Shrout & Fleiss ICC(1,1)\")\n            @r=@icc_1_1\n            @f=icc_1_f\n            @lbound, @ubound=icc_1_1_ci(@alpha)            \n          when :icc_2_1\n            @icc_name=_(\"Shrout & Fleiss ICC(2,1)\")\n            @r=@icc_2_1\n            @f=icc_2_f\n            @lbound, @ubound=icc_2_1_ci(@alpha)            \n            \n          when :icc_3_1\n            @icc_name=_(\"Shrout & Fleiss ICC(3,1)\")\n            \n            @r=@icc_3_1\n            @f=icc_3_f\n            @lbound, @ubound=icc_3_1_ci(@alpha)            \n\n          when :icc_1_k\n            @icc_name=_(\"Shrout & Fleiss ICC(1,k)\")\n            \n            @r=@icc_1_k\n            @f=icc_1_k_f\n            @lbound, @ubound=icc_1_k_ci(@alpha)            \n          when :icc_2_k\n            @icc_name=_(\"Shrout & Fleiss ICC(2,k)\")\n            \n            @r=@icc_2_k\n            @f=icc_2_k_f\n            @lbound, @ubound=icc_2_k_ci(@alpha)            \n            \n          when :icc_3_k\n            @icc_name=_(\"Shrout & Fleiss ICC(3,k)\")\n            \n            @r=@icc_3_k\n            @f=icc_3_k_f\n            @lbound, @ubound=icc_3_k_ci(@alpha)            \n            \n            \n          when :icc_1\n            @icc_name=_(\"McGraw & Wong ICC(1)\")\n            \n            @r=@icc_1_1\n            @f=icc_1_f(@g_rho)\n            @lbound, @ubound=icc_1_1_ci(@alpha)\n          when :icc_k\n            @icc_name=_(\"McGraw & Wong ICC(K)\")\n            \n            @r=@icc_1_k\n            @f=icc_1_k_f(@g_rho)\n            @lbound, @ubound=icc_1_k_ci(@alpha)\n          when :icc_c_1\n            @icc_name=_(\"McGraw & Wong ICC(C,1)\")\n            \n            @r=@icc_3_1\n            @f=icc_c_1_f(@g_rho)\n            @lbound, @ubound=icc_3_1_ci(@alpha)\n\n          when :icc_c_k\n            @icc_name=_(\"McGraw & Wong ICC(C,K)\")\n            \n            @r=@icc_3_k\n            @f=icc_c_k_f(@g_rho)\n            @lbound, @ubound=icc_c_k_ci(@alpha)\n\n          when :icc_a_1\n            @icc_name=_(\"McGraw & Wong ICC(A,1)\")\n            \n            @r=@icc_2_1\n            @f=icc_a_1_f(@g_rho)\n            @lbound,@ubound = icc_2_1_ci(@alpha)\n\n          when :icc_a_k\n            @icc_name=_(\"McGraw & Wong ICC(A,K)\")\n            \n            @r=@icc_2_k\n            @f=icc_a_k_f(@g_rho)\n            @lbound,@ubound=icc_2_k_ci(@alpha)\n\n          else\n            raise \"Type #{v} doesn't exists\" \n        end\n      end\n      def compute\n        @df_bt=n-1\n        @df_wt=n*(k-1)\n        @df_bj=k-1\n        @df_residual=(n-1)*(k-1)\n        @total_mean=@vectors.inject(0){|ac,v| ac+v.sum}.quo(n*k)\n        vm=@ds.vector_mean\n        \n        @ss_bt=k*vm.ss(@total_mean)\n        @ms_bt=@ss_bt.quo(@df_bt)\n        \n        @ss_bj=n*@vectors.inject(0){|ac,v| ac+(v.mean-@total_mean).square}\n        @ms_bj=@ss_bj.quo(@df_bj)\n        \n        @ss_wt=@vectors.inject(0){|ac,v| ac+(v-vm).ss(0)}\n        @ms_wt=@ss_wt.quo(@df_wt)\n        \n        @ss_residual=@ss_wt-@ss_bj\n        @ms_residual=@ss_residual.quo(@df_residual)\n        ###\n        # Shrout and Fleiss denomination\n        ###\n        # ICC(1,1) / ICC(1)\n        @icc_1_1=(bms-wms).quo(bms+(k-1)*wms) \n        # ICC(2,1) / ICC(A,1)\n        @icc_2_1=(bms-ems).quo(bms+(k-1)*ems+k*(jms - ems).quo(n))  \n        # ICC(3,1) / ICC(C,1)\n        @icc_3_1=(bms-ems).quo(bms+(k-1)*ems) \n        \n        \n        \n        # ICC(1,K) / ICC(K)\n        @icc_1_k=(bms-wms).quo(bms) \n        # ICC(2,K) / ICC(A,k)\n        @icc_2_k=(bms-ems).quo(bms+(jms-ems).quo(n))\n        # ICC(3,K) / ICC(C,k) = Cronbach's alpha\n        @icc_3_k=(bms-ems).quo(bms) \n        \n        ###\n        # McGraw and Wong\n        ###\n        \n      end\n      \n      def icc_1_f(rho=0.0)\n        num=msr*(1-rho)\n        den=msw*(1+(k-1)*rho)\n        Statsample::Test::F.new(num, den, @df_bt, @df_wt)\n      end\n      # One way random F, type k\n      def icc_1_k_f(rho=0)\n        num=msr*(1-rho)\n        den=msw\n        Statsample::Test::F.new(num, den, @df_bt, @df_wt)\n      end\n      \n      def icc_c_1_f(rho=0)\n        num=msr*(1-rho)\n        den=mse*(1+(k-1)*rho)\n        Statsample::Test::F.new(num, den, @df_bt, @df_residual)\n      end\n      def icc_c_k_f(rho=0)\n        num=(1-rho)\n        den=1-@icc_3_k\n        Statsample::Test::F.new(num, den, @df_bt, @df_residual)\n      end\n      \n      def v(a,b)\n        ((a*msc+b*mse)**2).quo(((a*msc)**2.quo(k-1))+((b*mse)**2.quo( (n-1) * (k-1))))\n      end\n      def a(rho)\n        (k*rho).quo(n*(1-rho))\n      end\n      def b(rho)\n        1+((k*rho*(n-1)).quo(n*(1-rho)))\n      end\n      def c(rho)\n        rho.quo(n*(1-rho))\n      end\n      def d(rho)\n        1+((rho*(n-1)).quo(n*(1-rho)))\n      end\n      private :v, :a, :b, :c, :d\n      def icc_a_1_f(rho=0)\n        fj=jms.quo(ems)\n        num=msr\n        den=a(rho)*msc+b(rho)*mse\n        pp = @icc_2_1\n        vn=(k-1)*(n-1)*((k*pp*fj+n*(1+(k-1)*pp)-k*pp)**2)\n        vd=(n-1)*(k**2)*(pp**2)*(fj**2)+((n*(1+(k-1)*pp)-k*pp)**2)\n        v=vn.quo(vd)\n        Statsample::Test::F.new(num, den, @df_bt, v)        \n      end\n      \n      def icc_a_k_f(rho=0)\n        num=msr\n        den=c(rho)*msc+d(rho)*mse\n        \n        fj=jms.quo(ems)\n        \n        pp = @icc_2_k\n        vn=(k-1)*(n-1)*((k*pp*fj+n*(1+(k-1)*pp)-k*pp)**2)\n        vd=(n-1)*(k**2)*(pp**2)*(fj**2)+((n*(1+(k-1)*pp)-k*pp)**2)\n        v=vn.quo(vd)\n        \n        \n        Statsample::Test::F.new(num, den, @df_bt,v)        \n\n      end\n      \n      # F test for ICC Case 1. Shrout and Fleiss\n      def icc_1_f_shrout\n        Statsample::Test::F.new(bms, wms, @df_bt, @df_wt)\n      end\n\n      # Intervale of confidence for ICC (1,1)\n      def icc_1_1_ci(alpha=0.05)\n        per=1-(0.5*alpha)\n       \n        fu=icc_1_f.f*Distribution::F.p_value(per, @df_wt, @df_bt)\n        fl=icc_1_f.f.quo(Distribution::F.p_value(per, @df_bt, @df_wt))\n        \n        [(fl-1).quo(fl+k-1), (fu-1).quo(fu+k-1)]\n      end\n      \n      # Intervale of confidence for ICC (1,k)\n      def icc_1_k_ci(alpha=0.05)\n        per=1-(0.5*alpha)\n        fu=icc_1_f.f*Distribution::F.p_value(per, @df_wt, @df_bt)\n        fl=icc_1_f.f.quo(Distribution::F.p_value(per, @df_bt, @df_wt))\n        [1-1.quo(fl), 1-1.quo(fu)]\n      end\n      \n      # F test for ICC Case 2\n      def icc_2_f\n        Statsample::Test::F.new(bms, ems, @df_bt, @df_residual)\n      end\n      \n      \n      #\n      # F* for ICC(2,1) and ICC(2,k)\n      # \n      def icc_2_1_fs(pp,alpha=0.05)\n        fj=jms.quo(ems)\n        per=1-(0.5*alpha)\n        vn=(k-1)*(n-1)*((k*pp*fj+n*(1+(k-1)*pp)-k*pp)**2)\n        vd=(n-1)*(k**2)*(pp**2)*(fj**2)+((n*(1+(k-1)*pp)-k*pp)**2)\n        v=vn.quo(vd)\n        f1=Distribution::F.p_value(per, n-1,v)\n        f2=Distribution::F.p_value(per, v, n-1)\n        [f1,f2]\n      end\n     \n      \n      def icc_2_1_ci(alpha=0.05)\n        icc_2_1_ci_mcgraw\n      end\n      \n      # Confidence interval ICC(A,1), McGawn\n      \n      def icc_2_1_ci_mcgraw(alpha=0.05)\n        fd,fu=icc_2_1_fs(icc_2_1,alpha)\n        cl=(n*(msr-fd*mse)).quo(fd*(k*msc+(k*n-k-n)*mse)+n*msr)\n        cu=(n*(fu*msr-mse)).quo(k*msc+(k*n-k-n)*mse+n*fu*msr)\n        [cl,cu]\n      end\n      \n      def icc_2_k_ci(alpha=0.05)\n        icc_2_k_ci_mcgraw(alpha)\n      end\n      \n      def icc_2_k_ci_mcgraw(alpha=0.05)\n        f1,f2=icc_2_1_fs(icc_2_k,alpha)\n        [\n        (n*(msr-f1*mse)).quo(f1*(msc-mse)+n*msr),\n        (n*(f2*msr-mse)).quo(msc-mse+n*f2*msr)\n        ]\n        \n      end\n      def icc_2_k_ci_shrout(alpha=0.05)\n        ci=icc_2_1_ci(alpha)\n        [(ci[0]*k).quo(1+(k-1)*ci[0]), (ci[1]*k).quo(1+(k-1)*ci[1])]\n      end\n      \n      \n      def icc_3_f\n        Statsample::Test::F.new(bms, ems, @df_bt, @df_residual)\n      end\n      \n      def icc_3_1_ci(alpha=0.05)\n        per=1-(0.5*alpha)\n        fl=icc_3_f.f.quo(Distribution::F.p_value(per, @df_bt, @df_residual))\n        fu=icc_3_f.f*Distribution::F.p_value(per, @df_residual, @df_bt)\n        [(fl-1).quo(fl+k-1), (fu-1).quo(fu+k-1)]\n      end\n      \n      def icc_3_k_ci(alpha=0.05)\n        per=1-(0.5*alpha)\n        fl=icc_3_f.f.quo(Distribution::F.p_value(per, @df_bt, @df_residual))\n        fu=icc_3_f.f*Distribution::F.p_value(per, @df_residual, @df_bt)\n        [1-1.quo(fl),1-1.quo(fu)]\n      end\n      \n      def icc_c_k_ci(alpha=0.05)\n        per=1-(0.5*alpha)\n        fl=icc_c_k_f.f.quo(Distribution::F.p_value(per, @df_bt, @df_residual))\n        fu=icc_c_k_f.f*Distribution::F.p_value(per, @df_residual, @df_bt)\n        [1-1.quo(fl),1-1.quo(fu)]\n      end\n      def report_building(b)\n         b.section(:name=>name) do |s|\n           s.text @icc_name\n           s.text _(\"ICC: %0.4f\") % @r\n           s.parse_element(@f)\n           s.text _(\"CI (%0.2f): [%0.4f - %0.4f]\") % [(1-@alpha)*100, @lbound, @ubound]\n         end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/reliability/multiscaleanalysis.rb",
    "content": "module Statsample\n  module Reliability\n    # DSL for analysis of multiple scales analysis. \n    # Retrieves reliability analysis for each scale and\n    # provides fast accessors to correlations matrix,\n    # PCA and Factor Analysis.\n    # \n    # == Usage\n    #  @x1=[1,1,1,1,2,2,2,2,3,3,3,30].to_vector(:scale)\n    #  @x2=[1,1,1,2,2,3,3,3,3,4,4,50].to_vector(:scale)\n    #  @x3=[2,2,1,1,1,2,2,2,3,4,5,40].to_vector(:scale)\n    #  @x4=[1,2,3,4,4,4,4,3,4,4,5,30].to_vector(:scale)\n    #  ds={'x1'=>@x1,'x2'=>@x2,'x3'=>@x3,'x4'=>@x4}.to_dataset\n    #  opts={:name=>\"Scales\", # Name of analysis\n    #        :summary_correlation_matrix=>true, # Add correlation matrix\n    #        :summary_pca } # Add PCA between scales\n    #  msa=Statsample::Reliability::MultiScaleAnalysis.new(opts) do |m|\n    #    m.scale :s1, ds.clone(%w{x1 x2})\n    #    m.scale :s2, ds.clone(%w{x3 x4}), {:name=>\"Scale 2\"}\n    #  end\n    #  # Retrieve summary\n    #  puts msa.summary \n    class MultiScaleAnalysis\n      include Statsample::Summarizable\n      # Hash with scales\n      attr_reader :scales\n      # Name of analysis\n      attr_accessor :name\n      # Add a correlation matrix on summary\n      attr_accessor :summary_correlation_matrix\n      # Add PCA to summary\n      attr_accessor :summary_pca\n      # Add Principal Axis to summary\n      attr_accessor :summary_principal_axis\n      # Options for Factor::PCA object\n      attr_accessor :pca_options\n      # Options for Factor::PrincipalAxis \n      attr_accessor :principal_axis_options\n      \n      # Add Parallel Analysis to summary\n      attr_accessor :summary_parallel_analysis\n      # Options for Parallel Analysis\n      attr_accessor :parallel_analysis_options\n      \n      # Add MPA to summary\n      attr_accessor :summary_map\n      # Options for MAP\n      attr_accessor :map_options\n      \n      \n      # Generates a new MultiScaleAnalysis\n      # Opts could be any accessor of the class \n      # * :name, \n      # * :summary_correlation_matrix\n      # * :summary_pca\n      # * :summary_principal_axis\n      # * :summary_map\n      # * :pca_options\n      # * :factor_analysis_options\n      # * :map_options\n      # If block given, all methods should be called\n      # inside object environment.\n      # \n      def initialize(opts=Hash.new, &block)\n        @scales=Hash.new\n        @scales_keys=Array.new\n        opts_default={  :name=>_(\"Multiple Scale analysis\"),\n                        :summary_correlation_matrix=>false,\n                        :summary_pca=>false,\n                        :summary_principal_axis=>false,\n                        :summary_parallel_analysis=>false,\n                        :summary_map=>false,\n                        :pca_options=>Hash.new,\n                        :principal_axis_options=>Hash.new,\n                        :parallel_analysis_options=>Hash.new,\n                        :map_options=>Hash.new\n        }\n        @opts=opts_default.merge(opts)\n        @opts.each{|k,v|\n          self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n\n        if block\n          block.arity<1 ? instance_eval(&block) : block.call(self)\n        end\n      end\n      # Add or retrieve a scale to analysis.\n      # If second parameters is a dataset, generates a ScaleAnalysis \n      # for <tt>ds</tt>, named <tt>code</tt> with options <tt>opts</tt>.\n      # \n      # If second parameters is empty, returns the ScaleAnalysis\n      # <tt>code</tt>.\n      def scale(code, ds=nil, opts=nil)\n        if ds.nil?\n          @scales[code]\n        else\n          opts={:name=>_(\"Scale %s\") % code} if opts.nil?\n          @scales_keys.push(code)\n          @scales[code]=ScaleAnalysis.new(ds, opts)\n        end\n      end\n      # Delete ScaleAnalysis named <tt>code</tt>\n      def delete_scale(code)\n        @scales_keys.delete code\n        @scales.delete code\n      end\n      # Retrieves a Principal Component Analysis (Factor::PCA)\n      # using all scales, using <tt>opts</tt> a options.\n      def pca(opts=nil)\n        opts||=pca_options        \n        Statsample::Factor::PCA.new(correlation_matrix, opts)\n      end\n      # Retrieve Velicer's MAP\n      # using all scales.\n      def map(opts=nil)\n        opts||=map_options\n        Statsample::Factor::MAP.new(correlation_matrix, opts)\n      end\n      # Retrieves a PrincipalAxis Analysis (Factor::PrincipalAxis)\n      # using all scales, using <tt>opts</tt> a options.\n      def principal_axis_analysis(opts=nil)\n        opts||=principal_axis_options\n        Statsample::Factor::PrincipalAxis.new(correlation_matrix, opts)\n      end\n      def dataset_from_scales\n        ds=Dataset.new(@scales_keys)\n        @scales.each_pair do |code,scale|\n          ds[code.to_s]=scale.ds.vector_sum\n          ds[code.to_s].name=scale.name\n        end\n        ds.update_valid_data\n        ds\n      end\n      def parallel_analysis(opts=nil)\n        opts||=parallel_analysis_options\n        Statsample::Factor::ParallelAnalysis.new(dataset_from_scales, opts)\n      end\n      # Retrieves a Correlation Matrix between scales.\n      # \n      def correlation_matrix\n        Statsample::Bivariate.correlation_matrix(dataset_from_scales)\n      end\n      def report_building(b) # :nodoc:\n        b.section(:name=>name) do |s|\n          s.section(:name=>_(\"Reliability analysis of scales\")) do |s2|\n            @scales.each_pair do |k, scale|\n              s2.parse_element(scale)\n            end\n          end\n          if summary_correlation_matrix\n            s.section(:name=>_(\"Correlation matrix for %s\") % name) do |s2|\n              s2.parse_element(correlation_matrix)\n            end\n          end\n          if summary_pca\n            s.section(:name=>_(\"PCA for %s\") % name) do |s2|\n              s2.parse_element(pca)\n            end\n          end\n          if summary_principal_axis\n            s.section(:name=>_(\"Principal Axis for %s\") % name) do |s2|\n              s2.parse_element(principal_axis_analysis)\n            end\n          end\n          \n          if summary_parallel_analysis\n            s.section(:name=>_(\"Parallel Analysis for %s\") % name) do |s2|\n              s2.parse_element(parallel_analysis)\n            end\n          end \n          if summary_map\n            s.section(:name=>_(\"MAP for %s\") % name) do |s2|\n              s2.parse_element(map)\n            end\n          end           \n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/statsample/reliability/scaleanalysis.rb",
    "content": "module Statsample\n  module Reliability\n    # Analysis of a Scale. Analoge of Scale Reliability analysis on SPSS.\n    # Returns several statistics for complete scale and each item\n    # == Usage\n    #  @x1=[1,1,1,1,2,2,2,2,3,3,3,30].to_vector(:scale)\n    #  @x2=[1,1,1,2,2,3,3,3,3,4,4,50].to_vector(:scale)\n    #  @x3=[2,2,1,1,1,2,2,2,3,4,5,40].to_vector(:scale)\n    #  @x4=[1,2,3,4,4,4,4,3,4,4,5,30].to_vector(:scale)\n    #  ds={'x1'=>@x1,'x2'=>@x2,'x3'=>@x3,'x4'=>@x4}.to_dataset\n    #  ia=Statsample::Reliability::ScaleAnalysis.new(ds)\n    #  puts ia.summary\n    class ScaleAnalysis\n      include Summarizable\n      attr_reader :ds,:mean, :sd,:valid_n, :alpha , :alpha_standarized, :variances_mean, :covariances_mean, :cov_m\n      attr_accessor :name\n      attr_accessor :summary_histogram\n      def initialize(ds, opts=Hash.new)\n        @dumped=ds.fields.find_all {|f|\n          ds[f].variance==0\n        }\n        \n        @ods=ds\n        @ds=ds.dup_only_valid(ds.fields - @dumped)\n        @ds.name=ds.name\n        \n        @k=@ds.fields.size        \n        @total=@ds.vector_sum\n        @o_total=@dumped.size > 0 ? @ods.vector_sum : nil\n        \n        @vector_mean=@ds.vector_mean\n        @item_mean=@vector_mean.mean\n        @item_sd=@vector_mean.sd\n        \n        @mean=@total.mean\n        @median=@total.median\n        \n        @skew=@total.skew\n        @kurtosis=@total.kurtosis\n        @sd = @total.sd\n        @variance=@total.variance\n        @valid_n = @total.size\n        opts_default={\n          :name=>_(\"Reliability Analysis\"),\n          :summary_histogram=>true\n        }\n        @opts=opts_default.merge(opts)\n        @opts.each{|k,v| self.send(\"#{k}=\",v) if self.respond_to? k }\n        \n        @cov_m=Statsample::Bivariate.covariance_matrix(@ds)\n        # Mean for covariances and variances\n        @variances=@k.times.map {|i| @cov_m[i,i]}.to_scale\n        @variances_mean=@variances.mean\n        @covariances_mean=(@variance-@variances.sum).quo(@k**2-@k)\n        #begin\n          @alpha = Statsample::Reliability.cronbach_alpha(@ds)\n          @alpha_standarized = Statsample::Reliability.cronbach_alpha_standarized(@ds)\n        #rescue => e\n        #  raise DatasetException.new(@ds,e), \"Error calculating alpha\"\n        #end\n      end\n      # Returns a hash with structure\n      def item_characteristic_curve\n        i=0\n        out={}\n        total={}\n        @ds.each do |row|\n          tot=@total[i]\n          @ds.fields.each do |f|\n            out[f]||= {}\n            total[f]||={}\n            out[f][tot]||= 0\n            total[f][tot]||=0\n            out[f][tot]+= row[f]\n            total[f][tot]+=1\n          end\n          i+=1\n        end\n        total.each do |f,var|\n          var.each do |tot,v|\n            out[f][tot]=out[f][tot].quo(total[f][tot])\n          end\n        end\n        out\n      end\n      # =Adjusted R.P.B. for each item\n      # Adjusted RPB(Point biserial-correlation) for each item\n      #\n      def item_total_correlation\n        @itc||=@ds.fields.inject({}) do |a,v|\n          vector=@ds[v].clone\n          ds2=@ds.clone\n          ds2.delete_vector(v)\n          total=ds2.vector_sum\n          a[v]=Statsample::Bivariate.pearson(vector,total)\n          a\n        end\n      end\n      def mean_rpb\n        item_total_correlation.values.to_scale.mean\n      end\n      def item_statistics\n          @is||=@ds.fields.inject({}) do |a,v|\n            a[v]={:mean=>@ds[v].mean, :sds=>Math::sqrt(@cov_m.variance(v))}\n            a\n          end\n      end\n      # Returns a dataset with cases ordered by score\n      # and variables ordered by difficulty\n\n      def item_difficulty_analysis\n        dif={}\n        @ds.fields.each{|f| dif[f]=@ds[f].mean }\n        dif_sort=dif.sort{|a,b| -(a[1]<=>b[1])}\n        scores_sort={}\n        scores=@ds.vector_mean\n        scores.each_index{|i| scores_sort[i]=scores[i] }\n        scores_sort=scores_sort.sort{|a,b| a[1]<=>b[1]}\n        ds_new=Statsample::Dataset.new(['case','score'] + dif_sort.collect{|a,b| a})\n        scores_sort.each do |i,score|\n          row=[i, score]\n          case_row=@ds.case_as_hash(i)\n          dif_sort.each{|variable,dif_value| row.push(case_row[variable]) }\n          ds_new.add_case_array(row)\n        end\n        ds_new.update_valid_data\n        ds_new\n      end\n      \n      def stats_if_deleted\n        @sif||=stats_if_deleted_intern\n      end\n      \n      def stats_if_deleted_intern # :nodoc:\n        return Hash.new if @ds.fields.size==1\n        @ds.fields.inject({}) do |a,v|\n          cov_2=@cov_m.submatrix(@ds.fields-[v])\n          #ds2=@ds.clone\n          #ds2.delete_vector(v)\n          #total=ds2.vector_sum\n          a[v]={}\n          #a[v][:mean]=total.mean\n          a[v][:mean]=@mean-item_statistics[v][:mean]\n          a[v][:variance_sample]=cov_2.total_sum\n          a[v][:sds]=Math::sqrt(a[v][:variance_sample])\n          n=cov_2.row_size\n          a[v][:alpha] = (n>=2) ? Statsample::Reliability.cronbach_alpha_from_covariance_matrix(cov_2) : nil\n          a\n        end\n      end\n      def report_building(builder) #:nodoc:\n        builder.section(:name=>@name) do |s|\n          \n          \n          if @dumped.size>0\n            s.section(:name=>\"Items with variance=0\") do |s1|\n              s.table(:name=>_(\"Summary for %s with all items\") % @name) do |t|\n                t.row [_(\"Items\"), @ods.fields.size]\n                t.row [_(\"Sum mean\"),     \"%0.4f\" % @o_total.mean]\n                t.row [_(\"S.d. mean\"),     \"%0.4f\" % @o_total.sd]\n              end\n              s.table(:name=>_(\"Deleted items\"), :header=>['item','mean']) do |t|\n                @dumped.each do |f|\n                  t.row([\"#{@ods[f].name}(#{f})\", \"%0.5f\" % @ods[f].mean])\n                end\n              end\n              s.parse_element(Statsample::Graph::Histogram.new(@o_total, :name=>\"Histogram (complete data) for %s\" % @name)) if @summary_histogram\n            end\n          end\n          \n          \n          s.table(:name=>_(\"Summary for %s\") % @name) do |t|\n            t.row [_(\"Valid Items\"), @ds.fields.size]\n          \n          t.row [_(\"Valid cases\"), @valid_n]\n          t.row [_(\"Sum mean\"),     \"%0.4f\" % @mean]\n          t.row [_(\"Sum sd\"),       \"%0.4f\" % @sd  ]\n#          t.row [_(\"Sum variance\"), \"%0.4f\" % @variance]\n          t.row [_(\"Sum median\"),   @median]\n          t.hr\n          t.row [_(\"Item mean\"),    \"%0.4f\" % @item_mean]\n          t.row [_(\"Item sd\"),    \"%0.4f\" % @item_sd]\n          t.hr\n          t.row [_(\"Skewness\"),     \"%0.4f\" % @skew]\n          t.row [_(\"Kurtosis\"),     \"%0.4f\" % @kurtosis]\n          t.hr\n          t.row [_(\"Cronbach's alpha\"), @alpha ? (\"%0.4f\" % @alpha) : \"--\"]\n          t.row [_(\"Standarized Cronbach's alpha\"), @alpha_standarized ? (\"%0.4f\" % @alpha_standarized) : \"--\" ]\n          t.row [_(\"Mean rpb\"), \"%0.4f\" % mean_rpb]\n          \n          t.row [_(\"Variances mean\"),  \"%g\" % @variances_mean]\n          t.row [_(\"Covariances mean\") , \"%g\" % @covariances_mean]\n          end\n          \n          if (@alpha)\n            s.text _(\"Items for obtain alpha(0.8) : %d\" % Statsample::Reliability::n_for_desired_reliability(@alpha, 0.8, @ds.fields.size))\n            s.text _(\"Items for obtain alpha(0.9) : %d\" % Statsample::Reliability::n_for_desired_reliability(@alpha, 0.9, @ds.fields.size))          \n          end\n          \n          \n          sid=stats_if_deleted\n          is=item_statistics\n          itc=item_total_correlation\n          \n          s.table(:name=>_(\"Items report for %s\") % @name, :header=>[\"item\",\"mean\",\"sd\", \"mean if deleted\", \"var if deleted\", \"sd if deleted\",\" item-total correl.\", \"alpha if deleted\"]) do |t|\n            @ds.fields.each do |f|\n              row=[\"#{@ds[f].name}(#{f})\"]\n              if is[f]\n                row+=[sprintf(\"%0.5f\",is[f][:mean]), sprintf(\"%0.5f\", is[f][:sds])]\n              else\n                row+=[\"-\",\"-\"]\n              end\n              if sid[f]\n                row+= [sprintf(\"%0.5f\",sid[f][:mean]), sprintf(\"%0.5f\",sid[f][:variance_sample]), sprintf(\"%0.5f\",sid[f][:sds])]\n              else\n                row+=%w{- - -}\n              end\n              if itc[f]\n                row+= [sprintf(\"%0.5f\",itc[f])]\n              else \n                row+=['-']\n              end\n              if sid[f] and !sid[f][:alpha].nil?\n                row+=[sprintf(\"%0.5f\",sid[f][:alpha])]\n              else\n                row+=[\"-\"]\n              end\n              t.row row\n            end # end each\n          end # table\n          s.parse_element(Statsample::Graph::Histogram.new(@total, :name=>\"Histogram (valid data) for %s\" % @name)) if @summary_histogram\n        end # section\n      end # def\n    end # class\n  end # module\nend # module\n"
  },
  {
    "path": "lib/statsample/reliability/skillscaleanalysis.rb",
    "content": "module Statsample\n  module Reliability\n    # Analysis of a Skill Scale\n    # Given a dataset with results and a correct answers hash,\n    # generates a ScaleAnalysis \n    # == Usage\n    #  x1=%{a b b c}.to_vector\n    #  x2=%{b a b c}.to_vector\n    #  x3=%{a c b a}.to_vector\n    #  ds={'x1'=>@x1,'x2'=>@x2,'x3'=>@x3}.to_dataset\n    #  key={'x1'=>'a','x2'=>'b','x3'=>'a'}    \n    #  ssa=Statsample::Reliability::SkillScaleAnalysis.new(ds,key)\n    #  puts ssa.summary\n    class SkillScaleAnalysis\n      include Summarizable\n      attr_accessor :name\n      attr_accessor :summary_minimal_item_correlation\n      attr_accessor :summary_show_problematic_items\n      def initialize(ds,key,opts=Hash.new)\n        opts_default={\n          :name=>_(\"Skill Scale Reliability Analysis (%s)\") % ds.name,\n          :summary_minimal_item_correlation=>0.10,\n          :summary_show_problematic_items=>true\n        }\n        @ds=ds\n        @key=key\n        @opts=opts_default.merge(opts)\n        @opts.each{|k,v| self.send(\"#{k}=\",v) if self.respond_to? k }\n        @cds=nil\n      end\n      # Dataset only corrected vectors\n      def corrected_dataset_minimal\n        cds=corrected_dataset\n        dsm=@key.keys.inject({}) {|ac,v| ac[v]=cds[v];ac}.to_dataset\n        @key.keys.each do |k|\n          dsm[k].name=_(\"%s(corrected)\") % @ds[k].name\n          dsm[k].labels=@ds[k].labels\n        end\n        \n        dsm.name=_(\"Corrected dataset from %s\") % @ds.name\n        dsm\n      end\n      def vector_sum\n        corrected_dataset_minimal.vector_sum\n      end\n      def vector_mean\n        corrected_dataset_minimal.vector_mean\n      end\n      def scale_analysis\n        sa=ScaleAnalysis.new(corrected_dataset_minimal)\n        sa.name=_(\"%s (Scale Analysis)\") % @name\n        sa\n      end\n      def corrected_dataset\n        if @cds.nil?\n          @cds=@ds.dup_empty\n          @key.keys.each {|k| @cds[k].type=:scale; @cds[k].name=@ds[k].name}\n          @ds.each do |row|\n            out={}\n            row.each do |k,v|\n              if @key.keys.include? k\n                if @ds[k].is_valid? v\n                  out[k]= @key[k]==v ? 1 : 0\n                else\n                  out[k]=nil\n                end\n              else\n                out[k]=v\n              end\n            end\n            @cds.add_case(out,false)\n          end\n          @cds.update_valid_data\n        end\n        @cds\n      end\n      def report_building(builder)\n        builder.section(:name=>@name) do |s|\n          sa=scale_analysis\n          s.parse_element(sa)\n          if summary_show_problematic_items\n            s.section(:name=>_(\"Problematic Items\")) do |spi|\n              count=0\n              sa.item_total_correlation.each do |k,v|\n                if v < summary_minimal_item_correlation\n                  count+=1\n                  spi.section(:name=>_(\"Item: %s\") % @ds[k].name) do |spii|\n                    spii.text _(\"Correct answer: %s\") % @key[k]\n                    spii.text _(\"p: %0.3f\") % corrected_dataset[k].mean\n                    props=@ds[k].proportions.inject({}) {|ac,v| ac[v[0]] = v[1].to_f;ac}\n                    \n                    spi.table(:name=>\"Proportions\",:header=>[_(\"Value\"), _(\"%\")]) do |table|\n                      props.each do |k1,v|\n                        table.row [ @ds[k].labeling(k1), \"%0.3f\" % v]\n                      end\n                    end\n                    \n                  end\n                end\n              end\n              spi.text _(\"No problematic items\") if count==0\n            end\n          end\n          \n        end\n      end\n    end    \n  end\nend\n"
  },
  {
    "path": "lib/statsample/reliability.rb",
    "content": "module Statsample\n  module Reliability\n    class << self\n      # Calculate Chonbach's alpha for a given dataset.\n      # only uses tuples without missing data\n      def cronbach_alpha(ods)\n        ds=ods.dup_only_valid\n        return nil if ds.vectors.any? {|k,v| v.variance==0}\n        n_items=ds.fields.size\n        return nil if n_items<=1\n        s2_items=ds.vectors.inject(0) {|ac,v|\n        ac+v[1].variance }\n        total=ds.vector_sum\n        \n        (n_items.quo(n_items-1)) * (1-(s2_items.quo(total.variance)))\n      end\n      # Calculate Chonbach's alpha for a given dataset\n      # using standarized values for every vector.\n      # Only uses tuples without missing data\n      # Return nil if one or more vectors has 0 variance\n      def cronbach_alpha_standarized(ods)\n        \n        ds=ods.dup_only_valid\n        \n        return nil if ds.vectors.any? {|k,v| v.variance==0}\n        \n        ds=ds.fields.inject({}){|a,f|\n          a[f]=ods[f].standarized; \n          a\n        }.to_dataset\n        \n        cronbach_alpha(ds)\n      end\n      # Predicted reliability of a test by replicating\n      # +n+ times the number of items \n      def spearman_brown_prophecy(r,n)\n        (n*r).quo(1+(n-1)*r)\n      end\n      \n      alias :sbp :spearman_brown_prophecy\n      # Returns the number of items \n      # to obtain +r_d+ desired reliability\n      # from +r+ current reliability, achieved with\n      # +n+ items\n      def n_for_desired_reliability(r,r_d,n=1)\n        return nil if r.nil?\n        (r_d*(1-r)).quo(r*(1-r_d))*n\n      end\n      \n      # Get Cronbach alpha from <tt>n</tt> cases, \n      # <tt>s2</tt> mean variance and <tt>cov</tt>\n      # mean covariance\n      def cronbach_alpha_from_n_s2_cov(n,s2,cov)\n        (n.quo(n-1)) * (1-(s2.quo(s2+(n-1)*cov)))\n      end\n      # Get Cronbach's alpha from a covariance matrix\n      def cronbach_alpha_from_covariance_matrix(cov)\n        n=cov.row_size\n        raise \"covariance matrix should have at least 2 variables\" if n < 2\n        s2=n.times.inject(0) {|ac,i| ac+cov[i,i]}\n        (n.quo(n-1))*(1-(s2.quo(cov.total_sum)))\n      end\n      # Returns n necessary to obtain specific alpha\n      # given variance and covariance mean of items\n      def n_for_desired_alpha(alpha,s2,cov)\n        # Start with a regular test : 50 items\n        min=2\n        max=1000\n        n=50\n        prev_n=0\n        epsilon=0.0001\n        dif=1000\n        c_a=cronbach_alpha_from_n_s2_cov(n,s2,cov)\n        dif=c_a - alpha\n        while(dif.abs>epsilon and n!=prev_n)\n          prev_n=n\n          if dif<0\n            min=n\n            n=(n+(max-min).quo(2)).to_i\n          else\n            max=n\n            n=(n-(max-min).quo(2)).to_i\n          end\n          c_a=cronbach_alpha_from_n_s2_cov(n,s2,cov)\n          dif=c_a - alpha\n          #puts \"#{n} , #{c_a}\"\n          \n        end\n        n\n      end\n      # First derivative for alfa\n      # Parameters\n      # <tt>n</tt>: Number of items\n      # <tt>sx</tt>: mean of variances \n      # <tt>sxy</tt>: mean of covariances\n      \n      def alpha_first_derivative(n,sx,sxy)\n        (sxy*(sx-sxy)).quo(((sxy*(n-1))+sx)**2)\n      end\n      # Second derivative for alfa\n      # Parameters\n      # <tt>n</tt>: Number of items\n      # <tt>sx</tt>: mean of variances \n      # <tt>sxy</tt>: mean of covariances\n      \n      def alfa_second_derivative(n,sx,sxy)\n        (2*(sxy**2)*(sxy-sx)).quo(((sxy*(n-1))+sx)**3)\n      end\n    end\n    class ItemCharacteristicCurve\n      attr_reader :totals, :counts, :vector_total\n      def initialize (ds, vector_total=nil)\n        vector_total||=ds.vector_sum\n        raise ArgumentError, \"Total size != Dataset size\" if vector_total.size!=ds.cases\n        @vector_total=vector_total\n        @ds=ds\n        @totals={}\n        @counts=@ds.fields.inject({}) {|a,v| a[v]={};a}\n        process\n      end\n      def process\n        i=0\n        @ds.each do |row|\n          tot=@vector_total[i]\n          @totals[tot]||=0\n          @totals[tot]+=1\n          @ds.fields.each  do |f|\n            item=row[f].to_s\n            @counts[f][tot]||={}\n            @counts[f][tot][item]||=0\n            @counts[f][tot][item] += 1\n          end\n          i+=1\n        end\n      end\n      # Return a hash with p for each different value on a vector\n      def curve_field(field, item)\n        out={}\n        item=item.to_s\n        @totals.each do |value,n|\n          count_value= @counts[field][value][item].nil? ? 0 : @counts[field][value][item]\n          out[value]=count_value.quo(n)\n        end\n        out\n      end # def\n    end # self\n  end # Reliability\nend # Statsample\n\nrequire 'statsample/reliability/icc.rb'\nrequire 'statsample/reliability/scaleanalysis.rb'\nrequire 'statsample/reliability/skillscaleanalysis.rb'\nrequire 'statsample/reliability/multiscaleanalysis.rb'"
  },
  {
    "path": "lib/statsample/resample.rb",
    "content": "module Statsample\n  module Resample\n    class << self\n      def repeat_and_save(times,&action)\n        (1..times).inject([]) {|a,x| a.push(action.call); a}\n      end\n      \n      def generate (size,low,upper)\n        range=upper-low+1\n        Vector.new((0...size).collect {|x| rand(range)+low },:scale)\n      end\n              \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/rserve_extension.rb",
    "content": "# Several additions to Statsample objects, to support\n# rserve-client\n\nmodule Statsample\n  class Vector\n    def to_REXP\n      Rserve::REXP::Wrapper.wrap(data_with_nils)\n    end\n  end\n  class Dataset\n    def to_REXP\n      names=@fields\n      data=@fields.map {|f|\n        Rserve::REXP::Wrapper.wrap(@vectors[f].data_with_nils)\n      }\n      l=Rserve::Rlist.new(data,names)\n      Rserve::REXP.create_data_frame(l)\n    end\n  end\nend"
  },
  {
    "path": "lib/statsample/shorthand.rb",
    "content": "class Object\n  # Shorthand for Statsample::Analysis.store(*args,&block)\n  def ss_analysis(*args,&block)\n    Statsample::Analysis.store(*args,&block)\n  end\nend\n\nmodule Statsample\n  # Module which provide shorthands for many methods.\n  module Shorthand\n    ###\n    # :section: R like methods\n    ###\n    def read_with_cache(klass, filename,opts=Hash.new, cache=true)\n      file_ds=filename+\".ds\"\n      if cache and (File.exists? file_ds and File.mtime(file_ds)>File.mtime(filename))\n        ds=Statsample.load(file_ds)\n      else\n        ds=klass.read(filename)\n        ds.save(file_ds) if cache\n      end\n      ds\n    end\n    # Import an Excel file. Cache result by default\n    def read_excel(filename, opts=Hash.new, cache=true)\n      read_with_cache(Statsample::Excel, filename, opts, cache)\n\n    end\n    # Import an CSV file. Cache result by default\n\n    def read_csv\n      read_with_cache(Statsample::CSV, filename, opts, cache)\n    end\n    \n    # Retrieve names (fields) from dataset\n    def names(ds)\n      ds.fields\n    end\n    # Create a correlation matrix from a dataset\n    def cor(ds)\n      Statsample::Bivariate.correlation_matrix(ds)\n    end\n    # Create a variance/covariance matrix from a dataset\n    def cov(ds)\n      Statsample::Bivariate.covariate_matrix(ds)\n    end\n    # Create a Statsample::Vector\n    # Analog to R's c\n    def vector(*args)\n      Statsample::Vector[*args]\n    end\n    # Random generation for the normal distribution\n    def rnorm(n,mean=0,sd=1)\n      rng=Distribution::Normal.rng(mean,sd)\n      Statsample::Vector.new_scale(n) { rng.call}\n    end\n    # Creates a new Statsample::Dataset\n    # Each key is transformed into string\n    def dataset(vectors=Hash.new)\n      vectors=vectors.inject({}) {|ac,v| ac[v[0].to_s]=v[1];ac}\n      Statsample::Dataset.new(vectors)\n    end\n    alias :data_frame :dataset\n    # Returns a Statsample::Graph::Boxplot\n    def boxplot(*args)\n      Statsample::Graph::Boxplot.new(*args)\n    end\n    # Returns a Statsample::Graph::Histogram\n    def histogram(*args)\n      Statsample::Graph::Histogram.new(*args)\n    end\n    \n    # Returns a Statsample::Graph::Scatterplot\n    def scatterplot(*args)\n      Statsample::Graph::Scatterplot.new(*args)\n    end\n    # Returns a Statsample::Test::Levene\n    def levene(*args)\n      Statsample::Test::Levene.new(*args)\n    end\n    def principal_axis(*args)\n      Statsample::Factor::PrincipalAxis.new(*args)\n      \n    end\n    def polychoric(*args)\n      Statsample::Bivariate::Polychoric.new(*args)\n    end\n    def tetrachoric(*args)\n      Statsample::Bivariate::Tetrachoric.new(*args)\n    end\n\n    ###\n    # Other Shortcuts\n    ###\n    def lr(*args)\n      Statsample::Regression.multiple(*args)\n    end\n    def pca(ds,opts=Hash.new)\n      Statsample::Factor::PCA.new(ds,opts)\n    end\n    def dominance_analysis(*args)\n      Statsample::DominanceAnalysis.new(*args)\n    end\n    def dominance_analysis_bootstrap(*args)\n      Statsample::DominanceAnalysis::Bootstrap.new(*args)\n    end\n    def scale_analysis(*args)\n      Statsample::Reliability::ScaleAnalysis.new(*args)\n    end\n    def skill_scale_analysis(*args)\n      Statsample::Reliability::SkillScaleAnalysis.new(*args)\n    end\n    def multiscale_analysis(*args,&block)\n      Statsample::Reliability::MultiScaleAnalysis.new(*args,&block)\n    end\n    def test_u(*args)\n      Statsample::Test::UMannWhitney.new(*args)\n    end\n    module_function :test_u, :rnorm\n  end\nend\n"
  },
  {
    "path": "lib/statsample/srs.rb",
    "content": "module Statsample\n\t# Several methods to estimate parameters for simple random sampling\n  # == Reference: \n  # * Cochran, W.(1972). Sampling Techniques [spanish edition].\n  # * http://stattrek.com/Lesson6/SRS.aspx\n  \n\tmodule SRS\n\n\t\tclass << self\n      ########################\n      #\n      # :SECTION: Proportion estimation\n      #\n      # Function for estimation of proportions\n      ########################\n      \n      #\n      # Finite population correction (over variance)\n      # Source: Cochran(1972)\n      def fpc_var(sam,pop)\n          (pop - sam).quo(pop - 1)\n      end\n      # Finite population correction (over standard deviation)\n      def fpc(sam,pop)\n          Math::sqrt((pop-sam).quo(pop-1))\n      end\n      \n      # Non sample fraction.\n      #\n      # 1 - sample fraction\n      def qf(sam , pop)\n          1-(sam.quo(pop))\n      end\n      # Sample size estimation for proportions, infinite poblation\n      def estimation_n0(d,prop,margin=0.95)\n          t=Distribution::Normal.p_value(1-(1-margin).quo(2))\n          var=prop*(1-prop)\n          t**2*var.quo(d**2)\n      end\n      # Sample size estimation for proportions, finite poblation.\n      def estimation_n(d,prop,n_pobl,margin=0.95)\n          n0=estimation_n0(d,prop,margin)\n          n0.quo( 1 + ((n0 - 1).quo(n_pobl)))\n      end\n      \n      \n      # Proportion confidence interval with t values\n      # Uses estimated proportion, sample without replacement.\n      \n      def proportion_confidence_interval_t(prop, n_sample, n_population, margin=0.95)\n          t = Distribution::T.p_value(1-((1-margin).quo(2)) , n_sample-1)\n          proportion_confidence_interval(prop,n_sample,n_population, t)\n      end\n      \n      # Proportion confidence interval with z values\n      # Uses estimated proportion, sample without replacement.\n      def proportion_confidence_interval_z(p, n_sample, n_population, margin=0.95)\n          z=Distribution::Normal.p_value(1-((1-margin).quo(2)))\n          proportion_confidence_interval(p,n_sample,n_population, z)\n      end\n      # Proportion confidence interval with x value\n      # Uses estimated proportion, sample without replacement\n      \n      def proportion_confidence_interval(p, sam,pop , x)\n          #f=sam.quo(pop)\n          one_range=x * Math::sqrt((qf(sam, pop) * p * (1-p)).quo(sam-1)) + (1.quo(sam * 2.0))\n          [p-one_range, p+one_range]\n      end\n      # Standard deviation for sample distribution of a proportion\n      # Know proportion, sample with replacement.\n      # Based on http://stattrek.com/Lesson6/SRS.aspx\n      def proportion_sd_kp_wr(p, n_sample)\n          Math::sqrt(p*(1-p).quo(n_sample))\n      end\n      # Standard deviation for sample distribution of a proportion\n      # Know proportion, sample without replacement.\n      #\n      # Sources: \n      # * Cochran(1972)\n      def proportion_sd_kp_wor(p, sam, pop)\n          fpc(sam,pop)*Math::sqrt(p*(1-p).quo(sam))\n      end\n      # Standard deviation for sample distribution of a proportion\n      # Estimated proportion, sample with replacement\n      # Based on http://stattrek.com/Lesson6/SRS.aspx.\n      def proportion_sd_ep_wr(p, n_sample)\n          Math::sqrt(p*(1-p).quo(n_sample-1))\n      end                                       \n      # Standard deviation for sample distribution of a proportion.\n      # Estimated proportion, sample without replacement.\n      # Reference: \n      # * Cochran, 1972, Técnicas de muestreo\n      def proportion_sd_ep_wor(p, sam,pop)\n          fsc=(pop-sam).quo((sam-1)*pop)\n          Math::sqrt(fsc*p*(1-p))\n      end\n      \n      # Total estimation sd based on sample. \n      # Known proportion, sample without replacement\n      # Reference: \n      # * Cochran(1972)\n      def proportion_total_sd_kp_wor(prop, sam, pop)\n          pob * proportion_sd_kp_wor(p, sam, pop)\n      end\n      # Total estimation sd based on sample. \n      # Estimated proportion, sample without replacement\n      # Source: Cochran(1972)\n      def proportion_total_sd_ep_wor(prop, sam, pop)\n          fsc=((pop - sam).to_f / ( sam - 1))\n          Math::sqrt(fsc*pop*prop*(1-prop))\n      end \n      \n      ########################\n      #\n      # :SECTION:  Mean stimation\n      #\n      ########################\n\n      \n      # Standard error. Known variance, sample with replacement.\n      def standard_error_ksd_wr(s, sam, pop)\n          s.quo(Math::sqrt(sam)) * Math::sqrt((pop-1).quo(pop))\n      end\n      \n      # Standard error of the mean. Known variance, sample w/o replacement\n      def standard_error_ksd_wor(s,sam,pop)\n          s.quo(Math::sqrt(sam)) * Math::sqrt(qf(sam,pop)) \n      end\n      \n      alias_method :standard_error_esd_wr, :standard_error_ksd_wr\n      \n      # Standard error of the mean. \n      # Estimated variance, without replacement\n      # Cochran (1972) p.47\n      def standard_error_esd_wor(s,sam,pop)\n          s.quo(Math::sqrt(sam)) * Math::sqrt(qf(sam,pop))\n      end\n      \n      alias_method :standard_error, :standard_error_esd_wor\n      alias_method :se, :standard_error_esd_wor\n\n      # Standard error of total estimation\n      \n      def standard_error_total(s,sam,pop)\n          pop*se(s,sam,pop)\n      end\n\n      # Confidence Interval using T-Student\n      # Use with n < 60\n      def mean_confidence_interval_t(mean,s,n_sample,n_population,margin=0.95)\n          t=Distribution::T.p_value(1-((1-margin) / 2),n_sample-1)\n          mean_confidence_interval(mean,s,n_sample,n_population,t)\n      end\n      # Confidente Interval using Z\n      # Use with n > 60\n      def mean_confidence_interval_z(mean,s,n_sample,n_population,margin=0.95)\n          z=Distribution::Normal.p_value(1-((1-margin) / 2))\n          mean_confidence_interval(mean,s,n_sample,n_population, z)\n      end\n      # Confidente interval using X.\n      #\n      # Better use mean_confidence_interval_z or mean_confidence_interval_t\n      def mean_confidence_interval(mean,s,n_sample,n_population,x)\n          range=x*se(s,n_sample,n_population)\n          [mean-range,mean+range]\n      end\n\t\tend\n\tend\nend\n"
  },
  {
    "path": "lib/statsample/test/bartlettsphericity.rb",
    "content": "module Statsample\n  module Test\n    # == Bartlett's test of Sphericity.\n    # Test the hyphotesis that the sample correlation matrix\n    # comes from a multivariate normal population where variables\n    # are independent. In other words, the population correlation\n    # matrix is the identity matrix.\n    # == Reference\n    # * Dziuban, C., & Shirkey E. (1974). When is a correlation matrix appropriate for factor analysis? Some decision rules. Psychological Bulletin, 81(6), 358-361.\n    class BartlettSphericity\n      include Statsample::Test\n      include Summarizable\n      attr_accessor :name\n      attr_reader :ncases\n      attr_reader :nvars\n      attr_reader :value\n      attr_reader :df\n      # Args\n      # * _matrix_: correlation matrix\n      # * _ncases_: number of cases\n      def initialize(matrix,ncases)\n        @matrix=matrix\n        @ncases=ncases\n        @nvars=@matrix.row_size\n        @name=_(\"Bartlett's test of sphericity\")\n        compute\n      end\n      # Uses SPSS formula.\n      # On Dziuban & Shirkey, the minus between the first and second\n      # statement is a *!!!\n      # \n      def compute\n        @value=-((@ncases-1)-(2*@nvars+5).quo(6))*Math::log(@matrix.determinant)\n        @df=(@nvars*(@nvars-1)).quo(2)\n      end\n      def probability\n        1-Distribution::ChiSquare.cdf(@value,@df)\n      end\n      def report_building(builder) # :nodoc:\n        builder.text \"%s : X(%d) = %0.4f , p = %0.4f\" % [@name, @df, @value, probability]\n      end\n      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test/chisquare.rb",
    "content": "module Statsample\n  module Test\n    module ChiSquare\n      class WithMatrix\n        attr_reader :df\n        attr_reader :value\n        def initialize(observed, expected=nil)\n          @observed=observed\n          @expected=expected or calculate_expected\n          raise \"Observed size!=expected size\" if @observed.row_size!=@expected.row_size or @observed.column_size!=@expected.column_size\n          @df=(@observed.row_size-1)*(@observed.column_size-1)\n          @value=compute_chi\n        end\n        def calculate_expected\n          sum=@observed.total_sum\n          @expected=Matrix.rows( @observed.row_size.times.map {|i|\n            @observed.column_size.times.map {|j|\n              (@observed.row_sum[i].quo(sum) * @observed.column_sum[j].quo(sum))*sum\n            }\n          })          \n        end\n        def to_f\n          @value\n        end\n        def chi_square\n          @value\n        end\n        def probability\n          1-Distribution::ChiSquare.cdf(@value.to_f,@df)\n        end\n        def compute_chi\n            sum=0\n            (0...@observed.row_size).each {|i|\n              (0...@observed.column_size).each {|j|\n              sum+=((@observed[i, j] - @expected[i,j])**2).quo(@expected[i,j])\n              }\n            }\n            sum\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/statsample/test/f.rb",
    "content": "module Statsample\n  module Test\n    # From Wikipedia:\n    # An F-test is any statistical test in which the test statistic has an F-distribution under the null hypothesis. It is most often used when comparing statistical models that have been fit to a data set, in order to identify the model that best fits the population from which the data were sampled.\n    class F\n      include Statsample::Test\n      include Summarizable\n      attr_reader :var_num, :var_den, :df_num, :df_den, :var_total, :df_total\n      # Tails for probability (:both, :left or :right)\n      attr_accessor :tails\n      # Name of F analysis\n      attr_accessor :name\n\n      # Parameters:\n      # * var_num: variance numerator\n      # * var_den: variance denominator\n      # * df_num: degrees of freedom numerator\n      # * df_den: degrees of freedom denominator\n      def initialize(var_num, var_den, df_num, df_den, opts=Hash.new)\n        @var_num=var_num\n        @var_den=var_den\n        @df_num=df_num\n        @df_den=df_den\n        @var_total=var_num+var_den\n        @df_total=df_num+df_den\n        opts_default={:tails=>:right, :name=>_(\"F Test\")}\n        @opts=opts_default.merge(opts)\n        raise \"Tails should be right or left, not both\" if @opts[:tails]==:both\n        opts_default.keys.each {|k|\n          send(\"#{k}=\", @opts[k])\n        }\n      end\n      def f\n        @var_num.quo(@var_den)\n      end\n      def to_f\n        f\n      end\n      # probability\n      def probability\n        p_using_cdf(Distribution::F.cdf(f, @df_num, @df_den), tails)\n      end\n      def report_building(builder) #:nodoc:\n        if @df_num.is_a? Integer and @df_den.is_a? Integer\n          builder.text \"%s : F(%d, %d) = %0.4f , p = %0.4f\" % [@name, @df_num, @df_den, f, probability]\n        else\n          builder.text \"%s : F(%0.2f, %0.2f) = %0.4f , p = %0.4f\" % [@name, @df_num, @df_den, f, probability]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test/kolmogorovsmirnov.rb",
    "content": "module Statsample\n  module Test\n    # == Kolmogorov-Smirnov's test of equality of distributions.\n    class KolmogorovSmirnov\n      \n      attr_reader :d\n      include Statsample::Test\n      include Summarizable\n      # Creates a new Kolmogorov-Smirnov test\n      # d1 should have each method\n      # d2 could be a Distribution class, with a cdf method,\n      # a vector or a lambda\n      def initialize(d1,d2)\n        raise \"First argument should have each method\" unless d1.respond_to? :each\n        @d1=make_cdf(d1)\n        if d2.respond_to? :cdf or d2.is_a? Proc\n          @d2=d2\n        elsif d2.respond_to? :each\n          @d2=make_cdf(d2)\n        else\n           raise \"Second argument should respond to cdf or each\"    \n         end\n         calculate\n      end\n      def calculate\n         d=0\n        @d1.each {|x|\n        v1=@d1.cdf(x);\n        v2=@d2.is_a?(Proc) ? @d2.call(x) : @d2.cdf(x)\n        d=(v1-v2).to_f.abs if (v1-v2).abs>d\n        }\n        @d=d\n      end\n      # Make a wrapper EmpiricDistribution to any method which implements\n      # each\n      # On Statsample::Vector, only uses #valid_data\n      def make_cdf(v)\n        v.is_a?(Statsample::Vector) ? EmpiricDistribution.new(v.valid_data) : EmpiricDistribution.new(v)\n      end\n      class EmpiricDistribution\n        def initialize(data)\n          @min=data.min\n          @max=data.max\n          @data=data.sort\n          @n=data.size\n        end\n        def each\n          @data.each {|x|\n            yield x\n          }\n        end\n        def cdf(x)\n          return 0 if x<@min\n          return 1 if x>=@max\n          v=@data.index{|v1| v1>=x}\n          v.nil? ? 0 : (v+(x==@data[v]? 1 : 0)).quo(@n)\n        end\n      end # End EmpiricDistribution\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test/levene.rb",
    "content": "module Statsample\n  module Test\n    # = Levene Test for Equality of Variances\n    # From NIST/SEMATECH:\n    # <blockquote>Levene's test ( Levene, 1960) is used to test if k samples have equal variances. Equal variances across samples is called homogeneity of variance. Some statistical tests, for example the analysis of variance, assume that variances are equal across groups or samples. The Levene test can be used to verify that assumption.</blockquote>\n    # Use:\n    #   require 'statsample'\n    #   a=[1,2,3,4,5,6,7,8,100,10].to_scale\n    #   b=[30,40,50,60,70,80,90,100,110,120].to_scale\n    # \n    #   levene=Statsample::Test::Levene.new([a,b])\n    #   puts levene.summary\n    #   \n    # Output:\n    #   Levene Test\n    #   F: 0.778121319848449\n    #   p: 0.389344552595791\n    #\n    # Reference:\n    # * NIST/SEMATECH e-Handbook of Statistical Methods. Available on http://www.itl.nist.gov/div898/handbook/eda/section3/eda35a.htm\n    class Levene\n      include Statsample::Test\n      include Summarizable\n      # Degrees of freedom 1 (k-1)\n      attr_reader :d1\n      # Degrees of freedom 2 (n-k)\n      attr_reader :d2\n      # Name of test\n      attr_accessor :name\n      # Input could be an array of vectors or a dataset\n      def initialize(input, opts=Hash.new())\n        if input.is_a? Statsample::Dataset\n          @vectors=input.vectors.values\n        else\n          @vectors=input\n        end\n        @name=_(\"Levene Test\")\n        opts.each{|k,v|\n          self.send(\"#{k}=\",v) if self.respond_to? k\n        }\n        compute\n      end\n      # Value of the test\n      def f\n        @w\n      end\n      def report_building(builder) # :nodoc:\n        builder.text \"%s : F(%d, %d) = %0.4f , p = %0.4f\" % [@name, @d1, @d2, f, probability]\n      end\n      def compute\n        n=@vectors.inject(0) {|ac,v| ac+v.n_valid}\n        \n        zi=@vectors.collect {|vector|\n          mean=vector.mean\n          vector.collect {|v| (v-mean).abs }.to_scale\n        }\n        \n        total_mean=zi.inject([]) {|ac,vector|\n          ac+vector.valid_data\n        }.to_scale.mean\n      \n        k=@vectors.size\n        \n        sum_num=zi.inject(0) {|ac,vector|\n          ac+(vector.size*(vector.mean-total_mean)**2)\n        }\n        \n        sum_den=zi.inject(0) {|ac,vector|\n          z_mean=vector.mean\n          ac+vector.valid_data.inject(0) {|acp,zij|\n            acp+(zij-z_mean)**2\n          }\n        }\n        @w=((n-k)*sum_num).quo((k-1)*sum_den)\n        @d1=k-1\n        @d2=n-k\n      end\n      private :compute\n      # Probability.\n      # With H_0 = Sum(s2)=0, probability of getting a value of the test upper or equal to the obtained on the sample\n      def probability\n        p_using_cdf(Distribution::F.cdf(f, @d1, @d2), :right)\n      end\n      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test/t.rb",
    "content": "module Statsample\n  module Test\n    \n    \n    \n    \n    # A t-test is any statistical hypothesis test in which the test statistic follows a Student's t distribution, if the null hypothesis is supported\n    class T\n      \n      class << self\n        include Math\n        # Test the null hypothesis that the population mean is equal to a specified value u, one uses the statistic.\n        # Is the same formula used on t-test for paired sample.\n        # * <tt>x</tt>: sample/differences mean\n        # * <tt>u</tt>: population mean\n        # * <tt>s</tt>: sample/differences standard deviation\n        # * <tt>n</tt>: sample size\n        def one_sample(x,u,s,n)\n          (x-u)*Math::sqrt(n).quo(s)\n        end\n        # Test if means of two samples are different.\n        # * <tt>x1</tt>: sample 1 mean\n        # * <tt>x2</tt>: sample 2 mean\n        # * <tt>s1</tt>: sample 1 standard deviation\n        # * <tt>s2</tt>: sample 2 standard deviation\n        # * <tt>n1</tt>: sample 1 size\n        # * <tt>n2</tt>: sample 2 size\n        # * <tt>equal_variance</tt>: true if equal_variance assumed\n        #\n        def two_sample_independent(x1, x2, s1, s2, n1, n2, equal_variance = false)\n          num=x1-x2\n          if equal_variance\n            sx1x2 = sqrt(((n1-1)*s1**2 + (n2-1)*s2**2).quo(n1+n2-2))\n            den   = sx1x2*sqrt(1.quo(n1)+1.quo(n2))\n          else\n            den=sqrt((s1**2).quo(n1) + (s2**2).quo(n2))\n          end\n          num.quo(den)\n        end\n        # Degrees of freedom for equal variance on t test\n        def df_equal_variance(n1,n2)\n          n1+n2-2\n        end\n        # Degrees of freedom for unequal variance\n        # * <tt>s1</tt>: sample 1 standard deviation\n        # * <tt>s2</tt>: sample 2 standard deviation\n        # * <tt>n1</tt>: sample 1 size\n        # * <tt>n2</tt>: sample 2 size\n        # == Reference\n        # * http://en.wikipedia.org/wiki/Welch-Satterthwaite_equation\n        def df_not_equal_variance(s1,s2,n1,n2)\n          s2_1=s1**2\n          s2_2=s2**2\n          num=(s2_1.quo(n1)+s2_2.quo(n2))**2\n          den=(s2_1.quo(n1)**2).quo(n1-1) + (s2_2.quo(n2)**2).quo(n2-1)\n          num.quo(den)\n        end        \n      end\n      \n      include Statsample::Test\n      include Summarizable\n      attr_reader :standard_error, :estimate, :df\n      # Tails for p-value (:both, :left or :right). Default :both\n      attr_accessor :tails\n      # Name of F analysis\n      attr_accessor :name\n      attr_accessor :confidence_level\n      attr_reader :t\n      attr_accessor :estimate_name, :standard_error_name\n      # Creates a generic t test. Use OneSample or TwoSamplesIndependent\n      # classes for better summaries.\n      # Parameters:\n      # * estimate: estimate\n      # * standard_error: standard error of estimate\n      # * df: degrees of freedom\n      def initialize(estimate, standard_error, df, opts=Hash.new)\n        @estimate=estimate\n        @standard_error=standard_error\n        @df=df\n        @t = @estimate / @standard_error.to_f\n        opts_default={  :tails=>:both,\n                        :name=>_(\"T Test\"),\n                        :estimate_name=>_(\"Estimate\"),\n                        :standard_error_name=>_(\"Std.Err.of Estimate\"),\n        :confidence_level=>0.95}\n        @opts = opts_default.merge(opts)\n        \n        @opts.keys.each {|k|\n          send(\"#{k}=\", @opts[k]) if respond_to? k\n        }\n      end\n      \n      alias :se :standard_error\n      \n      def to_f\n        t\n      end\n      \n      # probability\n      def probability\n        p_using_cdf(Distribution::T.cdf(t, df),  tails)\n      end\n      \n      def confidence_interval(cl=nil)\n          cl||=confidence_level\n          t_crit = t_critical(cl, df)\n          [estimate - se*t_crit, estimate + se*t_crit]\n      end\n      alias :ci :confidence_interval\n      \n      \n      def report_building(builder) #:nodoc:\n        builder.section(:name=>@name) do |section|\n          section.text _(\"%s: %0.4f | %s: %0.4f\") % [@estimate_name, @estimate, @standard_error_name, se]\n          report_building_t(section)\n        end\n      end\n      def report_building_t(s)\n        df_f=@df.is_a?(Integer) ? \"%d\" : \"%0.4f\"\n        s.text _(\"t(%d) = %0.4f, p=%0.4f (%s tails)\") % [df, t,probability, tails]\n        s.text _(\"CI(%d%%): %0.4f - %0.4f\") % [confidence_level*100, ci[0],ci[1]]\n        \n      end\n      \n      \n      # One Sample t-test\n      # == Usage\n      #   a=1000.times.map {rand(100)}.to_scale\n      #   t_1=Statsample::Test::T::OneSample.new(a, {:u=>50})\n      #   t_1.summary\n      #\n      # === Output\n      #\n      #  = One Sample T Test\n      #  Sample mean: 48.954\n      #  Population mean:50\n      #  Tails: both\n      #  t = -1.1573, p=0.2474, d.f=999\n\n      class OneSample\n        include Math\n        include Statsample::Test\n        include Summarizable\n        # Options\n        attr_accessor :opts\n        # Name of test\n        attr_accessor :name\n        # Population mean to contrast\n        attr_accessor :u\n        # Degress of freedom\n        attr_reader :df\n        # Tails for probability (:both, :left or :right)\n        attr_accessor :tails \n        \n        # Create a One Sample T Test\n        # Options:\n        # * :u = Mean to compare. Default= 0\n        # * :name = Name of the analysis\n        # * :tails = Tail for probability. Could be :both, :left, :right\n        def initialize(vector, opts=Hash.new)\n          @vector=vector\n          default={:u=>0, :name=>\"One Sample T Test\", :tails=>:both}\n          @opts=default.merge(opts)\n          @name=@opts[:name]\n          @u=@opts[:u]\n          @tails=@opts[:tails]\n          @confidence_level=@opts[:confidence_level] || 0.95\n          @df= @vector.n_valid-1\n          @t=nil\n        end        \n        def t_object\n          T.new(@vector.mean-u, @vector.se, @vector.n_valid-1, opts)\n        end\n        def t\n          t_object.t\n        end\n        def probability\n          t_object.probability\n        end\n        def standard_error\n          t_object.standard_error\n        end\n        alias :se :standard_error\n        def confidence_interval(cl=nil)\n          t_object.confidence_interval(cl)\n        end\n        alias :ci :confidence_interval\n        def report_building(b) # :nodoc:\n          b.section(:name=>@name) {|s|\n            s.text _(\"Sample mean: %0.4f | Sample sd: %0.4f | se : %0.4f\") % [@vector.mean, @vector.sd, se]\n            s.text _(\"Population mean: %0.4f\") % u if u!=0\n            t_object.report_building_t(s)\n          }\n        end\n      end\n      # Two Sample t-test.\n      #\n      # == Usage\n      #   a=1000.times.map {rand(100)}.to_scale\n      #   b=1000.times.map {rand(100)}.to_scale\n      #   t_2=Statsample::Test::T::TwoSamplesIndependent.new(a,b)\n      #   t_2.summary\n      # === Output\n      #  = Two Sample T Test\n      #  Mean and standard deviation\n      #  +----------+---------+---------+------+\n      #  | Variable |    m    |   sd    |  n   |\n      #  +----------+---------+---------+------+\n      #  | 1        | 49.3310 | 29.3042 | 1000 |\n      #  | 2        | 47.8180 | 28.8640 | 1000 |\n      #  +----------+---------+---------+------+\n      #  \n      #  == Levene Test\n      #   Levene Test\n      #   F: 0.3596\n      #   p: 0.5488\n      #   T statistics\n      #   +--------------------+--------+-----------+----------------+\n      #   |        Type        |   t    |    df     | p (both tails) |\n      #   +--------------------+--------+-----------+----------------+\n      #   | Equal variance     | 1.1632 | 1998      | 0.2449         |\n      #   | Non equal variance | 1.1632 | 1997.5424 | 0.1362         |\n      #   +--------------------+--------+-----------+----------------+\n\n      class TwoSamplesIndependent\n        include Math\n        include Statsample::Test\n        \n        include DirtyMemoize\n        include Summarizable\n        # Options\n        attr_accessor :opts\n        # Name of test\n        attr_accessor :name\n        # Degress of freedom (equal variance)\n        attr_reader :df_equal_variance\n        # Degress of freedom (not equal variance)\n        attr_reader :df_not_equal_variance\n        # Value of t for equal_variance\n        attr_reader :t_equal_variance\n        # Value of t for non-equal_variance\n        attr_reader :t_not_equal_variance\n        # Probability(equal variance)\n        attr_reader :probability_equal_variance\n        # Probability(unequal variance)\n        attr_reader :probability_not_equal_variance        \n        # Tails for probability (:both, :left or :right)\n        attr_accessor :tails \n        # Create the object\n        \n        dirty_writer :tails\n        dirty_memoize :t_equal_variance, :t_not_equal_variance, :probability_equal_variance, :probability_not_equal_variance, :df_equal_variance, :df_not_equal_variance\n\n        # Create a Two Independent T Test\n        # Options:\n        # * :name = Name of the analysis\n        # * :tails = Tail for probability. Could be :both, :left, :right        \n        def initialize(v1, v2, opts=Hash.new)\n          @v1=v1\n          @v2=v2\n          default={:u=>0, :name=>\"Two Sample T Test\",  :tails=>:both}\n          @opts=default.merge(opts)\n          @name=@opts[:name]\n          @tails=@opts[:tails]          \n        end        \n       \n        # Set t and probability for given u\n        def compute\n          @t_equal_variance= T.two_sample_independent(@v1.mean, @v2.mean, @v1.sd, @v2.sd, @v1.n_valid, @v2.n_valid,true)\n          \n          @t_not_equal_variance= T.two_sample_independent(@v1.mean, @v2.mean, @v1.sd, @v2.sd, @v1.n_valid, @v2.n_valid, false)\n\n          @df_equal_variance=T.df_equal_variance(@v1.n_valid, @v2.n_valid)\n          @df_not_equal_variance=T.df_not_equal_variance(@v1.sd, @v2.sd, @v1.n_valid, @v2.n_valid)\n          \n          @probability_equal_variance = p_using_cdf(Distribution::T.cdf(@t_equal_variance, @df_equal_variance), tails)\n          \n          @probability_not_equal_variance = p_using_cdf(Distribution::T.cdf(@t_not_equal_variance, @df_not_equal_variance), tails)\n\n        end\n        # Cohen's d is a measure of effect size. Its defined as the difference between two means divided by a standard deviation for the data\n        def d\n          n1=@v1.n_valid\n          n2=@v2.n_valid\n          num=@v1.mean-@v2.mean\n          den=Math::sqrt( ((n1-1)*@v1.sd+(n2-1)*@v2.sd).quo(n1+n2))\n          num.quo(den)\n        end\n        \n        def report_building(b) # :nodoc:\n          b.section(:name=>@name) {|g|\n            g.table(:name=>_(\"Mean and standard deviation\"), :header=>[_(\"Variable\"), _(\"mean\"), _(\"sd\"),_(\"n\")]) {|t|\n              t.row([@v1.name,\"%0.4f\" % @v1.mean,\"%0.4f\" % @v1.sd,@v1.n_valid])\n              t.row([@v2.name,\"%0.4f\" % @v2.mean,\"%0.4f\" % @v2.sd, @v2.n_valid])\n            }\n            g.parse_element(Statsample::Test.levene([@v1,@v2],:name=>_(\"Levene test for equality of variances\")))\n            \n            g.table(:name=>_(\"T statistics\"),:header=>[\"Type\",\"t\",\"df\", \"p (#{tails} tails)\"].map{|v| _(v)}) {|t|\n              t.row([_(\"Equal variance\"), \"%0.4f\" % t_equal_variance, df_equal_variance, \"%0.4f\" % probability_equal_variance])\n              t.row([_(\"Non equal variance\"), \"%0.4f\" % t_not_equal_variance, \"%0.4f\" % df_not_equal_variance, \"%0.4f\" % probability_not_equal_variance])\n            }\n            g.table(:name=>_(\"Effect size\")) do |t|\n              t.row ['x1-x2', \"%0.4f\" % (@v1.mean-@v2.mean)]\n              t.row ['d', \"%0.4f\" % d]\n            end\n          }\n        end\n      end      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test/umannwhitney.rb",
    "content": "module Statsample\n  module Test\n    #\n    # = U Mann-Whitney test\n    #\n    # Non-parametric test for assessing whether two independent samples\n    # of observations come from the same distribution.\n    # \n    # == Assumptions\n    #\n    # * The two samples under investigation in the test are independent of each other and the observations within each sample are independent.\n    # * The observations are comparable (i.e., for any two observations, one can assess whether they are equal or, if not, which one is greater).\n    # * The variances in the two groups are approximately equal.\n    #\n    # Higher differences of distributions correspond to \n    # to lower values of U.\n    #\n    class UMannWhitney\n      # Max for m*n allowed for exact calculation of probability\n      MAX_MN_EXACT=10000\n      \n      # U sampling distribution, based on Dinneen & Blakesley (1973) algorithm.\n      # This is the algorithm used on SPSS.\n      # \n      # Parameters:\n      # * <tt>n1</tt>: group 1 size\n      # * <tt>n2</tt>: group 2 size \n      # == Reference: \n      # * Dinneen, L., & Blakesley, B. (1973). Algorithm AS 62: A Generator for the Sampling Distribution of the Mann- Whitney U Statistic. <em>Journal of the Royal Statistical Society, 22</em>(2), 269-273\n      # \n      def self.u_sampling_distribution_as62(n1,n2)\n\n        freq=[]\n        work=[]\n        mn1=n1*n2+1\n        max_u=n1*n2\n        minmn=n1<n2 ? n1 : n2\n        maxmn=n1>n2 ? n1 : n2\n        n1=maxmn+1\n        (1..n1).each{|i| freq[i]=1}\n        n1+=1\n        (n1..mn1).each{|i| freq[i]=0}\n        work[1]=0\n        xin=maxmn\n        (2..minmn).each do |i|\n          work[i]=0\n          xin=xin+maxmn\n          n1=xin+2\n          l=1+xin.quo(2)\n          k=i\n          (1..l).each do |j|\n            k=k+1\n            n1=n1-1\n            sum=freq[j]+work[j]\n            freq[j]=sum\n            work[k]=sum-freq[n1]\n            freq[n1]=sum\n          end\n        end\n        \n        # Generate percentages for normal U\n        dist=(1+max_u/2).to_i\n        freq.shift\n        total=freq.inject(0) {|a,v| a+v }\n        (0...dist).collect {|i|\n          if i!=max_u-i\n            ues=freq[i]*2\n          else\n            ues=freq[i]\n          end\n          ues.quo(total)\n        }\n      end\n      \n      # Generate distribution for permutations. \n      # Very expensive, but useful for demostrations\n      \n      def self.distribution_permutations(n1,n2)\n        base=[0]*n1+[1]*n2\n        po=Statsample::Permutation.new(base)\n        \n        total=n1*n2\n        req={}\n        po.each do |perm|\n          r0,s0=0,0\n          perm.each_index {|c_i|\n            if perm[c_i]==0\n              r0+=c_i+1\n              s0+=1\n            end\n          }\n          u1=r0-((s0*(s0+1)).quo(2))\n          u2=total-u1\n          temp_u= (u1 <= u2) ? u1 : u2\n          req[perm]=temp_u\n        end\n        req\n      end\n      # Sample 1 Rank sum\n      attr_reader :r1\n      # Sample 2 Rank sum\n      attr_reader :r2\n      # Sample 1 U (useful for demostration)\n      attr_reader :u1\n      # Sample 2 U (useful for demostration)\n      attr_reader :u2\n      # U Value \n      attr_reader :u\n      # Value of compensation for ties (useful for demostration)\n      attr_reader :t\n      # Name of test\n      attr_accessor :name\n      include Summarizable\n      #\n      # Create a new U Mann-Whitney test\n      # Params: Two Statsample::Vectors\n      # \n      def initialize(v1,v2, opts=Hash.new)\n        @v1=v1\n        @v2=v2\n        @n1=v1.valid_data.size\n        @n2=v2.valid_data.size\n        data=(v1.valid_data+v2.valid_data).to_scale\n        groups=(([0]*@n1)+([1]*@n2)).to_vector\n        ds={'g'=>groups, 'data'=>data}.to_dataset\n        @t=nil\n        @ties=data.data.size!=data.data.uniq.size        \n        if(@ties)\n          adjust_for_ties(ds['data'])\n        end\n        ds['ranked']=ds['data'].ranked(:scale)\n        \n        @n=ds.cases\n          \n        @r1=ds.filter{|r| r['g']==0}['ranked'].sum\n        @r2=((ds.cases*(ds.cases+1)).quo(2))-r1\n        @u1=r1-((@n1*(@n1+1)).quo(2))\n        @u2=r2-((@n2*(@n2+1)).quo(2))\n        @u=(u1<u2) ? u1 : u2\n        opts_default={:name=>_(\"Mann-Whitney's U\")}\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k|\n          send(\"#{k}=\", @opts[k])\n        }\n          \n      end\n      def report_building(generator) # :nodoc:\n        generator.section(:name=>@name) do |s|\n          s.table(:name=>_(\"%s results\") % @name) do |t|\n            t.row([_(\"Sum of ranks %s\") % @v1.name, \"%0.3f\" % @r1])\n            t.row([_(\"Sum of ranks %s\") % @v2.name, \"%0.3f\" % @r2])\n            t.row([_(\"U Value\"), \"%0.3f\" % @u])\n            t.row([_(\"Z\"), \"%0.3f (p: %0.3f)\" % [z, probability_z]])\n            if @n1*@n2<MAX_MN_EXACT\n              t.row([_(\"Exact p (Dinneen & Blakesley, 1973):\"), \"%0.3f\" % probability_exact])\n            end\n          end\n        end\n      end\n      # Exact probability of finding values of U lower or equal to sample on U distribution. Use with caution with m*n>100000.\n      # Uses u_sampling_distribution_as62\n      def probability_exact\n        dist=UMannWhitney.u_sampling_distribution_as62(@n1,@n2)\n        sum=0\n        (0..@u.to_i).each {|i|\n          sum+=dist[i]\n        }\n        sum\n      end\n      # Adjunt for ties.\n      # \n      # == Reference: \n      # * http://europe.isixsigma.com/library/content/c080806a.asp\n      def adjust_for_ties(data)\n        @t=data.frequencies.find_all{|k,v| v>1}.inject(0) {|a,v|\n          a+(v[1]**3-v[1]).quo(12)\n        }        \n      end\n      \n      private :adjust_for_ties\n      \n      # Z value for U, with adjust for ties.\n      # For large samples, U is approximately normally distributed. \n      # In that case, you can use z to obtain probabily for U.\n      # == Reference: \n      # * SPSS Manual\n      def z\n        mu=(@n1*@n2).quo(2)\n        if(!@ties)\n          ou=Math::sqrt(((@n1*@n2)*(@n1+@n2+1)).quo(12))\n        else\n          n=@n1+@n2\n          first=(@n1*@n2).quo(n*(n-1))\n          second=((n**3-n).quo(12))-@t\n          ou=Math::sqrt(first*second)\n        end\n        (@u-mu).quo(ou)\n      end\n      # Assuming H_0, the proportion of cdf with values of U lower\n      # than the sample, using normal approximation.\n      # Use with more than 30 cases per group.\n      def probability_z\n        (1-Distribution::Normal.cdf(z.abs()))*2\n      end\n    end\n      \n  end\nend"
  },
  {
    "path": "lib/statsample/test/wilcoxonsignedrank.rb",
    "content": "module Statsample\n  module Test\n    # From Wikipedia:\n    # The Wilcoxon signed-rank test is a non-parametric statistical hypothesis test used when comparing two related samples, matched samples, or repeated measurements on a single sample to assess whether their population mean ranks differ (i.e. it is a paired difference test). It can be used as an alternative to the paired Student's t-test, t-test for matched pairs, or the t-test for dependent samples when the population cannot be assumed to be normally distributed.\n    class WilcoxonSignedRank\n      include Statsample::Test\n      include Summarizable\n      \n      # Name of F analysis\n      attr_accessor :name\n\t  attr_reader :w\n\t  attr_reader :nr\n\t  attr_writer :tails\n      # Parameters:\n      def initialize(v1,v2, opts=Hash.new)\n\t\t@v1=v1\n\t\t@v2=v2\n        opts_default={:name=>_(\"Wilcoxon Signed Rank Test\"),:tails=>:both}\n        @opts=opts_default.merge(opts)\n        opts_default.keys.each {|k|\n          send(\"#{k}=\", @opts[k])\n        }\n        calculate\n      end\n      def calculate\n\t\tdf=Statsample::Dataset.new({'v1'=>@v1,'v2'=>@v2})\n\t\tdf[\"abs\"]=df.collect {|row| \n\t\t\tr=(row[\"v2\"]-row[\"v1\"]).abs\n\t\t}\n\t\tdf[\"sgn\"]=df.collect {|row| \n\t\t\tr=row[\"v2\"]-row[\"v1\"]\n\t\t\tr==0 ? 0 : r/r.abs\n\t\t}\n\t\tdf=df.filter {|row| row[\"sgn\"]!=0}\n\t\tdf[\"rank\"]=df[\"abs\"].ranked\n\t\t@nr=df.cases\n\t\t@w=df.collect {|row|\n\t\t\trow[\"sgn\"]*row[\"rank\"]\n\t\t\t#p row[\"sgn\"]*row[\"rank\"]\n\t\t}.sum\n      end\n      def report_building(generator) # :nodoc:\n        generator.section(:name=>@name) do |s|\n          s.table(:name=>_(\"%s results\") % @name) do |t|\n            t.row([_(\"W Value\"), \"%0.3f\" % @w])\n            t.row([_(\"Z\"), \"%0.3f (p: %0.3f)\" % [z, probability_z]])\n            if(nr<=10) \n\t\t\t\tt.row([_(\"Exact probability\"), \"p-exact: %0.3f\" % [probability_exact]])\n            end\n          end\n        end\n      end\n      def z\n\t\tsigma=Math.sqrt((nr*(nr+1)*(2*nr+1))/6)\n\t\t(w-0.5)/sigma\n      end\n      # Assuming normal distribution of W, this calculate\n      # the probability of samples with Z equal or higher than\n      # obtained on sample\n      def probability_z\n\t\t(1-Distribution::Normal.cdf(z))*(@tails==:both ? 2:1)\n      end\n      # Calculate exact probability.\n      # Don't calculate for large Nr, please!\n      def probability_exact\n\t\tstr_format=\"%0#{nr}b\"\n\t\tcombinations=2**nr\n\t\t#p str_format\n\t\ttotal_w=combinations.times.map {|i|\n\t\t\tcomb=sprintf(str_format,i)\n\t\t\tw_local=comb.length.times.inject(0) {|ac,j|\n\t\t\t\tsgn=comb[j]==\"0\" ? -1 : 1\n\t\t\t\tac+(j+1)*sgn\n\t\t\t}\n\t\t}.sort\n\t\ttotal_w.find_all {|v| \n\t\t\tif @tails==:both\n\t\t\t\tv<=-w.abs or v>=w.abs\n\t\t\telsif @tails==:left\n\t\t\t\tv<=w\n\t\t\telsif @tails==:right\n\t\t\t\tv>=w\n\t\t\tend\n\t\t}.count/(combinations.to_f)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/test.rb",
    "content": "module Statsample\n  # Module for several statistical tests\n  \n  module Test\n    autoload(:UMannWhitney, 'statsample/test/umannwhitney')\n    autoload(:Levene, 'statsample/test/levene')\n    autoload(:T, 'statsample/test/t')\n    autoload(:F, 'statsample/test/f')\n    autoload(:ChiSquare, 'statsample/test/chisquare')\n    autoload(:BartlettSphericity, 'statsample/test/bartlettsphericity')\n    autoload(:KolmogorovSmirnov, 'statsample/test/kolmogorovsmirnov')\n    autoload(:WilcoxonSignedRank, 'statsample/test/wilcoxonsignedrank')\n    \n    \n    # Returns probability of getting a value lower or higher\n    # than sample, using cdf and number of tails.\n    # \n    # * <tt>:left</tt> : For one tail left, return the cdf\n    # * <tt>:right</tt> : For one tail right, return 1-cdf\n    # * <tt>:both</tt> : For both tails, returns 2*right_tail(cdf.abs)\n    def p_using_cdf(cdf, tails=:both)\n      tails=:both if tails==2 or tails==:two\n      tails=:right if tails==1 or tails==:positive\n      tails=:left if tails==:negative\n      case tails\n        when :left then cdf\n        when :right then 1-cdf\n        when :both \n          if cdf>=0.5\n            cdf=1-cdf\n          end\n          2*cdf\n      end\n    end\n    # Get critical t to create confidence interval \n    def t_critical(confidence_level, df)\n      -Distribution::T.p_value((1-confidence_level) / 2.0, df)\n    end\n    # Get critical z to create confidence interval \n    def z_critical(confidence_level)\n      -Distribution::Z.p_value((1-confidence_level) / 2.0)\n    end\n    \n    extend self\n    # Calculate chi square for two Matrix\n    class << self\n      def chi_square(observed, expected=nil)\n        case observed\n          when Vector\n            ChiSquare::WithVector.new(observed,expected)\n          when Matrix\n            ChiSquare::WithMatrix.new(observed,expected)\n          else\n            raise \"Not implemented for #{observed.class}\"\n        end\n      end\n      # Shorthand for Statsample::Test::UMannWhitney.new\n      # \n      # * <tt>v1</tt> and <tt>v2</tt> should be Statsample::Vector.\n      def u_mannwhitney(v1, v2)\n        Statsample::Test::UMannWhitney.new(v1,v2)\n      end\n      # Shorthand for Statsample::Test::T::OneSample.new\n      def t_one_sample(vector, opts=Hash.new)\n        Statsample::Test::T::OneSample.new(vector,opts)\n      end\n      # Shorthand for Statsample::Test::T::TwoSamplesIndependent.new\n      def t_two_samples_independent(v1,v2, opts=Hash.new)\n        Statsample::Test::T::TwoSamplesIndependent.new(v1,v2,opts)\n      end\n      # Shorthand for Statsample::Test::WilcoxonSignedRank.new\n\t  def wilcoxon_signed_rank(v1,v2,opts=Hash.new)\n\t\tStatsample::Test::WilcoxonSignedRank.new(v1,v2,opts)\n\t  end\n      # Shorthand for Statsample::Test::Levene.new\n      def levene(input, opts=Hash.new)\n        Statsample::Test::Levene.new(input,opts)\n      end\n      \n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/vector/gsl.rb",
    "content": "module Statsample\n  class Vector\n    module GSL_      \n      def clear_gsl\n        @gsl=nil\n      end\n      \n      def set_valid_data\n        clear_gsl\n        set_valid_data_ruby\n      end\n      def push(v)\n        # If data is GSL::Vector, should be converted first to an Array\n        if @data.is_a? GSL::Vector\n          @data=@data.to_a\n        end\n        push_ruby(v)\n      end\n      \n      def gsl\n        @gsl||=GSL::Vector.alloc(@scale_data) if @scale_data.size>0\n      end\n      \n      alias :to_gsl :gsl\n      def vector_standarized_compute(m,sd)\n        if flawed?\n          vector_standarized_compute_ruby(m,sd)\n        else\n          gsl.collect {|x| (x.to_f - m).quo(sd)}.to_scale\n        end\n      end\n      \n      def vector_centered_compute(m)\n        if flawed?\n          vector_centered_compute_ruby(m)\n        else\n          gsl.collect {|x| (x.to_f - m)}.to_scale\n        end\n      end\n      def sample_with_replacement(sample=1)\n        if(@type!=:scale)\n          sample_with_replacement_ruby(sample)\n        else\n          r = GSL::Rng.alloc(GSL::Rng::MT19937,rand(10000))\n          Statsample::Vector.new(r.sample(gsl, sample).to_a,:scale)\n        end\n      end\n      \n      def sample_without_replacement(sample=1)\n        if(@type!=:scale)\n          sample_without_replacement_ruby(sample)\n        else\n          r = GSL::Rng.alloc(GSL::Rng::MT19937,rand(10000))\n          r.choose(gsl, sample).to_a\n        end\n      end\n      def median\n        if @type!=:scale\n          median_ruby\n        else\n          sorted=GSL::Vector.alloc(@scale_data.sort)\n          GSL::Stats::median_from_sorted_data(sorted)\n        end\n      end\n      \n      def sum \n        check_type :scale\n        gsl.nil? ? nil : gsl.sum\n      end\n      def mean\n        check_type :scale\n        gsl.nil? ? nil : gsl.mean\n      end\t\t\t\t\n      def variance_sample(m=nil)\n        check_type :scale\n        m||=mean\n        gsl.nil? ? nil : gsl.variance_m\n      end\n      \n      def standard_deviation_sample(m=nil)\n        check_type :scale\n        m||=mean\n        gsl.nil? ? nil : gsl.sd(m)\n      end\n\n      def variance_population(m=nil) # :nodoc:\n        check_type :scale    \n        m||=mean\n        gsl.nil? ? nil : gsl.variance_with_fixed_mean(m)\n      end\n      def standard_deviation_population(m=nil) # :nodoc:\n        check_type :scale\n        m||=mean\n        gsl.nil? ? nil : gsl.sd_with_fixed_mean(m)\n      end\n      def skew # :nodoc:\n        check_type :scale\n        gsl.nil? ? nil : gsl.skew\n      end\n      def kurtosis # :nodoc:\n        check_type :scale\n        gsl.nil? ? nil : gsl.kurtosis\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/statsample/vector.rb",
    "content": "require 'date'\nrequire 'statsample/vector/gsl'\n\nmodule Statsample::VectorShorthands\n  # Creates a new Statsample::Vector object\n  # Argument should be equal to Vector.new\n  def to_vector(*args)\n\t\tStatsample::Vector.new(self,*args)\n\tend\n  # Creates a new Statsample::Vector object of type :scale\n  def to_scale(*args)\n    Statsample::Vector.new(self, :scale, *args)\n  end\nend\n\nclass Array\n  include Statsample::VectorShorthands\nend\n\nif Statsample.has_gsl?\n  module GSL\n    class Vector\n      include Statsample::VectorShorthands\n    end\n  end\nend\nmodule Statsample\n\n\n  # Collection of values on one dimension. Works as a column on a Spreadsheet.\n  #\n  # == Usage\n  # The fast way to create a vector uses Array.to_vector or Array.to_scale.\n  #\n  #  v=[1,2,3,4].to_vector(:scale)\n  #  v=[1,2,3,4].to_scale\n  #\n  class Vector\n    include Enumerable\n    include Writable\n    include Summarizable\n    include Statsample::VectorShorthands\n\n    # Level of measurement. Could be :nominal, :ordinal or :scale\n    attr_reader :type\n    # Original data.\n    attr_reader :data\n    # Valid data. Equal to data, minus values assigned as missing values\n    attr_reader :valid_data\n    # Array of values considered as missing. Nil is a missing value, by default\n    attr_reader :missing_values\n    # Array of values considered as \"Today\", with date type. \"NOW\", \"TODAY\", :NOW and :TODAY are 'today' values, by default\n    attr_reader :today_values\n    # Missing values array\n    attr_reader :missing_data\n    # Original data, with all missing values replaced by nils\n    attr_reader :data_with_nils\n    # Date date, with all missing values replaced by nils\n    attr_reader :date_data_with_nils\n    # Change label for specific values\n    attr_accessor :labels\n    # Name of vector. Should be used for output by many classes\n    attr_accessor :name\n\n    # Creates a new Vector object.\n    # * <tt>data</tt> Any data which can be converted on Array\n    # * <tt>type</tt> Level of meausurement. See Vector#type\n    # * <tt>opts</tt> Hash of options\n    #   * <tt>:missing_values</tt>  Array of missing values. See Vector#missing_values\n    #   * <tt>:today_values</tt> Array of 'today' values. See Vector#today_values\n    #   * <tt>:labels</tt> Labels for data values\n    #   * <tt>:name</tt> Name of vector\n    def initialize(data=[], type=:nominal, opts=Hash.new)\n      @data=data.is_a?(Array) ? data : data.to_a\n      @type=type\n      opts_default={\n        :missing_values=>[],\n        :today_values=>['NOW','TODAY', :NOW, :TODAY],\n        :labels=>{},\n        :name=>nil\n      }\n      @opts=opts_default.merge(opts)\n      if  @opts[:name].nil?\n        @@n_table||=0\n        @@n_table+=1\n        @opts[:name]=\"Vector #{@@n_table}\"\n      end\n      @missing_values=@opts[:missing_values]\n      @labels=@opts[:labels]\n      @today_values=@opts[:today_values]\n      @name=@opts[:name]\n      @valid_data=[]\n      @data_with_nils=[]\n      @date_data_with_nils=[]\n      @missing_data=[]\n      @has_missing_data=nil\n      @scale_data=nil\n      set_valid_data\n      self.type=type\n    end\n    # Create a vector using (almost) any object\n    # * Array: flattened\n    # * Range: transformed using to_a\n    # * Statsample::Vector\n    # * Numeric and string values\n    def self.[](*args)\n      values=[]\n      args.each do |a|\n        case a\n        when Array\n          values.concat a.flatten\n        when Statsample::Vector\n          values.concat a.to_a\n        when Range\n          values.concat  a.to_a\n        else\n          values << a\n        end\n      end\n      vector=new(values)\n      vector.type=:scale if vector.can_be_scale?\n      vector\n    end\n    # Create a new scale type vector\n    # Parameters\n    # [n]      Size\n    # [val]    Value of each value\n    # [&block] If block provided, is used to set the values of vector\n    def self.new_scale(n,val=nil, &block)\n      if block\n        vector=n.times.map {|i| block.call(i)}.to_scale\n      else\n        vector=n.times.map { val}.to_scale\n      end\n      vector.type=:scale\n      vector\n    end\n    # Creates a duplicate of the Vector.\n    # Note: data, missing_values and labels are duplicated, so\n    # changes on original vector doesn't propages to copies.\n    def dup\n      Vector.new(@data.dup,@type, :missing_values => @missing_values.dup, :labels => @labels.dup, :name=>@name)\n    end\n    # Returns an empty duplicate of the vector. Maintains the type,\n    # missing values and labels.\n    def dup_empty\n      Vector.new([],@type, :missing_values => @missing_values.dup, :labels => @labels.dup, :name=> @name)\n    end\n\n    if Statsample::STATSAMPLE__.respond_to?(:check_type)\n      # Raises an exception if type of vector is inferior to t type\n      def check_type(t)\n        Statsample::STATSAMPLE__.check_type(self,t)\n      end\n    else\n      def check_type(t) #:nodoc:\n        _check_type(t)\n      end\n    end\n\n\n    def _check_type(t) #:nodoc:\n      raise NoMethodError if (t==:scale and @type!=:scale) or (t==:ordinal and @type==:nominal) or (t==:date) or (:date==@type)\n    end\n\n    def vector_standarized_compute(m,sd) # :nodoc:\n      @data_with_nils.collect{|x| x.nil? ? nil : (x.to_f - m).quo(sd) }.to_vector(:scale)\n    end\n    # Return a vector usign the standarized values for data\n    # with sd with denominator n-1. With variance=0 or mean nil,\n    # returns a vector of equal size full of nils\n    #\n    def vector_standarized(use_population=false)\n      check_type :scale\n      m=mean\n      sd=use_population ? sdp : sds\n      return ([nil]*size).to_scale if mean.nil? or sd==0.0\n      vector=vector_standarized_compute(m,sd)\n      vector.name=_(\"%s(standarized)\")  % @name\n      vector\n    end\n    def vector_centered_compute(m) #:nodoc:\n      @data_with_nils.collect {|x| x.nil? ? nil : x.to_f-m }.to_scale\n    end\n    # Return a centered vector\n    def vector_centered\n      check_type :scale\n      m=mean\n      return ([nil]*size).to_scale if mean.nil?\n      vector=vector_centered_compute(m)\n      vector.name=_(\"%s(centered)\") % @name\n      vector\n    end\n\n    alias_method :standarized, :vector_standarized\n    alias_method  :centered, :vector_centered\n    # Return a vector with values replaced with the percentiles\n    # of each values\n    def vector_percentil\n      check_type :ordinal\n      c=@valid_data.size\n      vector=ranked.map {|i| i.nil? ? nil : (i.quo(c)*100).to_f }.to_vector(@type)\n      vector.name=_(\"%s(percentil)\")  % @name\n      vector\n    end\n    def box_cox_transformation(lambda) # :nodoc:\n      raise \"Should be a scale\" unless @type==:scale\n      @data_with_nils.collect{|x|\n      if !x.nil?\n        if(lambda==0)\n          Math.log(x)\n        else\n          (x**lambda-1).quo(lambda)\n        end\n      else\n        nil\n      end\n      }.to_vector(:scale)\n    end\n\n    # Vector equality.\n    # Two vector will be the same if their data, missing values, type, labels are equals\n    def ==(v2)\n      return false unless v2.instance_of? Statsample::Vector\n      @data==v2.data and @missing_values==v2.missing_values and @type==v2.type and @labels==v2.labels\n    end\n\n    def _dump(i) # :nodoc:\n      Marshal.dump({'data'=>@data,'missing_values'=>@missing_values, 'labels'=>@labels, 'type'=>@type,'name'=>@name})\n    end\n\n    def self._load(data) # :nodoc:\n    h=Marshal.load(data)\n    Vector.new(h['data'], h['type'], :missing_values=> h['missing_values'], :labels=>h['labels'], :name=>h['name'])\n    end\n    # Returns a new vector, with data modified by block.\n    # Equivalent to create a Vector after #collect on data\n    def recode(type=nil)\n      type||=@type\n      @data.collect{|x|\n        yield x\n      }.to_vector(type)\n    end\n    # Modifies current vector, with data modified by block.\n    # Equivalent to #collect! on @data\n    def recode!\n    @data.collect!{|x|\n      yield x\n    }\n    set_valid_data\n    end\n    def push(v)\n      @data.push(v)\n      set_valid_data\n    end\n    # Dicotomize the vector with 0 and 1, based on lowest value\n    # If parameter if defined, this value and lower\n    # will be 0 and higher, 1\n    def dichotomize(low=nil)\n      fs=factors\n      low||=factors.min\n      @data_with_nils.collect{|x|\n        if x.nil?\n          nil\n        elsif x>low\n          1\n        else\n          0\n        end\n      }.to_scale\n    end\n    # Iterate on each item.\n    # Equivalent to\n    #   @data.each{|x| yield x}\n    def each\n      @data.each{|x| yield(x) }\n    end\n\n    # Iterate on each item, retrieving index\n    def each_index\n    (0...@data.size).each {|i|\n      yield(i)\n    }\n    end\n    # Add a value at the end of the vector.\n    # If second argument set to false, you should update the Vector usign\n    # Vector.set_valid_data at the end of your insertion cycle\n    #\n    def add(v,update_valid=true)\n      @data.push(v)\n      set_valid_data if update_valid\n    end\n    # Update valid_data, missing_data, data_with_nils and gsl\n    # at the end of an insertion.\n    #\n    # Use after Vector.add(v,false)\n    # Usage:\n    #   v=Statsample::Vector.new\n    #   v.add(2,false)\n    #   v.add(4,false)\n    #   v.data\n    #   => [2,3]\n    #   v.valid_data\n    #   => []\n    #   v.set_valid_data\n    #   v.valid_data\n    #   => [2,3]\n    def set_valid_data\n      @valid_data.clear\n      @missing_data.clear\n      @data_with_nils.clear\n      @date_data_with_nils.clear\n      set_valid_data_intern\n      set_scale_data if(@type==:scale)\n      set_date_data if(@type==:date)\n    end\n    if Statsample::STATSAMPLE__.respond_to?(:set_valid_data_intern)\n      def set_valid_data_intern #:nodoc:\n        Statsample::STATSAMPLE__.set_valid_data_intern(self)\n      end\n    else\n      def set_valid_data_intern #:nodoc:\n        _set_valid_data_intern\n      end\n    end\n    def _set_valid_data_intern #:nodoc:\n      @data.each do |n|\n        if is_valid? n\n          @valid_data.push(n)\n          @data_with_nils.push(n)\n        else\n          @data_with_nils.push(nil)\n          @missing_data.push(n)\n        end\n      end\n      @has_missing_data=@missing_data.size>0\n    end\n\n    # Retrieves true if data has one o more missing values\n    def has_missing_data?\n      @has_missing_data\n    end\n    alias :flawed? :has_missing_data?\n\n    # Retrieves label for value x. Retrieves x if\n    # no label defined.\n    def labeling(x)\n      @labels.has_key?(x) ? @labels[x].to_s : x.to_s\n    end\n    alias :label :labeling\n    # Returns a Vector with data with labels replaced by the label.\n    def vector_labeled\n      d=@data.collect{|x|\n        if @labels.has_key? x\n          @labels[x]\n        else\n          x\n        end\n      }\n      Vector.new(d,@type)\n    end\n    # Size of total data\n    def size\n      @data.size\n    end\n    alias_method :n, :size\n\n    # Retrieves i element of data\n    def [](i)\n      @data[i]\n    end\n    # Set i element of data.\n    # Note: Use set_valid_data if you include missing values\n    def []=(i,v)\n      @data[i]=v\n    end\n    # Return true if a value is valid (not nil and not included on missing values)\n    def is_valid?(x)\n      !(x.nil? or @missing_values.include? x)\n    end\n    # Set missing_values.\n    # set_valid_data is called after changes\n    def missing_values=(vals)\n      @missing_values = vals\n      set_valid_data\n    end\n    # Set data considered as \"today\" on data vectors\n    def today_values=(vals)\n      @today_values = vals\n      set_valid_data\n    end\n    # Set level of measurement.\n    def type=(t)\n      @type=t\n      set_scale_data if(t==:scale)\n      set_date_data if (t==:date)\n    end\n    def to_a\n      if @data.is_a? Array\n        @data.dup\n      else\n        @data.to_a\n      end\n    end\n    alias_method :to_ary, :to_a\n\n    # Vector sum.\n    # - If v is a scalar, add this value to all elements\n    # - If v is a Array or a Vector, should be of the same size of this vector\n    #   every item of this vector will be added to the value of the\n    #   item at the same position on the other vector\n    def +(v)\n    _vector_ari(\"+\",v)\n    end\n    # Vector rest.\n    # - If v is a scalar, rest this value to all elements\n    # - If v is a Array or a Vector, should be of the same\n    #   size of this vector\n    #   every item of this vector will be rested to the value of the\n    #   item at the same position on the other vector\n\n    def -(v)\n    _vector_ari(\"-\",v)\n    end\n\n    def *(v)\n      _vector_ari(\"*\",v)\n    end\n    # Reports all values that doesn't comply with a condition.\n    # Returns a hash with the index of data and the invalid data.\n    def verify\n    h={}\n    (0...@data.size).to_a.each{|i|\n      if !(yield @data[i])\n        h[i]=@data[i]\n      end\n    }\n    h\n    end\n    def _vector_ari(method,v) # :nodoc:\n    if(v.is_a? Vector or v.is_a? Array)\n      raise ArgumentError, \"The array/vector parameter (#{v.size}) should be of the same size of the original vector (#{@data.size})\" unless v.size==@data.size\n      sum=[]\n      v.size.times {|i|\n          if((v.is_a? Vector and v.is_valid?(v[i]) and is_valid?(@data[i])) or (v.is_a? Array and !v[i].nil? and !data[i].nil?))\n              sum.push(@data[i].send(method,v[i]))\n          else\n              sum.push(nil)\n          end\n      }\n      Statsample::Vector.new(sum, :scale)\n    elsif(v.respond_to? method )\n      Statsample::Vector.new(\n        @data.collect  {|x|\n          if(!x.nil?)\n            x.send(method,v)\n          else\n            nil\n          end\n        } , :scale)\n    else\n        raise TypeError,\"You should pass a scalar or a array/vector\"\n    end\n\n    end\n    # Return an array with the data splitted by a separator.\n    #   a=Vector.new([\"a,b\",\"c,d\",\"a,b\",\"d\"])\n    #   a.splitted\n    #     =>\n    #   [[\"a\",\"b\"],[\"c\",\"d\"],[\"a\",\"b\"],[\"d\"]]\n    def splitted(sep=Statsample::SPLIT_TOKEN)\n    @data.collect{|x|\n      if x.nil?\n        nil\n      elsif (x.respond_to? :split)\n        x.split(sep)\n      else\n        [x]\n      end\n    }\n    end\n    # Returns a hash of Vectors, defined by the different values\n    # defined on the fields\n    # Example:\n    #\n    #  a=Vector.new([\"a,b\",\"c,d\",\"a,b\"])\n    #  a.split_by_separator\n    #  =>  {\"a\"=>#<Statsample::Type::Nominal:0x7f2dbcc09d88\n    #        @data=[1, 0, 1]>,\n    #       \"b\"=>#<Statsample::Type::Nominal:0x7f2dbcc09c48\n    #        @data=[1, 1, 0]>,\n    #      \"c\"=>#<Statsample::Type::Nominal:0x7f2dbcc09b08\n    #        @data=[0, 1, 1]>}\n    #\n    def split_by_separator(sep=Statsample::SPLIT_TOKEN)\n    split_data=splitted(sep)\n    factors=split_data.flatten.uniq.compact\n    out=factors.inject({}) {|a,x|\n      a[x]=[]\n      a\n    }\n    split_data.each do |r|\n      if r.nil?\n        factors.each do |f|\n          out[f].push(nil)\n        end\n      else\n        factors.each do |f|\n          out[f].push(r.include?(f) ? 1:0)\n        end\n      end\n    end\n    out.inject({}){|s,v|\n      s[v[0]]=Vector.new(v[1],:nominal)\n      s\n    }\n    end\n    def split_by_separator_freq(sep=Statsample::SPLIT_TOKEN)\n      split_by_separator(sep).inject({}) {|a,v|\n        a[v[0]]=v[1].inject {|s,x| s+x.to_i}\n        a\n      }\n    end\n\n    # == Bootstrap\n    # Generate +nr+ resamples (with replacement) of size  +s+\n    # from vector, computing each estimate from +estimators+\n    # over each resample.\n    # +estimators+ could be\n    # a) Hash with variable names as keys and lambdas as  values\n    #   a.bootstrap(:log_s2=>lambda {|v| Math.log(v.variance)},1000)\n    # b) Array with names of method to bootstrap\n    #   a.bootstrap([:mean, :sd],1000)\n    # c) A single method to bootstrap\n    #   a.jacknife(:mean, 1000)\n    # If s is nil, is set to vector size by default.\n    #\n    # Returns a dataset where each vector is an vector\n    # of length +nr+ containing the computed resample estimates.\n    def bootstrap(estimators, nr, s=nil)\n      s||=n\n\n      h_est, es, bss= prepare_bootstrap(estimators)\n\n\n      nr.times do |i|\n        bs=sample_with_replacement(s)\n        es.each do |estimator|\n          # Add bootstrap\n          bss[estimator].push(h_est[estimator].call(bs))\n        end\n      end\n\n      es.each do |est|\n        bss[est]=bss[est].to_scale\n        bss[est].type=:scale\n      end\n      bss.to_dataset\n\n    end\n\n    # == Jacknife\n    # Returns a dataset with jacknife delete-+k+ +estimators+\n    # +estimators+ could be:\n    # a) Hash with variable names as keys and lambdas as values\n    #   a.jacknife(:log_s2=>lambda {|v| Math.log(v.variance)})\n    # b) Array with method names to jacknife\n    #   a.jacknife([:mean, :sd])\n    # c) A single method to jacknife\n    #   a.jacknife(:mean)\n    # +k+ represent the block size for block jacknife. By default\n    # is set to 1, for classic delete-one jacknife.\n    #\n    # Returns a dataset where each vector is an vector\n    # of length +cases+/+k+ containing the computed jacknife estimates.\n    #\n    # == Reference:\n    # * Sawyer, S. (2005). Resampling Data: Using a Statistical Jacknife.\n    def jacknife(estimators, k=1)\n      raise \"n should be divisible by k:#{k}\" unless n%k==0\n\n      nb=(n / k).to_i\n\n\n      h_est, es, ps= prepare_bootstrap(estimators)\n\n      est_n=es.inject({}) {|h,v|\n        h[v]=h_est[v].call(self)\n        h\n      }\n\n\n      nb.times do |i|\n        other=@data_with_nils.dup\n        other.slice!(i*k,k)\n        other=other.to_scale\n        es.each do |estimator|\n          # Add pseudovalue\n          ps[estimator].push( nb * est_n[estimator] - (nb-1) * h_est[estimator].call(other))\n        end\n      end\n\n\n      es.each do |est|\n        ps[est]=ps[est].to_scale\n        ps[est].type=:scale\n      end\n      ps.to_dataset\n    end\n\n\n    # For an array or hash of estimators methods, returns\n    # an array with three elements\n    # 1.- A hash with estimators names as keys and lambdas as values\n    # 2.- An array with estimators names\n    # 3.- A Hash with estimators names as keys and empty arrays as values\n    def prepare_bootstrap(estimators)\n      h_est=estimators\n\n      h_est=[h_est] unless h_est.is_a? Array or h_est.is_a? Hash\n\n      if h_est.is_a? Array\n        h_est=h_est.inject({}) {|h,est|\n          h[est]=lambda {|v| v.send(est)}\n          h\n        }\n      end\n\n      bss=h_est.keys.inject({}) {|h,v| h[v]=[];h}\n\n      [h_est,h_est.keys, bss]\n\n    end\n    private :prepare_bootstrap\n\n    # Returns an random sample of size n, with replacement,\n    # only with valid data.\n    #\n    # In all the trails, every item have the same probability\n    # of been selected.\n    def sample_with_replacement(sample=1)\n      vds=@valid_data.size\n      (0...sample).collect{ @valid_data[rand(vds)] }\n    end\n    # Returns an random sample of size n, without replacement,\n    # only with valid data.\n    #\n    # Every element could only be selected once.\n    #\n    # A sample of the same size of the vector is the vector itself.\n\n    def sample_without_replacement(sample=1)\n      raise ArgumentError, \"Sample size couldn't be greater than n\" if sample>@valid_data.size\n      out=[]\n      size=@valid_data.size\n      while out.size<sample\n        value=rand(size)\n        out.push(value) if !out.include?value\n      end\n      out.collect{|i| @data[i]}\n    end\n    # Retrieves number of cases which comply condition.\n    # If block given, retrieves number of instances where\n    # block returns true.\n    # If other values given, retrieves the frequency for\n    # this value.\n    def count(x=false)\n    if block_given?\n      r=@data.inject(0) {|s, i|\n        r=yield i\n        s+(r ? 1 : 0)\n      }\n      r.nil? ? 0 : r\n    else\n      frequencies[x].nil? ? 0 : frequencies[x]\n    end\n    end\n\n    # Returns the database type for the vector, according to its content\n\n    def db_type(dbs='mysql')\n    # first, detect any character not number\n    if @data.find {|v|  v.to_s=~/\\d{2,2}-\\d{2,2}-\\d{4,4}/} or @data.find {|v|  v.to_s=~/\\d{4,4}-\\d{2,2}-\\d{2,2}/}\n      return \"DATE\"\n    elsif @data.find {|v|  v.to_s=~/[^0-9e.-]/ }\n      return \"VARCHAR (255)\"\n    elsif @data.find {|v| v.to_s=~/\\./}\n      return \"DOUBLE\"\n    else\n      return \"INTEGER\"\n    end\n    end\n    # Return true if all data is Date, \"today\" values or nil\n    def can_be_date?\n    if @data.find {|v|\n    !v.nil? and !v.is_a? Date and !v.is_a? Time and (v.is_a? String and !@today_values.include? v) and (v.is_a? String and !(v=~/\\d{4,4}[-\\/]\\d{1,2}[-\\/]\\d{1,2}/))}\n      false\n    else\n      true\n    end\n    end\n    # Return true if all data is Numeric or nil\n    def can_be_scale?\n      if @data.find {|v| !v.nil? and !v.is_a? Numeric and !@missing_values.include? v}\n        false\n      else\n        true\n      end\n    end\n\n    def to_s\n      sprintf(\"Vector(type:%s, n:%d)[%s]\",@type.to_s,@data.size, @data.collect{|d| d.nil? ? \"nil\":d}.join(\",\"))\n    end\n    # Ugly name. Really, create a Vector for standard 'matrix' package.\n    # <tt>dir</tt> could be :horizontal or :vertical\n    def to_matrix(dir=:horizontal)\n      case dir\n      when :horizontal\n        Matrix[@data]\n      when :vertical\n        Matrix.columns([@data])\n      end\n    end\n    def inspect\n      self.to_s\n    end\n    # Retrieves uniques values for data.\n    def factors\n      if @type==:scale\n        @scale_data.uniq.sort\n      elsif @type==:date\n        @date_data_with_nils.uniq.sort\n      else\n        @valid_data.uniq.sort\n      end\n    end\n    if Statsample::STATSAMPLE__.respond_to?(:frequencies)\n      # Returns a hash with the distribution of frecuencies for\n      # the sample\n      def frequencies\n        Statsample::STATSAMPLE__.frequencies(@valid_data)\n      end\n    else\n      def frequencies #:nodoc:\n        _frequencies\n      end\n    end\n\n\n    def _frequencies #:nodoc:\n      @valid_data.inject(Hash.new) {|a,x|\n        a[x]||=0\n        a[x]=a[x]+1\n        a\n      }\n    end\n\n    # Returns the most frequent item.\n    def mode\n      frequencies.max{|a,b| a[1]<=>b[1]}.first\n    end\n    # The numbers of item with valid data.\n    def n_valid\n      @valid_data.size\n    end\n    # Returns a hash with the distribution of proportions of\n    # the sample.\n    def proportions\n        frequencies.inject({}){|a,v|\n            a[v[0]] = v[1].quo(n_valid)\n            a\n        }\n    end\n    # Proportion of a given value.\n    def proportion(v=1)\n        frequencies[v].quo(@valid_data.size)\n    end\n    def report_building(b)\n      b.section(:name=>name) do |s|\n        s.text _(\"n :%d\") % n\n        s.text _(\"n valid:%d\") % n_valid\n        if @type==:nominal\n          s.text  _(\"factors:%s\") % factors.join(\",\")\n          s.text   _(\"mode: %s\") % mode\n\n          s.table(:name=>_(\"Distribution\")) do |t|\n            frequencies.sort.each do |k,v|\n              key=labels.has_key?(k) ? labels[k]:k\n              t.row [key, v , (\"%0.2f%%\" % (v.quo(n_valid)*100))]\n            end\n          end\n        end\n\n        s.text _(\"median: %s\") % median.to_s if(@type==:ordinal or @type==:scale)\n        if(@type==:scale)\n          s.text _(\"mean: %0.4f\") % mean\n          if sd\n            s.text _(\"std.dev.: %0.4f\") % sd\n            s.text _(\"std.err.: %0.4f\") % se\n            s.text _(\"skew: %0.4f\") % skew\n            s.text _(\"kurtosis: %0.4f\") % kurtosis\n          end\n        end\n      end\n    end\n\n      # Variance of p, according to poblation size\n      def variance_proportion(n_poblation, v=1)\n        Statsample::proportion_variance_sample(self.proportion(v), @valid_data.size, n_poblation)\n      end\n      # Variance of p, according to poblation size\n      def variance_total(n_poblation, v=1)\n        Statsample::total_variance_sample(self.proportion(v), @valid_data.size, n_poblation)\n      end\n      def proportion_confidence_interval_t(n_poblation,margin=0.95,v=1)\n        Statsample::proportion_confidence_interval_t(proportion(v), @valid_data.size, n_poblation, margin)\n      end\n      def proportion_confidence_interval_z(n_poblation,margin=0.95,v=1)\n        Statsample::proportion_confidence_interval_z(proportion(v), @valid_data.size, n_poblation, margin)\n      end\n\n      self.instance_methods.find_all{|met| met=~/_slow$/}.each do |met|\n          met_or=met.gsub(\"_slow\",\"\")\n          if !self.method_defined?(met_or)\n              alias_method met_or, met\n          end\n      end\n\n      ######\n      ### Ordinal Methods\n      ######\n\n      # == Percentil\n      # Returns the value of the percentile q\n      #\n      # Accepts an optional second argument specifying the strategy to interpolate\n      # when the requested percentile lies between two data points a and b\n      # Valid strategies are:\n      # * :midpoint (Default): (a + b) / 2\n      # * :linear : a + (b - a) * d where d is the decimal part of the index between a and b.\n      # This is the NIST recommended method (http://en.wikipedia.org/wiki/Percentile#NIST_method)\n      #\n      def percentil(q, strategy = :midpoint)\n        check_type :ordinal\n        sorted=@valid_data.sort\n\n        case strategy\n        when :midpoint\n          v = (n_valid * q).quo(100)\n          if(v.to_i!=v)\n            sorted[v.to_i]\n          else\n            (sorted[(v-0.5).to_i].to_f + sorted[(v+0.5).to_i]).quo(2)\n          end\n        when :linear\n          index = (q / 100.0) * (n_valid + 1)\n\n          k = index.truncate\n          d = index % 1\n\n          if k == 0\n            sorted[0]\n          elsif k >= sorted.size\n            sorted[-1]\n          else\n            sorted[k - 1] + d * (sorted[k] - sorted[k - 1])\n          end\n        else\n          raise NotImplementedError.new \"Unknown strategy #{strategy.to_s}\"\n        end\n      end\n\n      # Returns a ranked vector.\n      def ranked(type=:ordinal)\n        check_type :ordinal\n        i=0\n        r=frequencies.sort.inject({}){|a,v|\n          a[v[0]]=(i+1 + i+v[1]).quo(2)\n          i+=v[1]\n          a\n        }\n        @data.collect {|c| r[c] }.to_vector(type)\n      end\n      # Return the median (percentil 50)\n      def median\n        check_type :ordinal\n        percentil(50)\n      end\n      # Minimun value\n      def min\n        check_type :ordinal\n        @valid_data.min\n      end\n        # Maximum value\n      def max\n        check_type :ordinal\n        @valid_data.max\n      end\n\n    def set_date_data\n      @date_data_with_nils=@data.collect do|x|\n        if x.is_a? Date\n          x\n        elsif x.is_a? Time\n          Date.new(x.year, x.month, x.day)\n        elsif x.is_a? String and x=~/(\\d{4,4})[-\\/](\\d{1,2})[-\\/](\\d{1,2})/\n          Date.new($1.to_i,$2.to_i,$3.to_i)\n        elsif @today_values.include? x\n          Date.today()\n        elsif @missing_values.include? x or x.nil?\n          nil\n        end\n      end\n    end\n\n    def set_scale_data\n      @scale_data=@valid_data.collect do|x|\n        if x.is_a? Numeric\n          x\n        elsif x.is_a? String and x.to_i==x.to_f\n          x.to_i\n        else\n          x.to_f\n        end\n      end\n    end\n\n    private :set_date_data, :set_scale_data\n\n    # The range of the data (max - min)\n    def range;\n      check_type :scale\n      @scale_data.max - @scale_data.min\n    end\n    # The sum of values for the data\n    def sum\n      check_type :scale\n      @scale_data.inject(0){|a,x|x+a} ;\n    end\n    # The arithmetical mean of data\n    def mean\n      check_type :scale\n      sum.to_f.quo(n_valid)\n    end\n    # Sum of squares for the data around a value.\n    # By default, this value is the  mean\n    #   ss= sum{(xi-m)^2}\n    #\n    def sum_of_squares(m=nil)\n      check_type :scale\n      m||=mean\n      @scale_data.inject(0){|a,x| a+(x-m).square}\n    end\n    # Sum of squared deviation\n    def sum_of_squared_deviation\n      check_type :scale\n      @scale_data.inject(0) {|a,x| x.square+a} - (sum.square.quo(n_valid))\n    end\n\n    # Population variance (denominator N)\n    def variance_population(m=nil)\n      check_type :scale\n      m||=mean\n      squares=@scale_data.inject(0){|a,x| x.square+a}\n      squares.quo(n_valid) - m.square\n    end\n\n\n    # Population Standard deviation (denominator N)\n    def standard_deviation_population(m=nil)\n      check_type :scale\n      Math::sqrt( variance_population(m) )\n    end\n\n    # Population average deviation (denominator N)\n    # author: Al Chou\n\n    def average_deviation_population( m = nil )\n      check_type :scale\n      m ||= mean\n      ( @scale_data.inject( 0 ) { |a, x| ( x - m ).abs + a } ).quo( n_valid )\n    end\n    def median_absolute_deviation\n      med=median\n      recode {|x| (x-med).abs}.median\n    end\n    alias  :mad :median_absolute_deviation\n    # Sample Variance (denominator n-1)\n    def variance_sample(m=nil)\n      check_type :scale\n      m||=mean\n      sum_of_squares(m).quo(n_valid - 1)\n    end\n\n    # Sample Standard deviation (denominator n-1)\n    def standard_deviation_sample(m=nil)\n        check_type :scale\n        m||=mean\n        Math::sqrt(variance_sample(m))\n    end\n    # Skewness of the sample\n    def skew(m=nil)\n        check_type :scale\n        m||=mean\n        th=@scale_data.inject(0){|a,x| a+((x-m)**3)}\n        th.quo((@scale_data.size)*sd(m)**3)\n    end\n    # Kurtosis of the sample\n    def kurtosis(m=nil)\n        check_type :scale\n        m||=mean\n        fo=@scale_data.inject(0){|a,x| a+((x-m)**4)}\n        fo.quo((@scale_data.size)*sd(m)**4)-3\n\n    end\n    # Product of all values on the sample\n    #\n    def product\n        check_type :scale\n        @scale_data.inject(1){|a,x| a*x }\n    end\n\n    # With a fixnum, creates X bins within the range of data\n    # With an Array, each value will be a cut point\n    def histogram(bins=10)\n      check_type :scale\n\n      if bins.is_a? Array\n        #h=Statsample::Histogram.new(self, bins)\n        h=Statsample::Histogram.alloc(bins)\n      else\n        # ugly patch. The upper limit for a bin has the form\n        # x < range\n        #h=Statsample::Histogram.new(self, bins)\n        min,max=Statsample::Util.nice(@valid_data.min,@valid_data.max)\n        # fix last data\n        if max==@valid_data.max\n          max+=1e-10\n        end\n        h=Statsample::Histogram.alloc(bins,[min,max])\n        # Fix last bin\n\n      end\n      h.increment(@valid_data)\n      h\n    end\n\n    # Coefficient of variation\n    # Calculed with the sample standard deviation\n    def coefficient_of_variation\n        check_type :scale\n        standard_deviation_sample.quo(mean)\n    end\n    # Standard error of the distribution mean\n    # Calculated using sd/sqrt(n)\n    def standard_error\n      standard_deviation_sample.quo(Math.sqrt(valid_data.size))\n    end\n    alias :se :standard_error\n\n    alias_method :sdp, :standard_deviation_population\n    alias_method :sds, :standard_deviation_sample\n    alias_method :adp, :average_deviation_population\n    alias_method :cov, :coefficient_of_variation\n    alias_method :variance, :variance_sample\n    alias_method :sd, :standard_deviation_sample\n    alias_method :ss, :sum_of_squares\n    include_aliasing Statsample::Vector::GSL_ if Statsample.has_gsl?\n  end\nend\n"
  },
  {
    "path": "lib/statsample/version.rb",
    "content": "module Statsample\n  VERSION = '1.4.0'\nend\n"
  },
  {
    "path": "lib/statsample.rb",
    "content": "# = statsample.rb - \n# Statsample - Statistic package for Ruby\n# Copyright (C) 2008-2014  Claudio Bustos\n#\n# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n#\n\n\n#$:.unshift(File.dirname(__FILE__))\nrequire 'matrix'\nrequire 'extendmatrix'\nrequire 'distribution'\nrequire 'dirty-memoize'\nrequire 'reportbuilder'\n\n\nclass Numeric\n  def square ; self * self ; end\nend\n\nclass String\n  def is_number?\n    if self =~ /^-?\\d+[,.]?\\d*(e-?\\d+)?$/\n      true\n    else\n      false\n    end\n  end\nend\n\nclass Module\n  def include_aliasing(m, suffix=\"ruby\")\n    m.instance_methods.each do |f|\n      if instance_methods.include? f\n        alias_method(\"#{f}_#{suffix}\",f) \n        remove_method f\n      end\n    end\n    include m\n  end\nend\n\nclass Array\n  # Recode repeated values on an array, adding the number of repetition\n  # at the end\n  # Example:\n  #   a=%w{a b c c d d d e}\n  #   a.recode_repeated\n  #   => [\"a\",\"b\",\"c_1\",\"c_2\",\"d_1\",\"d_2\",\"d_3\",\"e\"]\n  def recode_repeated\n    if self.size!=self.uniq.size\n      # Find repeated\n      repeated=self.inject({}) {|a,v|\n      (a[v].nil? ? a[v]=1 : a[v]+=1); a }.find_all{|k,v| v>1}.collect{|k,v| k}\n      ns=repeated.inject({}) {|a,v| a[v]=0;a}\n      self.collect do |f|\n        if repeated.include? f\n          ns[f]+=1\n          sprintf(\"%s_%d\",f,ns[f])\n        else\n          f\n        end\n      end\n    else\n      self\n    end\n  end\nend\n\ndef create_test(*args,&proc) \n  description=args.shift\n  fields=args\n  [description, fields, Proc.new]\nend\n#--\n# Test extensions\nbegin\n  require 'gettext'\nrescue LoadError\n  def bindtextdomain(d) #:nodoc:\n  d\n  end\n  \n  # Bored module\n  module GetText  #:nodoc:\n    def _(t)  \n        t\n    end\n  end\nend\n# Library for statistical analysis on Ruby\n#\n# * Classes for manipulation and storage of data:\n# * Module Statsample::Bivariate provides covariance and pearson, spearman, point biserial, tau a, tau b, gamma, tetrachoric (see Bivariate::Tetrachoric) and polychoric (see Bivariate::Polychoric) correlations. Include methods to create correlation and covariance matrices\n# * Multiple types of regression on Statsample::Regression\n# * Factorial Analysis algorithms on Statsample::Factor module.\n# * Dominance Analysis. Based on Budescu and Azen papers.link[http://psycnet.apa.org/journals/met/8/2/129/]. \n# * Module Statsample::Codification, to help to codify open questions\n# * Converters to import and export data from databases, csv and excel files.\n# * Module Statsample::Crosstab provides function to create crosstab for categorical data\n# * Reliability analysis provides functions to analyze scales.\n# * Module Statsample::SRS (Simple Random Sampling) provides a lot of functions to estimate standard error for several type of samples\n# * Interfaces to gdchart, gnuplot and SVG::Graph \n#\nmodule Statsample\n  \n  def self.create_has_library(library)\n    define_singleton_method(\"has_#{library}?\") do\n      cv=\"@@#{library}\"\n      if !class_variable_defined? cv\n        begin \n          require library.to_s\n          class_variable_set(cv,true)\n        rescue LoadError\n          class_variable_set(cv,false)\n        end\n      end\n      class_variable_get(cv)\n    end\n  end\n  \n  create_has_library :gsl\n  \n  SPLIT_TOKEN = \",\"\n  autoload(:Analysis, 'statsample/analysis')\n  autoload(:Database, 'statsample/converters')\n  autoload(:Anova, 'statsample/anova')\n  autoload(:CSV, 'statsample/converters')\n  autoload(:PlainText, 'statsample/converters')\n  autoload(:Excel, 'statsample/converters')\n  autoload(:GGobi, 'statsample/converters')\n  autoload(:SPSS, 'statsample/converter/spss')\n  autoload(:Histogram, 'statsample/histogram')\n  autoload(:DominanceAnalysis, 'statsample/dominanceanalysis')\n  autoload(:HtmlReport, 'statsample/htmlreport')\n  autoload(:Mx, 'statsample/converters')\n  autoload(:Resample, 'statsample/resample')\n  autoload(:SRS, 'statsample/srs')\n  autoload(:Codification, 'statsample/codification')\n  autoload(:Reliability, 'statsample/reliability')\n  autoload(:Bivariate, 'statsample/bivariate')\n  autoload(:Multivariate, 'statsample/multivariate')\n  autoload(:Multiset, 'statsample/multiset')\n  autoload(:StratifiedSample, 'statsample/multiset')\n  autoload(:MLE, 'statsample/mle')    \n  autoload(:Regression, 'statsample/regression')\n  autoload(:Test, 'statsample/test')\n  autoload(:Factor, 'statsample/factor')\n  autoload(:Graph, 'statsample/graph')\n  \n  \n  class << self\n    # Load a object saved on a file.\n    def load(filename)\n      if File.exist? filename\n        o=false\n        File.open(filename,\"r\") {|fp| o=Marshal.load(fp) }\n        o\n      else\n        false\n      end\n    end\n    \n    \n    \n    # Create a matrix using vectors as columns.\n    # Use:\n    #\n    #   matrix=Statsample.vector_cols_matrix(v1,v2)\n    def vector_cols_matrix(*vs)\n      # test\n      size=vs[0].size\n      vs.each{|v|\n        raise ArgumentError,\"Arguments should be Vector\" unless v.instance_of? Statsample::Vector\n        raise ArgumentError,\"Vectors size should be the same\" if v.size!=size\n      }\n      Matrix.rows((0...size).to_a.collect() {|i|\n        vs.collect{|v| v[i]}\n      })\n    end\n    # Returns a duplicate of the input vectors, without missing data\n    # for any of the vectors.\n    # \n    #  a=[1,2,3,6,7,nil,3,5].to_scale\n    #  b=[nil,nil,5,6,4,5,10,2].to_scale\n    #  c=[2,4,6,7,4,5,6,7].to_scale\n    #  a2,b2,c2=Statsample.only_valid(a,b,c)\n    #  => [#<Statsample::Scale:0xb748c8c8 @data=[3, 6, 7, 3, 5]>, \n    #        #<Statsample::Scale:0xb748c814 @data=[5, 6, 4, 10, 2]>, \n    #        #<Statsample::Scale:0xb748c760 @data=[6, 7, 4, 6, 7]>]\n    #\n    def only_valid(*vs)\n      i=1\n      h=vs.inject({}) {|a,v| a[\"v#{i}\"]=v;i+=1;a}\n      ds=Statsample::Dataset.new(h).dup_only_valid\n      ds.vectors.values\n    end\n    \n    # Cheap version of #only_valid. \n    # If any vectors have missing_values, return only valid.\n    # If not, return the vectors itself\n    def only_valid_clone(*vs)\n      if vs.any? {|v| v.flawed?}\n        only_valid(*vs)\n      else\n        vs\n      end\n    end\n  end  \n  \n  \n  \n  \n  module Util\n    # Reference: http://www.itl.nist.gov/div898/handbook/eda/section3/normprpl.htm\n    def normal_order_statistic_medians(i,n)\n      if i==1\n        u= 1.0 - normal_order_statistic_medians(n,n)\n      elsif i==n\n        u=0.5**(1 / n.to_f)\n      else\n        u= (i - 0.3175) / (n + 0.365)\n      end\n      u\n    end\n    \n    def self.nice(s,e) # :nodoc:\n      reverse = e<s\n      min = reverse ? e : s\n      max = reverse ? s : e\n      span=max-min\n      return [s, e] if (span == 0 or (span.respond_to? :infinite? and span.infinite?))\n      \n      step=10**((Math::log(span).quo(Math::log(10))).round - 1).to_f  \n      out=[(min.quo(step)).floor * step, (max.quo(step)).ceil * step]\n      out.reverse! if reverse\n      out\n    end\n    \n    \n  end\n  \n  \n  \n  module Writable\n    def save(filename)\n      fp=File.open(filename,\"w\")\n      Marshal.dump(self,fp)\n      fp.close\n    end        \n  end\n  # Provides method summary to generate summaries and include GetText\n  module Summarizable\n    include GetText\n    bindtextdomain(\"statsample\")\n    def summary(method=:to_text)\n      ReportBuilder.new(:no_title=>true).add(self).send(method)\n    end\n  end\n  module STATSAMPLE__ #:nodoc:\n  end\nend\n\n\n\n#--\nbegin \n  require 'statsamplert'\nrescue LoadError\n  module Statsample\n    OPTIMIZED=false\n  end\nend\n\nrequire 'statsample/vector'\nrequire 'statsample/dataset'\nrequire 'statsample/crosstab'\nrequire 'statsample/matrix'\nrequire 'statsample/shorthand'\nrequire 'statsample/version'\n"
  },
  {
    "path": "po/es/statsample.po",
    "content": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: statsample 1.0.1\\n\"\n\"POT-Creation-Date: 2011-03-03 12:03-0300\\n\"\n\"PO-Revision-Date: 2011-03-03 12:05-0300\\n\"\n\"Last-Translator: Claudio Bustos <clbustos@gmail.com>\\n\"\n\"Language-Team: Desarrollador\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Poedit-Language: Spanish\\n\"\n\"X-Poedit-SourceCharset: utf-8\\n\"\n\n#: lib/statsample/test/f.rb:26\nmsgid \"F Test\"\nmsgstr \"Prueba F\"\n\n#: lib/statsample/test/t.rb:82\nmsgid \"T Test\"\nmsgstr \"Prueba T\"\n\n#: lib/statsample/test/t.rb:83\nmsgid \"Estimate\"\nmsgstr \"Estimado\"\n\n#: lib/statsample/test/t.rb:84\nmsgid \"Std.Err.of Estimate\"\nmsgstr \"Err.Est. del Estimado\"\n\n#: lib/statsample/test/t.rb:114\nmsgid \"%s: %0.4f | %s: %0.4f\"\nmsgstr \"%s: %0.4f | %s: %0.4f\"\n\n#: lib/statsample/test/t.rb:120\nmsgid \"t(%d) = %0.4f, p=%0.4f (%s tails)\"\nmsgstr \"t(%d) = %0.4f, p=%0.4f (%s colas)\"\n\n#: lib/statsample/test/t.rb:121\nmsgid \"CI(%d%%): %0.4f - %0.4f\"\nmsgstr \"IC(%d%%): %0.4f - %0.4f\"\n\n#: lib/statsample/test/t.rb:190\nmsgid \"Sample mean: %0.4f | Sample sd: %0.4f | se : %0.4f\"\nmsgstr \"Media de la muestra: %0.4f | DE de la muestra: %0.4f | EE : %0.4f\"\n\n#: lib/statsample/test/t.rb:191\nmsgid \"Population mean: %0.4f\"\nmsgstr \"Promedio población: %0.4f\"\n\n#: lib/statsample/test/t.rb:292\nmsgid \"Mean and standard deviation\"\nmsgstr \"Promedio y desviación estándar\"\n\n#: lib/statsample/test/t.rb:292\n#: lib/statsample/regression/simple.rb:109\n#: lib/statsample/factor/pca.rb:216\n#: lib/statsample/factor/principalaxis.rb:202\nmsgid \"Variable\"\nmsgstr \"Variable\"\n\n#: lib/statsample/test/t.rb:292\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"mean\"\nmsgstr \"promedio\"\n\n#: lib/statsample/test/t.rb:292\nmsgid \"sd\"\nmsgstr \"de\"\n\n#: lib/statsample/test/t.rb:292\n#: lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"n\"\nmsgstr \"n\"\n\n#: lib/statsample/test/t.rb:296\nmsgid \"Levene test for equality of variances\"\nmsgstr \"Test de Levene para igualdad de variancas\"\n\n#: lib/statsample/test/t.rb:298\nmsgid \"T statistics\"\nmsgstr \"Estadístico T\"\n\n#: lib/statsample/test/t.rb:299\nmsgid \"Equal variance\"\nmsgstr \"Varianza Igual\"\n\n#: lib/statsample/test/t.rb:300\nmsgid \"Non equal variance\"\nmsgstr \"Varianza Desigual\"\n\n#: lib/statsample/test/t.rb:302\nmsgid \"Effect size\"\nmsgstr \"Tamaño del efecto\"\n\n#: lib/statsample/test/umannwhitney.rb:140\nmsgid \"Mann-Whitney's U\"\nmsgstr \"U de Mann-Whitney\"\n\n#: lib/statsample/test/umannwhitney.rb:149\nmsgid \"%s results\"\nmsgstr \"resultados de %s\"\n\n#: lib/statsample/test/umannwhitney.rb:150\n#: lib/statsample/test/umannwhitney.rb:151\nmsgid \"Sum of ranks %s\"\nmsgstr \"Suma de rangos %s\"\n\n#: lib/statsample/test/umannwhitney.rb:152\nmsgid \"U Value\"\nmsgstr \"Valor de U\"\n\n#: lib/statsample/test/umannwhitney.rb:153\nmsgid \"Z\"\nmsgstr \"Z\"\n\n#: lib/statsample/test/umannwhitney.rb:155\nmsgid \"Exact p (Dinneen & Blakesley, 1973):\"\nmsgstr \"p exacto (Dinneen & Blakesley, 1973):\"\n\n#: lib/statsample/test/levene.rb:37\nmsgid \"Levene Test\"\nmsgstr \"Test de Levene\"\n\n#: lib/statsample/test/bartlettsphericity.rb:25\nmsgid \"Bartlett's test of sphericity\"\nmsgstr \"Test de esfericidad de Bartlett\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:27\nmsgid \"Multiple Regression:  %s over %s\"\nmsgstr \"Regresión Múltiple: %s sobre %s\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:40\nmsgid \"Regression\"\nmsgstr \"Regresión\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:40\nmsgid \"Error\"\nmsgstr \"Error\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:184\nmsgid \"Engine: %s\"\nmsgstr \"Motor: %s\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:185\nmsgid \"Cases(listwise)=%d(%d)\"\nmsgstr \"Casos (sólo válidos)=%d(%d)\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:186\nmsgid \"R=\"\nmsgstr \"R=\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:187\nmsgid \"R^2=\"\nmsgstr \"R^2=\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:188\nmsgid \"R^2 Adj=\"\nmsgstr \"R^2 Adj=\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:189\nmsgid \"Std.Error R=\"\nmsgstr \"Error estándar R=\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:191\nmsgid \"Equation\"\nmsgstr \"Ecuación\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:197\nmsgid \"Beta coefficients\"\nmsgstr \"Coeficientes beta\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:198\nmsgid \"Constant\"\nmsgstr \"Constante\"\n\n#: lib/statsample/regression/multiple/matrixengine.rb:78\nmsgid \"Multiple reggresion of %s on %s\"\nmsgstr \"Regresión Múltiple de %s en %s\"\n\n#: lib/statsample/regression/simple.rb:88\nmsgid \"Regression of %s over %s\"\nmsgstr \"Regresión de %s sobre %s\"\n\n#: lib/statsample/regression/simple.rb:109\n#: lib/statsample/factor/map.rb:105\n#: lib/statsample/reliability/skillscaleanalysis.rb:92\nmsgid \"Value\"\nmsgstr \"Valor\"\n\n#: lib/statsample/regression/simple.rb:110\nmsgid \"r\"\nmsgstr \"r\"\n\n#: lib/statsample/regression/simple.rb:111\nmsgid \"r^2\"\nmsgstr \"r^2\"\n\n#: lib/statsample/regression/simple.rb:112\nmsgid \"a\"\nmsgstr \"a\"\n\n#: lib/statsample/regression/simple.rb:113\nmsgid \"b\"\nmsgstr \"b\"\n\n#: lib/statsample/regression/simple.rb:114\nmsgid \"s.e\"\nmsgstr \"e.e.\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:115\nmsgid \"Bootstrap dominance Analysis:  %s over %s\"\nmsgstr \"Resultados del Análisis de Dominancia Bootstrap: %s en %s\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:138\nmsgid \"Bootstrap %d of %d\"\nmsgstr \"Bootstrap: %d de %d\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:177\nmsgid \"Sample size: %d\\n\"\nmsgstr \"Tamaño de muestra: %d\\n\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:179\nmsgid \"Linear Regression Engine: %s\"\nmsgstr \"Motor de Regresión Linear: %s\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"pairs\"\nmsgstr \"pares\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"SE(Dij)\"\nmsgstr \"EE(Dij)\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"Reproducibility\"\nmsgstr \"Reproducibilidad\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:182\nmsgid \"Complete dominance\"\nmsgstr \"Dominancia Completa\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:190\nmsgid \"Conditional dominance\"\nmsgstr \"Dominancia Condicional\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:199\nmsgid \"General Dominance\"\nmsgstr \"Dominancia General\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"General averages\"\nmsgstr \"Promedios generales\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"var\"\nmsgstr \"var\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"se\"\nmsgstr \"de\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"p.5\"\nmsgstr \"p.5\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"p.95\"\nmsgstr \"p.95\"\n\n#: lib/statsample/anova/twoway.rb:59\nmsgid \"ANOVA Two-Way\"\nmsgstr \"Anova de dos vías\"\n\n#: lib/statsample/anova/twoway.rb:60\nmsgid \"A\"\nmsgstr \"A\"\n\n#: lib/statsample/anova/twoway.rb:61\nmsgid \"B\"\nmsgstr \"B\"\n\n#: lib/statsample/anova/twoway.rb:62\nmsgid \"Within\"\nmsgstr \"Dentro\"\n\n#: lib/statsample/anova/twoway.rb:98\n#: lib/statsample/anova/oneway.rb:57\nmsgid \"%s Table\"\nmsgstr \"Tabla %s\"\n\n#: lib/statsample/anova/twoway.rb:103\n#: lib/statsample/anova/oneway.rb:60\n#: lib/statsample/crosstab.rb:101\n#: lib/statsample/crosstab.rb:116\n#: lib/statsample/crosstab.rb:151\n#: lib/statsample/crosstab.rb:173\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Total\"\nmsgstr \"Total\"\n\n#: lib/statsample/anova/twoway.rb:172\nmsgid \"Anova Two-Way on %s\"\nmsgstr \"Anova de dos vías en %s\"\n\n#: lib/statsample/anova/twoway.rb:184\n#: lib/statsample/anova/oneway.rb:127\nmsgid \"Test of Homogeneity of variances (Levene)\"\nmsgstr \"Test de homogeneidad de varianza (Levene)\"\n\n#: lib/statsample/anova/twoway.rb:189\n#: lib/statsample/anova/twoway.rb:193\nmsgid \"%s Mean\"\nmsgstr \"Promedio %s\"\n\n#: lib/statsample/anova/oneway.rb:35\nmsgid \"Explained variance\"\nmsgstr \"Varianza explicada\"\n\n#: lib/statsample/anova/oneway.rb:36\nmsgid \"Unexplained variance\"\nmsgstr \"Varianza sin explicar\"\n\n#: lib/statsample/anova/oneway.rb:97\nmsgid \"Anova One-Way\"\nmsgstr \"Anova de una vía\"\n\n#: lib/statsample/anova/oneway.rb:98\nmsgid \"Between Groups\"\nmsgstr \"Entre grupos\"\n\n#: lib/statsample/anova/oneway.rb:99\nmsgid \"Within Groups\"\nmsgstr \"Dentro de grupos\"\n\n#: lib/statsample/anova/oneway.rb:119\nmsgid \"Contrast for %s\"\nmsgstr \"Contraste para %s\"\n\n#: lib/statsample/anova/oneway.rb:163\nmsgid \"Descriptives\"\nmsgstr \"Descriptivos\"\n\n#: lib/statsample/anova/contrast.rb:13\nmsgid \"Psi estimate\"\nmsgstr \"Psi Estimado\"\n\n#: lib/statsample/anova/contrast.rb:14\nmsgid \"Contrast\"\nmsgstr \"Contraste\"\n\n#: lib/statsample/anova/contrast.rb:73\nmsgid \"Contrast:%s\"\nmsgstr \"Contraste: %s\"\n\n#: lib/statsample/graph/scatterplot.rb:72\nmsgid \"Scatterplot (%s - %s)\"\nmsgstr \"Diagrama de dispersión (%s - %s)\"\n\n#: lib/statsample/graph/histogram.rb:50\nmsgid \"Histograma (%s)\"\nmsgstr \"Histograma (%s)\"\n\n#: lib/statsample/graph/boxplot.rb:63\nmsgid \"Boxplot\"\nmsgstr \"Diagrama de caja\"\n\n#: lib/statsample/bivariate/pearson.rb:32\nmsgid \"Correlation (%s - %s)\"\nmsgstr \"Correlación (%s - %s)\"\n\n#: lib/statsample/bivariate/pearson.rb:50\nmsgid \"%s : r=%0.3f (t:%0.3f, g.l.=%d, p:%0.3f / %s tails)\"\nmsgstr \"%s : r=%0.3f (t:%0.3f, g.l.=%d, p:%0.3f / %s colas)\"\n\n#: lib/statsample/factor/parallelanalysis.rb:68\nmsgid \"Parallel Analysis\"\nmsgstr \"Análisis Paralelo\"\n\n#: lib/statsample/factor/parallelanalysis.rb:96\nmsgid \"Bootstrap Method: %s\"\nmsgstr \"Método de Remuestreo: %s\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"Uses SMC: %s\"\nmsgstr \"Usa SMC: %s\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"Yes\"\nmsgstr \"Sí\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"No\"\nmsgstr \"No\"\n\n#: lib/statsample/factor/parallelanalysis.rb:98\nmsgid \"Correlation Matrix type : %s\"\nmsgstr \"Tipo de matriz de correlacion : %s\"\n\n#: lib/statsample/factor/parallelanalysis.rb:99\nmsgid \"Number of variables: %d\"\nmsgstr \"Número de variables: %d\"\n\n#: lib/statsample/factor/parallelanalysis.rb:100\nmsgid \"Number of cases: %d\"\nmsgstr \"Número de casos: %d\"\n\n#: lib/statsample/factor/parallelanalysis.rb:101\nmsgid \"Number of iterations: %d\"\nmsgstr \"Número de iteraciones: %d\"\n\n#: lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\n#: lib/statsample/factor/map.rb:105\nmsgid \"Eigenvalues\"\nmsgstr \"Eigenvalues\"\n\n#: lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"generated eigenvalue\"\nmsgstr \"eigenvalue generado\"\n\n#: lib/statsample/factor/parallelanalysis.rb:110\nmsgid \"Number or factors to preserve: %d\"\nmsgstr \"Número de factores a preservar: %d\"\n\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"data eigenvalue\"\nmsgstr \"eigenvalue de los datos\"\n\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"preserve?\"\nmsgstr \"¿preservar?\"\n\n#: lib/statsample/factor/map.rb:60\nmsgid \"Velicer's MAP\"\nmsgstr \"PPM de Velicer\"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"Velicer's Average Squared Correlations\"\nmsgstr \"Correlaciones Cuadradas Promedio de Velicer \"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"number of components\"\nmsgstr \"número de componentes\"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"average square correlation\"\nmsgstr \"correlación cuadrada promedio\"\n\n#: lib/statsample/factor/map.rb:115\nmsgid \"The smallest average squared correlation is : %0.6f\"\nmsgstr \"La correlación cuadrada promedio más pequeña es: %0.6f\"\n\n#: lib/statsample/factor/map.rb:116\nmsgid \"The number of components is : %d\"\nmsgstr \"El número de componentes es: %d\"\n\n#: lib/statsample/factor/pca.rb:56\nmsgid \"Principal Component Analysis\"\nmsgstr \"Análisis de componentes principales\"\n\n#: lib/statsample/factor/pca.rb:59\n#: lib/statsample/matrix.rb:14\n#: lib/statsample/matrix.rb:81\nmsgid \"VAR_%d\"\nmsgstr \"VAR_%d\"\n\n#: lib/statsample/factor/pca.rb:160\nmsgid \"Component matrix (from covariance)\"\nmsgstr \"Matriz de componentes (desde covarianza)\"\n\n#: lib/statsample/factor/pca.rb:181\nmsgid \"Component matrix\"\nmsgstr \"Matriz de componentes\"\n\n#: lib/statsample/factor/pca.rb:215\n#: lib/statsample/factor/principalaxis.rb:200\nmsgid \"Number of factors: %d\"\nmsgstr \"Número de factores: %d\"\n\n#: lib/statsample/factor/pca.rb:216\n#: lib/statsample/factor/principalaxis.rb:202\nmsgid \"Communalities\"\nmsgstr \"Comunalidades\"\n\n#: lib/statsample/factor/pca.rb:216\n#: lib/statsample/factor/principalaxis.rb:202\nmsgid \"Initial\"\nmsgstr \"Inicial\"\n\n#: lib/statsample/factor/pca.rb:216\n#: lib/statsample/factor/principalaxis.rb:202\nmsgid \"Extraction\"\nmsgstr \"Extracción\"\n\n#: lib/statsample/factor/pca.rb:216\n#: lib/statsample/factor/pca.rb:223\n#: lib/statsample/reliability/skillscaleanalysis.rb:92\nmsgid \"%\"\nmsgstr \"%\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Total Variance Explained\"\nmsgstr \"Varianza Total Explicada\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Component\"\nmsgstr \"Componente\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"E.Total\"\nmsgstr \"E. Total\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Cum. %\"\nmsgstr \"% Acum.\"\n\n#: lib/statsample/factor/pca.rb:227\nmsgid \"Component %d\"\nmsgstr \"Componente %d\"\n\n#: lib/statsample/factor/principalaxis.rb:70\nmsgid \"Variable %d\"\nmsgstr \"Variable %d\"\n\n#: lib/statsample/factor/principalaxis.rb:147\nmsgid \"Factor Matrix\"\nmsgstr \"Matriz de Factores\"\n\n#: lib/statsample/factor/principalaxis.rb:201\nmsgid \"Iterations: %d\"\nmsgstr \"Iteraciones: %d\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"Total Variance\"\nmsgstr \"Varianza Total\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"Factor\"\nmsgstr \"Factor\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E.Total\"\nmsgstr \"E.I. Total\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E. %\"\nmsgstr \"E.I. %\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E.Cum. %\"\nmsgstr \"E.I. Acum. %\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L.Total\"\nmsgstr \"C.C. Total\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L. %\"\nmsgstr \"C.C. %\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L.Cum. %\"\nmsgstr \"C.C. Acum %\"\n\n#: lib/statsample/factor/principalaxis.rb:215\nmsgid \"Factor %d\"\nmsgstr \"Factor %d\"\n\n#: lib/statsample/factor/rotation.rb:35\nmsgid \"%s rotation\"\nmsgstr \"rotación %s\"\n\n#: lib/statsample/factor/rotation.rb:132\nmsgid \"Rotated Component matrix\"\nmsgstr \"Matriz de componentes rotada\"\n\n#: lib/statsample/factor/rotation.rb:149\nmsgid \"Component transformation matrix\"\nmsgstr \"Matriz de transformación de componentes\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:67\nmsgid \"Multiple Scale analysis\"\nmsgstr \"Análisis de múltiples escalas\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:97\nmsgid \"Scale %s\"\nmsgstr \"Escala %s\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:145\nmsgid \"Reliability analysis of scales\"\nmsgstr \"Análisis de confiabilidad de escalas\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:151\nmsgid \"Correlation matrix for %s\"\nmsgstr \"Matriz de correlaciones para %s\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:156\nmsgid \"PCA for %s\"\nmsgstr \"ACP para %s\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:161\nmsgid \"Principal Axis for %s\"\nmsgstr \"Ejes principales para %s\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:167\nmsgid \"Parallel Analysis for %s\"\nmsgstr \"Análisis Paralelo para %s\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:172\nmsgid \"MAP for %s\"\nmsgstr \"MAP para %s\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:21\nmsgid \"Skill Scale Reliability Analysis (%s)\"\nmsgstr \"Análisis de confiabilidad de escalas de habilidad\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:36\nmsgid \"%s(corrected)\"\nmsgstr \"%s(corregido)\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:40\nmsgid \"Corrected dataset from %s\"\nmsgstr \"Grupo de datos corregido desde %s\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:51\nmsgid \"%s (Scale Analysis)\"\nmsgstr \"%s (Análisis de Escala)\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:82\nmsgid \"Problematic Items\"\nmsgstr \"Ítems problemáticos\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:87\nmsgid \"Item: %s\"\nmsgstr \"Ítem: %s\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:88\nmsgid \"Correct answer: %s\"\nmsgstr \"Respuesta correcta: %s\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:89\nmsgid \"p: %0.3f\"\nmsgstr \"p: %0.3f\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:101\nmsgid \"No problematic items\"\nmsgstr \"Sin ítems problemáticos\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:44\nmsgid \"Reliability Analisis\"\nmsgstr \"Análisis de confiabilidad\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:157\nmsgid \"Summary for %s with all items\"\nmsgstr \"Sumario para %s con todos los ítems\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:158\nmsgid \"Items\"\nmsgstr \"Ítems\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:159\n#: lib/statsample/reliability/scaleanalysis.rb:176\nmsgid \"Sum mean\"\nmsgstr \"Promedio de suma\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:160\nmsgid \"S.d. mean\"\nmsgstr \"Promedio de d.e.\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:162\nmsgid \"Deleted items\"\nmsgstr \"Ítems eliminados\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:172\nmsgid \"Summary for %s\"\nmsgstr \"Sumario para %s\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:173\nmsgid \"Valid Items\"\nmsgstr \"Ítems Válidos\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:175\nmsgid \"Valid cases\"\nmsgstr \"casos válidos\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:177\nmsgid \"Sum sd\"\nmsgstr \"d.e. de suma\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:179\nmsgid \"Sum median\"\nmsgstr \"Mediana de suma\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:181\nmsgid \"Item mean\"\nmsgstr \"Promedio de los ítemes\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:182\nmsgid \"Item sd\"\nmsgstr \"DE de Items\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:184\nmsgid \"Skewness\"\nmsgstr \"Sesgo\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:185\nmsgid \"Kurtosis\"\nmsgstr \"Curtosis\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:187\nmsgid \"Cronbach's alpha\"\nmsgstr \"Alfa de Cronbach\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:188\nmsgid \"Standarized Cronbach's alpha\"\nmsgstr \"Alfa de Cronbach estandarizado\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:189\nmsgid \"Mean rpb\"\nmsgstr \"rbp medio\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:191\nmsgid \"Variances mean\"\nmsgstr \"Promedio de las varianzas\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:192\nmsgid \"Covariances mean\"\nmsgstr \"Promedio de las covarianzas\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:196\nmsgid \"Items for obtain alpha(0.8) : %d\"\nmsgstr \"Ítems para obtener alfa(0,8): %d\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:197\nmsgid \"Items for obtain alpha(0.9) : %d\"\nmsgstr \"Ítems para obtener alfa(0,9): %d\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:205\nmsgid \"Items report for %s\"\nmsgstr \"Reporte de ítems para %s\"\n\n#: lib/statsample/reliability/icc.rb:114\nmsgid \"Shrout & Fleiss ICC(1,1)\"\nmsgstr \"Shrout & Fleiss ICC(1,1)\"\n\n#: lib/statsample/reliability/icc.rb:119\nmsgid \"Shrout & Fleiss ICC(2,1)\"\nmsgstr \"Shrout & Fleiss ICC(2,1)\"\n\n#: lib/statsample/reliability/icc.rb:125\nmsgid \"Shrout & Fleiss ICC(3,1)\"\nmsgstr \"Shrout & Fleiss ICC(3,1)\"\n\n#: lib/statsample/reliability/icc.rb:132\nmsgid \"Shrout & Fleiss ICC(1,k)\"\nmsgstr \"Shrout & Fleiss ICC(1,k)\"\n\n#: lib/statsample/reliability/icc.rb:138\nmsgid \"Shrout & Fleiss ICC(2,k)\"\nmsgstr \"Shrout & Fleiss ICC(2,k)\"\n\n#: lib/statsample/reliability/icc.rb:145\nmsgid \"Shrout & Fleiss ICC(3,k)\"\nmsgstr \"Shrout & Fleiss ICC(3,k)\"\n\n#: lib/statsample/reliability/icc.rb:153\nmsgid \"McGraw & Wong ICC(1)\"\nmsgstr \"McGraw & Wong ICC(1)\"\n\n#: lib/statsample/reliability/icc.rb:159\nmsgid \"McGraw & Wong ICC(K)\"\nmsgstr \"McGraw & Wong ICC(K)\"\n\n#: lib/statsample/reliability/icc.rb:165\nmsgid \"McGraw & Wong ICC(C,1)\"\nmsgstr \"McGraw & Wong ICC(C,1)\"\n\n#: lib/statsample/reliability/icc.rb:172\nmsgid \"McGraw & Wong ICC(C,K)\"\nmsgstr \"McGraw & Wong ICC(C,K)\"\n\n#: lib/statsample/reliability/icc.rb:179\nmsgid \"McGraw & Wong ICC(A,1)\"\nmsgstr \"McGraw & Wong ICC(A,1)\"\n\n#: lib/statsample/reliability/icc.rb:186\nmsgid \"McGraw & Wong ICC(A,K)\"\nmsgstr \"McGraw & Wong ICC(A,K)\"\n\n#: lib/statsample/reliability/icc.rb:408\nmsgid \"ICC: %0.4f\"\nmsgstr \"CIC: %0.3f\"\n\n#: lib/statsample/reliability/icc.rb:410\nmsgid \"CI (%0.2f): [%0.4f - %0.4f]\"\nmsgstr \"IC (%0.2f): [%0.4f - %0.4f]\"\n\n#: lib/statsample/crosstab.rb:22\nmsgid \"Crosstab %s - %s\"\nmsgstr \"Tabulación cruzada %s - %s\"\n\n#: lib/statsample/crosstab.rb:98\nmsgid \"Rows: %s\"\nmsgstr \"Filas: %s\"\n\n#: lib/statsample/crosstab.rb:99\nmsgid \"Columns: %s\"\nmsgstr \"Columnas: %s\"\n\n#: lib/statsample/crosstab.rb:101\nmsgid \"Raw\"\nmsgstr \"En Bruto\"\n\n#: lib/statsample/crosstab.rb:146\nmsgid \"% Row\"\nmsgstr \"% Fila\"\n\n#: lib/statsample/crosstab.rb:147\nmsgid \"% Column\"\nmsgstr \"% Columna\"\n\n#: lib/statsample/crosstab.rb:148\nmsgid \"% Total\"\nmsgstr \"% Total\"\n\n#: lib/statsample/dominanceanalysis.rb:121\nmsgid \"Dominance Analysis:  %s over %s\"\nmsgstr \"Análisis de dominancia: %s en %s\"\n\n#: lib/statsample/dominanceanalysis.rb:315\nmsgid \"sign\"\nmsgstr \"signo\"\n\n#: lib/statsample/dominanceanalysis.rb:317\nmsgid \"Dominance Analysis result\"\nmsgstr \"Resultados del análisis de dominancia\"\n\n#: lib/statsample/dominanceanalysis.rb:318\nmsgid \"Model 0\"\nmsgstr \"Modelo 0\"\n\n#: lib/statsample/dominanceanalysis.rb:333\nmsgid \"k=%d Average\"\nmsgstr \"k=%d Promedio\"\n\n#: lib/statsample/dominanceanalysis.rb:345\nmsgid \"Overall averages\"\nmsgstr \"Promedios generales\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Pairwise dominance\"\nmsgstr \"Dominancia en pares\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Pairs\"\nmsgstr \"Pares\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Conditional\"\nmsgstr \"Condicional\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"General\"\nmsgstr \"General\"\n\n#: lib/statsample/matrix.rb:181\nmsgid \"X%d\"\nmsgstr \"X%d\"\n\n#: lib/statsample/matrix.rb:184\nmsgid \"Y%d\"\nmsgstr \"Y%d\"\n\n#: lib/statsample/matrix.rb:196\nmsgid \"Matrix %d\"\nmsgstr \"Matriz %d\"\n\n#: lib/statsample/matrix.rb:255\nmsgid \"Covariate matrix %d\"\nmsgstr \"Matriz de Covarianza %d\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \"Correlation\"\nmsgstr \"Correlación\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \"Covariance\"\nmsgstr \"Covarianza\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \" Matrix\"\nmsgstr \"Matriz\"\n\n#: lib/statsample/vector.rb:177\nmsgid \"%s(standarized)\"\nmsgstr \"%s(estandarizado)\"\n\n#: lib/statsample/vector.rb:189\nmsgid \"%s(centered)\"\nmsgstr \"%s(centrado)\"\n\n#: lib/statsample/vector.rb:201\nmsgid \"%s(percentil)\"\nmsgstr \"%s(percentil)\"\n\n#: lib/statsample/vector.rb:778\nmsgid \"n :%d\"\nmsgstr \"n: %s\"\n\n#: lib/statsample/vector.rb:779\nmsgid \"n valid:%d\"\nmsgstr \"n válido: %d\"\n\n#: lib/statsample/vector.rb:780\nmsgid \"factors:%s\"\nmsgstr \"factores:%s\"\n\n#: lib/statsample/vector.rb:781\nmsgid \"mode: %s\"\nmsgstr \"modo: %s\"\n\n#: lib/statsample/vector.rb:782\nmsgid \"Distribution\"\nmsgstr \"Distribución\"\n\n#: lib/statsample/vector.rb:788\nmsgid \"median: %s\"\nmsgstr \"Mediana: %s\"\n\n#: lib/statsample/vector.rb:790\nmsgid \"mean: %0.4f\"\nmsgstr \"promedio: %0.3f\"\n\n#: lib/statsample/vector.rb:791\nmsgid \"sd: %0.4f\"\nmsgstr \"d.e.: %0.3f\"\n\n#: lib/statsample/dataset.rb:161\nmsgid \"Dataset %d\"\nmsgstr \"Dataset %d\"\n\n#: lib/statsample/dataset.rb:457\nmsgid \"Sum from %s\"\nmsgstr \"Suma para %s\"\n\n#: lib/statsample/dataset.rb:510\nmsgid \"Means from %s\"\nmsgstr \"Media desde %s\"\n\n#: lib/statsample/dataset.rb:734\nmsgid \"%s(filtered)\"\nmsgstr \"%s(filtrado)\"\n\n#: lib/statsample/dataset.rb:956\nmsgid \"Cases: %d\"\nmsgstr \"Casos: %s\"\n\n"
  },
  {
    "path": "po/statsample.pot",
    "content": "# Statsample po template.\n# Copyright (C) 2009-2009 Claudio Bustos\n# This file is distributed under the same license as the Statsample package.\n# Claudio Bustos <clbustos_AT_gmail.com>\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: statsample 1.0.1\\n\"\n\"POT-Creation-Date: 2011-03-03 12:03-0300\\n\"\n\"PO-Revision-Date: 2009-08-04 15:36-0400\\n\"\n\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n\n#: lib/statsample/test/f.rb:26\nmsgid \"F Test\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:82\nmsgid \"T Test\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:83\nmsgid \"Estimate\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:84\nmsgid \"Std.Err.of Estimate\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:114\nmsgid \"%s: %0.4f | %s: %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:120\nmsgid \"t(%d) = %0.4f, p=%0.4f (%s tails)\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:121\nmsgid \"CI(%d%%): %0.4f - %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:190\nmsgid \"Sample mean: %0.4f | Sample sd: %0.4f | se : %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:191\nmsgid \"Population mean: %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:292\nmsgid \"Mean and standard deviation\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:292 lib/statsample/regression/simple.rb:109\n#: lib/statsample/factor/pca.rb:216 lib/statsample/factor/principalaxis.rb:202\nmsgid \"Variable\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:292\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"mean\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:292\nmsgid \"sd\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:292 lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"n\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:296\nmsgid \"Levene test for equality of variances\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:298\nmsgid \"T statistics\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:299\nmsgid \"Equal variance\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:300\nmsgid \"Non equal variance\"\nmsgstr \"\"\n\n#: lib/statsample/test/t.rb:302\nmsgid \"Effect size\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:140\nmsgid \"Mann-Whitney's U\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:149\nmsgid \"%s results\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:150\n#: lib/statsample/test/umannwhitney.rb:151\nmsgid \"Sum of ranks %s\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:152\nmsgid \"U Value\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:153\nmsgid \"Z\"\nmsgstr \"\"\n\n#: lib/statsample/test/umannwhitney.rb:155\nmsgid \"Exact p (Dinneen & Blakesley, 1973):\"\nmsgstr \"\"\n\n#: lib/statsample/test/levene.rb:37\nmsgid \"Levene Test\"\nmsgstr \"\"\n\n#: lib/statsample/test/bartlettsphericity.rb:25\nmsgid \"Bartlett's test of sphericity\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:27\nmsgid \"Multiple Regression:  %s over %s\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:40\nmsgid \"Regression\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:40\nmsgid \"Error\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:184\nmsgid \"Engine: %s\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:185\nmsgid \"Cases(listwise)=%d(%d)\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:186\nmsgid \"R=\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:187\nmsgid \"R^2=\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:188\nmsgid \"R^2 Adj=\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:189\nmsgid \"Std.Error R=\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:191\nmsgid \"Equation\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:197\nmsgid \"Beta coefficients\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/baseengine.rb:198\nmsgid \"Constant\"\nmsgstr \"\"\n\n#: lib/statsample/regression/multiple/matrixengine.rb:78\nmsgid \"Multiple reggresion of %s on %s\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:88\nmsgid \"Regression of %s over %s\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:109 lib/statsample/factor/map.rb:105\n#: lib/statsample/reliability/skillscaleanalysis.rb:92\nmsgid \"Value\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:110\nmsgid \"r\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:111\nmsgid \"r^2\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:112\nmsgid \"a\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:113\nmsgid \"b\"\nmsgstr \"\"\n\n#: lib/statsample/regression/simple.rb:114\nmsgid \"s.e\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:115\nmsgid \"Bootstrap dominance Analysis:  %s over %s\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:138\nmsgid \"Bootstrap %d of %d\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:177\nmsgid \"Sample size: %d\\n\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:179\nmsgid \"Linear Regression Engine: %s\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"pairs\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"SE(Dij)\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:181\nmsgid \"Reproducibility\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:182\nmsgid \"Complete dominance\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:190\nmsgid \"Conditional dominance\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:199\nmsgid \"General Dominance\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"General averages\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"var\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"se\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"p.5\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis/bootstrap.rb:208\nmsgid \"p.95\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:59\nmsgid \"ANOVA Two-Way\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:60\nmsgid \"A\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:61\nmsgid \"B\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:62\nmsgid \"Within\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:98 lib/statsample/anova/oneway.rb:57\nmsgid \"%s Table\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:103 lib/statsample/anova/oneway.rb:60\n#: lib/statsample/crosstab.rb:101 lib/statsample/crosstab.rb:116\n#: lib/statsample/crosstab.rb:151 lib/statsample/crosstab.rb:173\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Total\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:172\nmsgid \"Anova Two-Way on %s\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:184 lib/statsample/anova/oneway.rb:127\nmsgid \"Test of Homogeneity of variances (Levene)\"\nmsgstr \"\"\n\n#: lib/statsample/anova/twoway.rb:189 lib/statsample/anova/twoway.rb:193\nmsgid \"%s Mean\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:35\nmsgid \"Explained variance\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:36\nmsgid \"Unexplained variance\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:97\nmsgid \"Anova One-Way\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:98\nmsgid \"Between Groups\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:99\nmsgid \"Within Groups\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:119\nmsgid \"Contrast for %s\"\nmsgstr \"\"\n\n#: lib/statsample/anova/oneway.rb:163\nmsgid \"Descriptives\"\nmsgstr \"\"\n\n#: lib/statsample/anova/contrast.rb:13\nmsgid \"Psi estimate\"\nmsgstr \"\"\n\n#: lib/statsample/anova/contrast.rb:14\nmsgid \"Contrast\"\nmsgstr \"\"\n\n#: lib/statsample/anova/contrast.rb:73\nmsgid \"Contrast:%s\"\nmsgstr \"\"\n\n#: lib/statsample/graph/scatterplot.rb:72\nmsgid \"Scatterplot (%s - %s)\"\nmsgstr \"\"\n\n#: lib/statsample/graph/histogram.rb:50\nmsgid \"Histograma (%s)\"\nmsgstr \"\"\n\n#: lib/statsample/graph/boxplot.rb:63\nmsgid \"Boxplot\"\nmsgstr \"\"\n\n#: lib/statsample/bivariate/pearson.rb:32\nmsgid \"Correlation (%s - %s)\"\nmsgstr \"\"\n\n#: lib/statsample/bivariate/pearson.rb:50\nmsgid \"%s : r=%0.3f (t:%0.3f, g.l.=%d, p:%0.3f / %s tails)\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:68\nmsgid \"Parallel Analysis\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:96\nmsgid \"Bootstrap Method: %s\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"Uses SMC: %s\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"Yes\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:97\nmsgid \"No\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:98\nmsgid \"Correlation Matrix type : %s\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:99\nmsgid \"Number of variables: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:100\nmsgid \"Number of cases: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:101\nmsgid \"Number of iterations: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\n#: lib/statsample/factor/map.rb:105\nmsgid \"Eigenvalues\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:103\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"generated eigenvalue\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:110\nmsgid \"Number or factors to preserve: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"data eigenvalue\"\nmsgstr \"\"\n\n#: lib/statsample/factor/parallelanalysis.rb:111\nmsgid \"preserve?\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:60\nmsgid \"Velicer's MAP\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"Velicer's Average Squared Correlations\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"number of components\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:110\nmsgid \"average square correlation\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:115\nmsgid \"The smallest average squared correlation is : %0.6f\"\nmsgstr \"\"\n\n#: lib/statsample/factor/map.rb:116\nmsgid \"The number of components is : %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:56\nmsgid \"Principal Component Analysis\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:59 lib/statsample/matrix.rb:14\n#: lib/statsample/matrix.rb:81\nmsgid \"VAR_%d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:160\nmsgid \"Component matrix (from covariance)\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:181\nmsgid \"Component matrix\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:215 lib/statsample/factor/principalaxis.rb:200\nmsgid \"Number of factors: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:216 lib/statsample/factor/principalaxis.rb:202\nmsgid \"Communalities\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:216 lib/statsample/factor/principalaxis.rb:202\nmsgid \"Initial\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:216 lib/statsample/factor/principalaxis.rb:202\nmsgid \"Extraction\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:216 lib/statsample/factor/pca.rb:223\n#: lib/statsample/reliability/skillscaleanalysis.rb:92\nmsgid \"%\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Total Variance Explained\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Component\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"E.Total\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:223\nmsgid \"Cum. %\"\nmsgstr \"\"\n\n#: lib/statsample/factor/pca.rb:227\nmsgid \"Component %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:70\nmsgid \"Variable %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:147\nmsgid \"Factor Matrix\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:201\nmsgid \"Iterations: %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"Total Variance\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"Factor\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E.Total\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E. %\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:207\nmsgid \"I.E.Cum. %\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L.Total\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L. %\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:208\nmsgid \"S.L.Cum. %\"\nmsgstr \"\"\n\n#: lib/statsample/factor/principalaxis.rb:215\nmsgid \"Factor %d\"\nmsgstr \"\"\n\n#: lib/statsample/factor/rotation.rb:35\nmsgid \"%s rotation\"\nmsgstr \"\"\n\n#: lib/statsample/factor/rotation.rb:132\nmsgid \"Rotated Component matrix\"\nmsgstr \"\"\n\n#: lib/statsample/factor/rotation.rb:149\nmsgid \"Component transformation matrix\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:67\nmsgid \"Multiple Scale analysis\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:97\nmsgid \"Scale %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:145\nmsgid \"Reliability analysis of scales\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:151\nmsgid \"Correlation matrix for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:156\nmsgid \"PCA for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:161\nmsgid \"Principal Axis for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:167\nmsgid \"Parallel Analysis for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/multiscaleanalysis.rb:172\nmsgid \"MAP for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:21\nmsgid \"Skill Scale Reliability Analysis (%s)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:36\nmsgid \"%s(corrected)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:40\nmsgid \"Corrected dataset from %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:51\nmsgid \"%s (Scale Analysis)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:82\nmsgid \"Problematic Items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:87\nmsgid \"Item: %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:88\nmsgid \"Correct answer: %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:89\nmsgid \"p: %0.3f\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/skillscaleanalysis.rb:101\nmsgid \"No problematic items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:44\nmsgid \"Reliability Analisis\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:157\nmsgid \"Summary for %s with all items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:158\nmsgid \"Items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:159\n#: lib/statsample/reliability/scaleanalysis.rb:176\nmsgid \"Sum mean\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:160\nmsgid \"S.d. mean\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:162\nmsgid \"Deleted items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:172\nmsgid \"Summary for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:173\nmsgid \"Valid Items\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:175\nmsgid \"Valid cases\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:177\nmsgid \"Sum sd\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:179\nmsgid \"Sum median\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:181\nmsgid \"Item mean\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:182\nmsgid \"Item sd\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:184\nmsgid \"Skewness\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:185\nmsgid \"Kurtosis\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:187\nmsgid \"Cronbach's alpha\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:188\nmsgid \"Standarized Cronbach's alpha\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:189\nmsgid \"Mean rpb\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:191\nmsgid \"Variances mean\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:192\nmsgid \"Covariances mean\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:196\nmsgid \"Items for obtain alpha(0.8) : %d\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:197\nmsgid \"Items for obtain alpha(0.9) : %d\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/scaleanalysis.rb:205\nmsgid \"Items report for %s\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:114\nmsgid \"Shrout & Fleiss ICC(1,1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:119\nmsgid \"Shrout & Fleiss ICC(2,1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:125\nmsgid \"Shrout & Fleiss ICC(3,1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:132\nmsgid \"Shrout & Fleiss ICC(1,k)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:138\nmsgid \"Shrout & Fleiss ICC(2,k)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:145\nmsgid \"Shrout & Fleiss ICC(3,k)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:153\nmsgid \"McGraw & Wong ICC(1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:159\nmsgid \"McGraw & Wong ICC(K)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:165\nmsgid \"McGraw & Wong ICC(C,1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:172\nmsgid \"McGraw & Wong ICC(C,K)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:179\nmsgid \"McGraw & Wong ICC(A,1)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:186\nmsgid \"McGraw & Wong ICC(A,K)\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:408\nmsgid \"ICC: %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/reliability/icc.rb:410\nmsgid \"CI (%0.2f): [%0.4f - %0.4f]\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:22\nmsgid \"Crosstab %s - %s\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:98\nmsgid \"Rows: %s\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:99\nmsgid \"Columns: %s\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:101\nmsgid \"Raw\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:146\nmsgid \"% Row\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:147\nmsgid \"% Column\"\nmsgstr \"\"\n\n#: lib/statsample/crosstab.rb:148\nmsgid \"% Total\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:121\nmsgid \"Dominance Analysis:  %s over %s\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:315\nmsgid \"sign\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:317\nmsgid \"Dominance Analysis result\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:318\nmsgid \"Model 0\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:333\nmsgid \"k=%d Average\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:345\nmsgid \"Overall averages\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Pairwise dominance\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Pairs\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"Conditional\"\nmsgstr \"\"\n\n#: lib/statsample/dominanceanalysis.rb:354\nmsgid \"General\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:181\nmsgid \"X%d\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:184\nmsgid \"Y%d\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:196\nmsgid \"Matrix %d\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:255\nmsgid \"Covariate matrix %d\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \"Correlation\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \"Covariance\"\nmsgstr \"\"\n\n#: lib/statsample/matrix.rb:303\nmsgid \" Matrix\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:177\nmsgid \"%s(standarized)\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:189\nmsgid \"%s(centered)\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:201\nmsgid \"%s(percentil)\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:778\nmsgid \"n :%d\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:779\nmsgid \"n valid:%d\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:780\nmsgid \"factors:%s\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:781\nmsgid \"mode: %s\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:782\nmsgid \"Distribution\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:788\nmsgid \"median: %s\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:790\nmsgid \"mean: %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/vector.rb:791\nmsgid \"sd: %0.4f\"\nmsgstr \"\"\n\n#: lib/statsample/dataset.rb:161\nmsgid \"Dataset %d\"\nmsgstr \"\"\n\n#: lib/statsample/dataset.rb:457\nmsgid \"Sum from %s\"\nmsgstr \"\"\n\n#: lib/statsample/dataset.rb:510\nmsgid \"Means from %s\"\nmsgstr \"\"\n\n#: lib/statsample/dataset.rb:734\nmsgid \"%s(filtered)\"\nmsgstr \"\"\n\n#: lib/statsample/dataset.rb:956\nmsgid \"Cases: %d\"\nmsgstr \"\"\n"
  },
  {
    "path": "references.txt",
    "content": "References\n* Azen, R. & Budescu, D.V. (2003). The dominance analysis approach for comparing predictors in multiple regression. <em>Psychological Methods, 8</em>(2), 129-148.\n* Azen, R. & Budescu, D.V. (2006). Comparing predictors in Multivariate Regression Models: An extension of Dominance Analysis. <em>Journal of Educational and Behavioral Statistics, 31</em>(2), 157-180.\n* Budescu, D. V. (1993). Dominance analysis: a new approach to the problem of relative importance of predictors in multiple regression. <em>Psychological Bulletin, 114</em>, 542-551.\n* Cochran, W.(1972). Sampling Techniques [spanish edition].\n* Cohen et al. (2003). Applied Multiple Reggression / Correlation Analysis for the Behavioral Sciences\n* Dinneen, L., & Blakesley, B. (1973). Algorithm AS 62: A Generator for the Sampling Distribution of the Mann- Whitney U Statistic. <em>Journal of the Royal Statistical Society, 22</em>(2), 269-273\n* Dziuban, C., & Shirkey E. (1974). When is a correlation matrix appropriate for factor analysis? Some decision rules. Psychological Bulletin, 81(6), 358-361.\n* Hayton, J., Allen, D. & Scarpello, V.(2004). Factor Retention Decisions in Exploratory Factor Analysis: a Tutorial on Parallel Analysis. <i>Organizational Research Methods, 7</i> (2), 191-205.\n* Härdle, W. & Simar, L. (2003). Applied Multivariate Statistical Analysis. Springer\n* Leach, L. & Henson, R. (2007). The Use and Impact of Adjusted R2 Effects in Published Regression Research. Multiple Linear Regression Viewpoints, 33(1), 1-11.\n* Lin, J. (2007). VARIMAX_K58 [Source code]. [http://www.johnny-lin.com/idl_code/varimax_k58.pro]\n* Liu, O., & Rijmen, F. (2008). A modified procedure for parallel analysis of ordered categorical data. Behavior Research Methods, 40(2), 556-562.\n* McGraw, K. & Wong, S.P. (1996). Forming Inferences About Some Intraclass Correlation Coefficients. Psychological methods, 1(1), 30-46.\n* O'Connor, B. (2000). SPSS and SAS programs for determining the number of components using parallel analysis and Velicer's MAP test. Behavior Research Methods, Instruments, & Computers, 32(3), 396-402.\n* SPSS Manual\n* Sawyer, S. (2005). Resampling Data: Using a Statistical Jacknife.\n* Shrout,P. & Fleiss, J. (1979). Intraclass Correlation: Uses in assessing rater reliability. Psychological Bulletin, 86(2), 420-428\n* Smith, L. (2002). A tutorial on Principal Component Analysis. Available on http://courses.eas.ualberta.ca/eas570/pca_tutorial.pdf \n* http://en.wikipedia.org/wiki/Welch-Satterthwaite_equation\n* http://europe.isixsigma.com/library/content/c080806a.asp\n* http://stattrek.com/Lesson6/SRS.aspx\n* http://talkstats.com/showthread.php?t=5056\n* http://www.gnu.org/software/gsl/manual/html_node/The-histogram-struct.html\n"
  },
  {
    "path": "setup.rb",
    "content": "#\n# setup.rb\n#\n# Copyright (c) 2000-2005 Minero Aoki\n#\n# This program is free software.\n# You can distribute/modify this program under the terms of\n# the GNU LGPL, Lesser General Public License version 2.1.\n#\n\nunless Enumerable.method_defined?(:map)   # Ruby 1.4.6\n  module Enumerable\n    alias map collect\n  end\nend\n\nunless File.respond_to?(:read)   # Ruby 1.6\n  def File.read(fname)\n    open(fname) {|f|\n      return f.read\n    }\n  end\nend\n\nunless Errno.const_defined?(:ENOTEMPTY)   # Windows?\n  module Errno\n    class ENOTEMPTY\n      # We do not raise this exception, implementation is not needed.\n    end\n  end\nend\n\ndef File.binread(fname)\n  open(fname, 'rb') {|f|\n    return f.read\n  }\nend\n\n# for corrupted Windows' stat(2)\ndef File.dir?(path)\n  File.directory?((path[-1,1] == '/') ? path : path + '/')\nend\n\n\nclass ConfigTable\n\n  include Enumerable\n\n  def initialize(rbconfig)\n    @rbconfig = rbconfig\n    @items = []\n    @table = {}\n    # options\n    @install_prefix = nil\n    @config_opt = nil\n    @verbose = true\n    @no_harm = false\n  end\n\n  attr_accessor :install_prefix\n  attr_accessor :config_opt\n\n  attr_writer :verbose\n\n  def verbose?\n    @verbose\n  end\n\n  attr_writer :no_harm\n\n  def no_harm?\n    @no_harm\n  end\n\n  def [](key)\n    lookup(key).resolve(self)\n  end\n\n  def []=(key, val)\n    lookup(key).set val\n  end\n\n  def names\n    @items.map {|i| i.name }\n  end\n\n  def each(&block)\n    @items.each(&block)\n  end\n\n  def key?(name)\n    @table.key?(name)\n  end\n\n  def lookup(name)\n    @table[name] or setup_rb_error \"no such config item: #{name}\"\n  end\n\n  def add(item)\n    @items.push item\n    @table[item.name] = item\n  end\n\n  def remove(name)\n    item = lookup(name)\n    @items.delete_if {|i| i.name == name }\n    @table.delete_if {|name, i| i.name == name }\n    item\n  end\n\n  def load_script(path, inst = nil)\n    if File.file?(path)\n      MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path\n    end\n  end\n\n  def savefile\n    '.config'\n  end\n\n  def load_savefile\n    begin\n      File.foreach(savefile()) do |line|\n        k, v = *line.split(/=/, 2)\n        self[k] = v.strip\n      end\n    rescue Errno::ENOENT\n      setup_rb_error $!.message + \"\\n#{File.basename($0)} config first\"\n    end\n  end\n\n  def save\n    @items.each {|i| i.value }\n    File.open(savefile(), 'w') {|f|\n      @items.each do |i|\n        f.printf \"%s=%s\\n\", i.name, i.value if i.value? and i.value\n      end\n    }\n  end\n\n  def load_standard_entries\n    standard_entries(@rbconfig).each do |ent|\n      add ent\n    end\n  end\n\n  def standard_entries(rbconfig)\n    c = rbconfig\n\n    rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])\n\n    major = c['MAJOR'].to_i\n    minor = c['MINOR'].to_i\n    teeny = c['TEENY'].to_i\n    version = \"#{major}.#{minor}\"\n\n    # ruby ver. >= 1.4.4?\n    newpath_p = ((major >= 2) or\n                 ((major == 1) and\n                  ((minor >= 5) or\n                   ((minor == 4) and (teeny >= 4)))))\n\n    if c['rubylibdir']\n      # V > 1.6.3\n      libruby         = \"#{c['prefix']}/lib/ruby\"\n      librubyver      = c['rubylibdir']\n      librubyverarch  = c['archdir']\n      siteruby        = c['sitedir']\n      siterubyver     = c['sitelibdir']\n      siterubyverarch = c['sitearchdir']\n    elsif newpath_p\n      # 1.4.4 <= V <= 1.6.3\n      libruby         = \"#{c['prefix']}/lib/ruby\"\n      librubyver      = \"#{c['prefix']}/lib/ruby/#{version}\"\n      librubyverarch  = \"#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}\"\n      siteruby        = c['sitedir']\n      siterubyver     = \"$siteruby/#{version}\"\n      siterubyverarch = \"$siterubyver/#{c['arch']}\"\n    else\n      # V < 1.4.4\n      libruby         = \"#{c['prefix']}/lib/ruby\"\n      librubyver      = \"#{c['prefix']}/lib/ruby/#{version}\"\n      librubyverarch  = \"#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}\"\n      siteruby        = \"#{c['prefix']}/lib/ruby/#{version}/site_ruby\"\n      siterubyver     = siteruby\n      siterubyverarch = \"$siterubyver/#{c['arch']}\"\n    end\n    parameterize = lambda {|path|\n      path.sub(/\\A#{Regexp.quote(c['prefix'])}/, '$prefix')\n    }\n\n    if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }\n      makeprog = arg.sub(/'/, '').split(/=/, 2)[1]\n    else\n      makeprog = 'make'\n    end\n\n    [\n      ExecItem.new('installdirs', 'std/site/home',\n                   'std: install under libruby; site: install under site_ruby; home: install under $HOME')\\\n          {|val, table|\n            case val\n            when 'std'\n              table['rbdir'] = '$librubyver'\n              table['sodir'] = '$librubyverarch'\n            when 'site'\n              table['rbdir'] = '$siterubyver'\n              table['sodir'] = '$siterubyverarch'\n            when 'home'\n              setup_rb_error '$HOME was not set' unless ENV['HOME']\n              table['prefix'] = ENV['HOME']\n              table['rbdir'] = '$libdir/ruby'\n              table['sodir'] = '$libdir/ruby'\n            end\n          },\n      PathItem.new('prefix', 'path', c['prefix'],\n                   'path prefix of target environment'),\n      PathItem.new('bindir', 'path', parameterize.call(c['bindir']),\n                   'the directory for commands'),\n      PathItem.new('libdir', 'path', parameterize.call(c['libdir']),\n                   'the directory for libraries'),\n      PathItem.new('datadir', 'path', parameterize.call(c['datadir']),\n                   'the directory for shared data'),\n      PathItem.new('mandir', 'path', parameterize.call(c['mandir']),\n                   'the directory for man pages'),\n      PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),\n                   'the directory for system configuration files'),\n      PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),\n                   'the directory for local state data'),\n      PathItem.new('libruby', 'path', libruby,\n                   'the directory for ruby libraries'),\n      PathItem.new('librubyver', 'path', librubyver,\n                   'the directory for standard ruby libraries'),\n      PathItem.new('librubyverarch', 'path', librubyverarch,\n                   'the directory for standard ruby extensions'),\n      PathItem.new('siteruby', 'path', siteruby,\n          'the directory for version-independent aux ruby libraries'),\n      PathItem.new('siterubyver', 'path', siterubyver,\n                   'the directory for aux ruby libraries'),\n      PathItem.new('siterubyverarch', 'path', siterubyverarch,\n                   'the directory for aux ruby binaries'),\n      PathItem.new('rbdir', 'path', '$siterubyver',\n                   'the directory for ruby scripts'),\n      PathItem.new('sodir', 'path', '$siterubyverarch',\n                   'the directory for ruby extentions'),\n      PathItem.new('rubypath', 'path', rubypath,\n                   'the path to set to #! line'),\n      ProgramItem.new('rubyprog', 'name', rubypath,\n                      'the ruby program using for installation'),\n      ProgramItem.new('makeprog', 'name', makeprog,\n                      'the make program to compile ruby extentions'),\n      SelectItem.new('shebang', 'all/ruby/never', 'ruby',\n                     'shebang line (#!) editing mode'),\n      BoolItem.new('without-ext', 'yes/no', 'no',\n                   'does not compile/install ruby extentions')\n    ]\n  end\n  private :standard_entries\n\n  def load_multipackage_entries\n    multipackage_entries().each do |ent|\n      add ent\n    end\n  end\n\n  def multipackage_entries\n    [\n      PackageSelectionItem.new('with', 'name,name...', '', 'ALL',\n                               'package names that you want to install'),\n      PackageSelectionItem.new('without', 'name,name...', '', 'NONE',\n                               'package names that you do not want to install')\n    ]\n  end\n  private :multipackage_entries\n\n  ALIASES = {\n    'std-ruby'         => 'librubyver',\n    'stdruby'          => 'librubyver',\n    'rubylibdir'       => 'librubyver',\n    'archdir'          => 'librubyverarch',\n    'site-ruby-common' => 'siteruby',     # For backward compatibility\n    'site-ruby'        => 'siterubyver',  # For backward compatibility\n    'bin-dir'          => 'bindir',\n    'bin-dir'          => 'bindir',\n    'rb-dir'           => 'rbdir',\n    'so-dir'           => 'sodir',\n    'data-dir'         => 'datadir',\n    'ruby-path'        => 'rubypath',\n    'ruby-prog'        => 'rubyprog',\n    'ruby'             => 'rubyprog',\n    'make-prog'        => 'makeprog',\n    'make'             => 'makeprog'\n  }\n\n  def fixup\n    ALIASES.each do |ali, name|\n      @table[ali] = @table[name]\n    end\n    @items.freeze\n    @table.freeze\n    @options_re = /\\A--(#{@table.keys.join('|')})(?:=(.*))?\\z/\n  end\n\n  def parse_opt(opt)\n    m = @options_re.match(opt) or setup_rb_error \"config: unknown option #{opt}\"\n    m.to_a[1,2]\n  end\n\n  def dllext\n    @rbconfig['DLEXT']\n  end\n\n  def value_config?(name)\n    lookup(name).value?\n  end\n\n  class Item\n    def initialize(name, template, default, desc)\n      @name = name.freeze\n      @template = template\n      @value = default\n      @default = default\n      @description = desc\n    end\n\n    attr_reader :name\n    attr_reader :description\n\n    attr_accessor :default\n    alias help_default default\n\n    def help_opt\n      \"--#{@name}=#{@template}\"\n    end\n\n    def value?\n      true\n    end\n\n    def value\n      @value\n    end\n\n    def resolve(table)\n      @value.gsub(%r<\\$([^/]+)>) { table[$1] }\n    end\n\n    def set(val)\n      @value = check(val)\n    end\n\n    private\n\n    def check(val)\n      setup_rb_error \"config: --#{name} requires argument\" unless val\n      val\n    end\n  end\n\n  class BoolItem < Item\n    def config_type\n      'bool'\n    end\n\n    def help_opt\n      \"--#{@name}\"\n    end\n\n    private\n\n    def check(val)\n      return 'yes' unless val\n      case val\n      when /\\Ay(es)?\\z/i, /\\At(rue)?\\z/i then 'yes'\n      when /\\An(o)?\\z/i, /\\Af(alse)\\z/i  then 'no'\n      else\n        setup_rb_error \"config: --#{@name} accepts only yes/no for argument\"\n      end\n    end\n  end\n\n  class PathItem < Item\n    def config_type\n      'path'\n    end\n\n    private\n\n    def check(path)\n      setup_rb_error \"config: --#{@name} requires argument\"  unless path\n      path[0,1] == '$' ? path : File.expand_path(path)\n    end\n  end\n\n  class ProgramItem < Item\n    def config_type\n      'program'\n    end\n  end\n\n  class SelectItem < Item\n    def initialize(name, selection, default, desc)\n      super\n      @ok = selection.split('/')\n    end\n\n    def config_type\n      'select'\n    end\n\n    private\n\n    def check(val)\n      unless @ok.include?(val.strip)\n        setup_rb_error \"config: use --#{@name}=#{@template} (#{val})\"\n      end\n      val.strip\n    end\n  end\n\n  class ExecItem < Item\n    def initialize(name, selection, desc, &block)\n      super name, selection, nil, desc\n      @ok = selection.split('/')\n      @action = block\n    end\n\n    def config_type\n      'exec'\n    end\n\n    def value?\n      false\n    end\n\n    def resolve(table)\n      setup_rb_error \"$#{name()} wrongly used as option value\"\n    end\n\n    undef set\n\n    def evaluate(val, table)\n      v = val.strip.downcase\n      unless @ok.include?(v)\n        setup_rb_error \"invalid option --#{@name}=#{val} (use #{@template})\"\n      end\n      @action.call v, table\n    end\n  end\n\n  class PackageSelectionItem < Item\n    def initialize(name, template, default, help_default, desc)\n      super name, template, default, desc\n      @help_default = help_default\n    end\n\n    attr_reader :help_default\n\n    def config_type\n      'package'\n    end\n\n    private\n\n    def check(val)\n      unless File.dir?(\"packages/#{val}\")\n        setup_rb_error \"config: no such package: #{val}\"\n      end\n      val\n    end\n  end\n\n  class MetaConfigEnvironment\n    def initialize(config, installer)\n      @config = config\n      @installer = installer\n    end\n\n    def config_names\n      @config.names\n    end\n\n    def config?(name)\n      @config.key?(name)\n    end\n\n    def bool_config?(name)\n      @config.lookup(name).config_type == 'bool'\n    end\n\n    def path_config?(name)\n      @config.lookup(name).config_type == 'path'\n    end\n\n    def value_config?(name)\n      @config.lookup(name).config_type != 'exec'\n    end\n\n    def add_config(item)\n      @config.add item\n    end\n\n    def add_bool_config(name, default, desc)\n      @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)\n    end\n\n    def add_path_config(name, default, desc)\n      @config.add PathItem.new(name, 'path', default, desc)\n    end\n\n    def set_config_default(name, default)\n      @config.lookup(name).default = default\n    end\n\n    def remove_config(name)\n      @config.remove(name)\n    end\n\n    # For only multipackage\n    def packages\n      raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer\n      @installer.packages\n    end\n\n    # For only multipackage\n    def declare_packages(list)\n      raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer\n      @installer.packages = list\n    end\n  end\n\nend   # class ConfigTable\n\n\n# This module requires: #verbose?, #no_harm?\nmodule FileOperations\n\n  def mkdir_p(dirname, prefix = nil)\n    dirname = prefix + File.expand_path(dirname) if prefix\n    $stderr.puts \"mkdir -p #{dirname}\" if verbose?\n    return if no_harm?\n\n    # Does not check '/', it's too abnormal.\n    dirs = File.expand_path(dirname).split(%r<(?=/)>)\n    if /\\A[a-z]:\\z/i =~ dirs[0]\n      disk = dirs.shift\n      dirs[0] = disk + dirs[0]\n    end\n    dirs.each_index do |idx|\n      path = dirs[0..idx].join('')\n      Dir.mkdir path unless File.dir?(path)\n    end\n  end\n\n  def rm_f(path)\n    $stderr.puts \"rm -f #{path}\" if verbose?\n    return if no_harm?\n    force_remove_file path\n  end\n\n  def rm_rf(path)\n    $stderr.puts \"rm -rf #{path}\" if verbose?\n    return if no_harm?\n    remove_tree path\n  end\n\n  def remove_tree(path)\n    if File.symlink?(path)\n      remove_file path\n    elsif File.dir?(path)\n      remove_tree0 path\n    else\n      force_remove_file path\n    end\n  end\n\n  def remove_tree0(path)\n    Dir.foreach(path) do |ent|\n      next if ent == '.'\n      next if ent == '..'\n      entpath = \"#{path}/#{ent}\"\n      if File.symlink?(entpath)\n        remove_file entpath\n      elsif File.dir?(entpath)\n        remove_tree0 entpath\n      else\n        force_remove_file entpath\n      end\n    end\n    begin\n      Dir.rmdir path\n    rescue Errno::ENOTEMPTY\n      # directory may not be empty\n    end\n  end\n\n  def move_file(src, dest)\n    force_remove_file dest\n    begin\n      File.rename src, dest\n    rescue\n      File.open(dest, 'wb') {|f|\n        f.write File.binread(src)\n      }\n      File.chmod File.stat(src).mode, dest\n      File.unlink src\n    end\n  end\n\n  def force_remove_file(path)\n    begin\n      remove_file path\n    rescue\n    end\n  end\n\n  def remove_file(path)\n    File.chmod 0777, path\n    File.unlink path\n  end\n\n  def install(from, dest, mode, prefix = nil)\n    $stderr.puts \"install #{from} #{dest}\" if verbose?\n    return if no_harm?\n\n    realdest = prefix ? prefix + File.expand_path(dest) : dest\n    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)\n    str = File.binread(from)\n    if diff?(str, realdest)\n      verbose_off {\n        rm_f realdest if File.exist?(realdest)\n      }\n      File.open(realdest, 'wb') {|f|\n        f.write str\n      }\n      File.chmod mode, realdest\n\n      File.open(\"#{objdir_root()}/InstalledFiles\", 'a') {|f|\n        if prefix\n          f.puts realdest.sub(prefix, '')\n        else\n          f.puts realdest\n        end\n      }\n    end\n  end\n\n  def diff?(new_content, path)\n    return true unless File.exist?(path)\n    new_content != File.binread(path)\n  end\n\n  def command(*args)\n    $stderr.puts args.join(' ') if verbose?\n    system(*args) or raise RuntimeError,\n        \"system(#{args.map{|a| a.inspect }.join(' ')}) failed\"\n  end\n\n  def ruby(*args)\n    command config('rubyprog'), *args\n  end\n  \n  def make(task = nil)\n    command(*[config('makeprog'), task].compact)\n  end\n\n  def extdir?(dir)\n    File.exist?(\"#{dir}/MANIFEST\") or File.exist?(\"#{dir}/extconf.rb\")\n  end\n\n  def files_of(dir)\n    Dir.open(dir) {|d|\n      return d.select {|ent| File.file?(\"#{dir}/#{ent}\") }\n    }\n  end\n\n  DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )\n\n  def directories_of(dir)\n    Dir.open(dir) {|d|\n      return d.select {|ent| File.dir?(\"#{dir}/#{ent}\") } - DIR_REJECT\n    }\n  end\n\nend\n\n\n# This module requires: #srcdir_root, #objdir_root, #relpath\nmodule HookScriptAPI\n\n  def get_config(key)\n    @config[key]\n  end\n\n  alias config get_config\n\n  # obsolete: use metaconfig to change configuration\n  def set_config(key, val)\n    @config[key] = val\n  end\n\n  #\n  # srcdir/objdir (works only in the package directory)\n  #\n\n  def curr_srcdir\n    \"#{srcdir_root()}/#{relpath()}\"\n  end\n\n  def curr_objdir\n    \"#{objdir_root()}/#{relpath()}\"\n  end\n\n  def srcfile(path)\n    \"#{curr_srcdir()}/#{path}\"\n  end\n\n  def srcexist?(path)\n    File.exist?(srcfile(path))\n  end\n\n  def srcdirectory?(path)\n    File.dir?(srcfile(path))\n  end\n  \n  def srcfile?(path)\n    File.file?(srcfile(path))\n  end\n\n  def srcentries(path = '.')\n    Dir.open(\"#{curr_srcdir()}/#{path}\") {|d|\n      return d.to_a - %w(. ..)\n    }\n  end\n\n  def srcfiles(path = '.')\n    srcentries(path).select {|fname|\n      File.file?(File.join(curr_srcdir(), path, fname))\n    }\n  end\n\n  def srcdirectories(path = '.')\n    srcentries(path).select {|fname|\n      File.dir?(File.join(curr_srcdir(), path, fname))\n    }\n  end\n\nend\n\n\nclass ToplevelInstaller\n\n  Version   = '3.4.1'\n  Copyright = 'Copyright (c) 2000-2005 Minero Aoki'\n\n  TASKS = [\n    [ 'all',      'do config, setup, then install' ],\n    [ 'config',   'saves your configurations' ],\n    [ 'show',     'shows current configuration' ],\n    [ 'setup',    'compiles ruby extentions and others' ],\n    [ 'install',  'installs files' ],\n    [ 'test',     'run all tests in test/' ],\n    [ 'clean',    \"does `make clean' for each extention\" ],\n    [ 'distclean',\"does `make distclean' for each extention\" ]\n  ]\n\n  def ToplevelInstaller.invoke\n    config = ConfigTable.new(load_rbconfig())\n    config.load_standard_entries\n    config.load_multipackage_entries if multipackage?\n    config.fixup\n    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)\n    klass.new(File.dirname($0), config).invoke\n  end\n\n  def ToplevelInstaller.multipackage?\n    File.dir?(File.dirname($0) + '/packages')\n  end\n\n  def ToplevelInstaller.load_rbconfig\n    if arg = ARGV.detect {|arg| /\\A--rbconfig=/ =~ arg }\n      ARGV.delete(arg)\n      load File.expand_path(arg.split(/=/, 2)[1])\n      $\".push 'rbconfig.rb'\n    else\n      require 'rbconfig'\n    end\n    ::Config::CONFIG\n  end\n\n  def initialize(ardir_root, config)\n    @ardir = File.expand_path(ardir_root)\n    @config = config\n    # cache\n    @valid_task_re = nil\n  end\n\n  def config(key)\n    @config[key]\n  end\n\n  def inspect\n    \"#<#{self.class} #{__id__()}>\"\n  end\n\n  def invoke\n    run_metaconfigs\n    case task = parsearg_global()\n    when nil, 'all'\n      parsearg_config\n      init_installers\n      exec_config\n      exec_setup\n      exec_install\n    else\n      case task\n      when 'config', 'test'\n        ;\n      when 'clean', 'distclean'\n        @config.load_savefile if File.exist?(@config.savefile)\n      else\n        @config.load_savefile\n      end\n      __send__ \"parsearg_#{task}\"\n      init_installers\n      __send__ \"exec_#{task}\"\n    end\n  end\n  \n  def run_metaconfigs\n    @config.load_script \"#{@ardir}/metaconfig\"\n  end\n\n  def init_installers\n    @installer = Installer.new(@config, @ardir, File.expand_path('.'))\n  end\n\n  #\n  # Hook Script API bases\n  #\n\n  def srcdir_root\n    @ardir\n  end\n\n  def objdir_root\n    '.'\n  end\n\n  def relpath\n    '.'\n  end\n\n  #\n  # Option Parsing\n  #\n\n  def parsearg_global\n    while arg = ARGV.shift\n      case arg\n      when /\\A\\w+\\z/\n        setup_rb_error \"invalid task: #{arg}\" unless valid_task?(arg)\n        return arg\n      when '-q', '--quiet'\n        @config.verbose = false\n      when '--verbose'\n        @config.verbose = true\n      when '--help'\n        print_usage $stdout\n        exit 0\n      when '--version'\n        puts \"#{File.basename($0)} version #{Version}\"\n        exit 0\n      when '--copyright'\n        puts Copyright\n        exit 0\n      else\n        setup_rb_error \"unknown global option '#{arg}'\"\n      end\n    end\n    nil\n  end\n\n  def valid_task?(t)\n    valid_task_re() =~ t\n  end\n\n  def valid_task_re\n    @valid_task_re ||= /\\A(?:#{TASKS.map {|task,desc| task }.join('|')})\\z/\n  end\n\n  def parsearg_no_options\n    unless ARGV.empty?\n      task = caller(0).first.slice(%r<`parsearg_(\\w+)'>, 1)\n      setup_rb_error \"#{task}: unknown options: #{ARGV.join(' ')}\"\n    end\n  end\n\n  alias parsearg_show       parsearg_no_options\n  alias parsearg_setup      parsearg_no_options\n  alias parsearg_test       parsearg_no_options\n  alias parsearg_clean      parsearg_no_options\n  alias parsearg_distclean  parsearg_no_options\n\n  def parsearg_config\n    evalopt = []\n    set = []\n    @config.config_opt = []\n    while i = ARGV.shift\n      if /\\A--?\\z/ =~ i\n        @config.config_opt = ARGV.dup\n        break\n      end\n      name, value = *@config.parse_opt(i)\n      if @config.value_config?(name)\n        @config[name] = value\n      else\n        evalopt.push [name, value]\n      end\n      set.push name\n    end\n    evalopt.each do |name, value|\n      @config.lookup(name).evaluate value, @config\n    end\n    # Check if configuration is valid\n    set.each do |n|\n      @config[n] if @config.value_config?(n)\n    end\n  end\n\n  def parsearg_install\n    @config.no_harm = false\n    @config.install_prefix = ''\n    while a = ARGV.shift\n      case a\n      when '--no-harm'\n        @config.no_harm = true\n      when /\\A--prefix=/\n        path = a.split(/=/, 2)[1]\n        path = File.expand_path(path) unless path[0,1] == '/'\n        @config.install_prefix = path\n      else\n        setup_rb_error \"install: unknown option #{a}\"\n      end\n    end\n  end\n\n  def print_usage(out)\n    out.puts 'Typical Installation Procedure:'\n    out.puts \"  $ ruby #{File.basename $0} config\"\n    out.puts \"  $ ruby #{File.basename $0} setup\"\n    out.puts \"  # ruby #{File.basename $0} install (may require root privilege)\"\n    out.puts\n    out.puts 'Detailed Usage:'\n    out.puts \"  ruby #{File.basename $0} <global option>\"\n    out.puts \"  ruby #{File.basename $0} [<global options>] <task> [<task options>]\"\n\n    fmt = \"  %-24s %s\\n\"\n    out.puts\n    out.puts 'Global options:'\n    out.printf fmt, '-q,--quiet',   'suppress message outputs'\n    out.printf fmt, '   --verbose', 'output messages verbosely'\n    out.printf fmt, '   --help',    'print this message'\n    out.printf fmt, '   --version', 'print version and quit'\n    out.printf fmt, '   --copyright',  'print copyright and quit'\n    out.puts\n    out.puts 'Tasks:'\n    TASKS.each do |name, desc|\n      out.printf fmt, name, desc\n    end\n\n    fmt = \"  %-24s %s [%s]\\n\"\n    out.puts\n    out.puts 'Options for CONFIG or ALL:'\n    @config.each do |item|\n      out.printf fmt, item.help_opt, item.description, item.help_default\n    end\n    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',\"running ruby's\"\n    out.puts\n    out.puts 'Options for INSTALL:'\n    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'\n    out.printf fmt, '--prefix=path',  'install path prefix', ''\n    out.puts\n  end\n\n  #\n  # Task Handlers\n  #\n\n  def exec_config\n    @installer.exec_config\n    @config.save   # must be final\n  end\n\n  def exec_setup\n    @installer.exec_setup\n  end\n\n  def exec_install\n    @installer.exec_install\n  end\n\n  def exec_test\n    @installer.exec_test\n  end\n\n  def exec_show\n    @config.each do |i|\n      printf \"%-20s %s\\n\", i.name, i.value if i.value?\n    end\n  end\n\n  def exec_clean\n    @installer.exec_clean\n  end\n\n  def exec_distclean\n    @installer.exec_distclean\n  end\n\nend   # class ToplevelInstaller\n\n\nclass ToplevelInstallerMulti < ToplevelInstaller\n\n  include FileOperations\n\n  def initialize(ardir_root, config)\n    super\n    @packages = directories_of(\"#{@ardir}/packages\")\n    raise 'no package exists' if @packages.empty?\n    @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))\n  end\n\n  def run_metaconfigs\n    @config.load_script \"#{@ardir}/metaconfig\", self\n    @packages.each do |name|\n      @config.load_script \"#{@ardir}/packages/#{name}/metaconfig\"\n    end\n  end\n\n  attr_reader :packages\n\n  def packages=(list)\n    raise 'package list is empty' if list.empty?\n    list.each do |name|\n      raise \"directory packages/#{name} does not exist\"\\\n              unless File.dir?(\"#{@ardir}/packages/#{name}\")\n    end\n    @packages = list\n  end\n\n  def init_installers\n    @installers = {}\n    @packages.each do |pack|\n      @installers[pack] = Installer.new(@config,\n                                       \"#{@ardir}/packages/#{pack}\",\n                                       \"packages/#{pack}\")\n    end\n    with    = extract_selection(config('with'))\n    without = extract_selection(config('without'))\n    @selected = @installers.keys.select {|name|\n                  (with.empty? or with.include?(name)) \\\n                      and not without.include?(name)\n                }\n  end\n\n  def extract_selection(list)\n    a = list.split(/,/)\n    a.each do |name|\n      setup_rb_error \"no such package: #{name}\"  unless @installers.key?(name)\n    end\n    a\n  end\n\n  def print_usage(f)\n    super\n    f.puts 'Inluded packages:'\n    f.puts '  ' + @packages.sort.join(' ')\n    f.puts\n  end\n\n  #\n  # Task Handlers\n  #\n\n  def exec_config\n    run_hook 'pre-config'\n    each_selected_installers {|inst| inst.exec_config }\n    run_hook 'post-config'\n    @config.save   # must be final\n  end\n\n  def exec_setup\n    run_hook 'pre-setup'\n    each_selected_installers {|inst| inst.exec_setup }\n    run_hook 'post-setup'\n  end\n\n  def exec_install\n    run_hook 'pre-install'\n    each_selected_installers {|inst| inst.exec_install }\n    run_hook 'post-install'\n  end\n\n  def exec_test\n    run_hook 'pre-test'\n    each_selected_installers {|inst| inst.exec_test }\n    run_hook 'post-test'\n  end\n\n  def exec_clean\n    rm_f @config.savefile\n    run_hook 'pre-clean'\n    each_selected_installers {|inst| inst.exec_clean }\n    run_hook 'post-clean'\n  end\n\n  def exec_distclean\n    rm_f @config.savefile\n    run_hook 'pre-distclean'\n    each_selected_installers {|inst| inst.exec_distclean }\n    run_hook 'post-distclean'\n  end\n\n  #\n  # lib\n  #\n\n  def each_selected_installers\n    Dir.mkdir 'packages' unless File.dir?('packages')\n    @selected.each do |pack|\n      $stderr.puts \"Processing the package `#{pack}' ...\" if verbose?\n      Dir.mkdir \"packages/#{pack}\" unless File.dir?(\"packages/#{pack}\")\n      Dir.chdir \"packages/#{pack}\"\n      yield @installers[pack]\n      Dir.chdir '../..'\n    end\n  end\n\n  def run_hook(id)\n    @root_installer.run_hook id\n  end\n\n  # module FileOperations requires this\n  def verbose?\n    @config.verbose?\n  end\n\n  # module FileOperations requires this\n  def no_harm?\n    @config.no_harm?\n  end\n\nend   # class ToplevelInstallerMulti\n\n\nclass Installer\n\n  FILETYPES = %w( bin lib ext data conf man )\n\n  include FileOperations\n  include HookScriptAPI\n\n  def initialize(config, srcroot, objroot)\n    @config = config\n    @srcdir = File.expand_path(srcroot)\n    @objdir = File.expand_path(objroot)\n    @currdir = '.'\n  end\n\n  def inspect\n    \"#<#{self.class} #{File.basename(@srcdir)}>\"\n  end\n\n  def noop(rel)\n  end\n\n  #\n  # Hook Script API base methods\n  #\n\n  def srcdir_root\n    @srcdir\n  end\n\n  def objdir_root\n    @objdir\n  end\n\n  def relpath\n    @currdir\n  end\n\n  #\n  # Config Access\n  #\n\n  # module FileOperations requires this\n  def verbose?\n    @config.verbose?\n  end\n\n  # module FileOperations requires this\n  def no_harm?\n    @config.no_harm?\n  end\n\n  def verbose_off\n    begin\n      save, @config.verbose = @config.verbose?, false\n      yield\n    ensure\n      @config.verbose = save\n    end\n  end\n\n  #\n  # TASK config\n  #\n\n  def exec_config\n    exec_task_traverse 'config'\n  end\n\n  alias config_dir_bin noop\n  alias config_dir_lib noop\n\n  def config_dir_ext(rel)\n    extconf if extdir?(curr_srcdir())\n  end\n\n  alias config_dir_data noop\n  alias config_dir_conf noop\n  alias config_dir_man noop\n\n  def extconf\n    ruby \"#{curr_srcdir()}/extconf.rb\", *@config.config_opt\n  end\n\n  #\n  # TASK setup\n  #\n\n  def exec_setup\n    exec_task_traverse 'setup'\n  end\n\n  def setup_dir_bin(rel)\n    files_of(curr_srcdir()).each do |fname|\n      update_shebang_line \"#{curr_srcdir()}/#{fname}\"\n    end\n  end\n\n  alias setup_dir_lib noop\n\n  def setup_dir_ext(rel)\n    make if extdir?(curr_srcdir())\n  end\n\n  alias setup_dir_data noop\n  alias setup_dir_conf noop\n  alias setup_dir_man noop\n\n  def update_shebang_line(path)\n    return if no_harm?\n    return if config('shebang') == 'never'\n    old = Shebang.load(path)\n    if old\n      $stderr.puts \"warning: #{path}: Shebang line includes too many args.  It is not portable and your program may not work.\" if old.args.size > 1\n      new = new_shebang(old)\n      return if new.to_s == old.to_s\n    else\n      return unless config('shebang') == 'all'\n      new = Shebang.new(config('rubypath'))\n    end\n    $stderr.puts \"updating shebang: #{File.basename(path)}\" if verbose?\n    open_atomic_writer(path) {|output|\n      File.open(path, 'rb') {|f|\n        f.gets if old   # discard\n        output.puts new.to_s\n        output.print f.read\n      }\n    }\n  end\n\n  def new_shebang(old)\n    if /\\Aruby/ =~ File.basename(old.cmd)\n      Shebang.new(config('rubypath'), old.args)\n    elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'\n      Shebang.new(config('rubypath'), old.args[1..-1])\n    else\n      return old unless config('shebang') == 'all'\n      Shebang.new(config('rubypath'))\n    end\n  end\n\n  def open_atomic_writer(path, &block)\n    tmpfile = File.basename(path) + '.tmp'\n    begin\n      File.open(tmpfile, 'wb', &block)\n      File.rename tmpfile, File.basename(path)\n    ensure\n      File.unlink tmpfile if File.exist?(tmpfile)\n    end\n  end\n\n  class Shebang\n    def Shebang.load(path)\n      line = nil\n      File.open(path) {|f|\n        line = f.gets\n      }\n      return nil unless /\\A#!/ =~ line\n      parse(line)\n    end\n\n    def Shebang.parse(line)\n      cmd, *args = *line.strip.sub(/\\A\\#!/, '').split(' ')\n      new(cmd, args)\n    end\n\n    def initialize(cmd, args = [])\n      @cmd = cmd\n      @args = args\n    end\n\n    attr_reader :cmd\n    attr_reader :args\n\n    def to_s\n      \"#! #{@cmd}\" + (@args.empty? ? '' : \" #{@args.join(' ')}\")\n    end\n  end\n\n  #\n  # TASK install\n  #\n\n  def exec_install\n    rm_f 'InstalledFiles'\n    exec_task_traverse 'install'\n  end\n\n  def install_dir_bin(rel)\n    install_files targetfiles(), \"#{config('bindir')}/#{rel}\", 0755\n  end\n\n  def install_dir_lib(rel)\n    install_files libfiles(), \"#{config('rbdir')}/#{rel}\", 0644\n  end\n\n  def install_dir_ext(rel)\n    return unless extdir?(curr_srcdir())\n    install_files rubyextentions('.'),\n                  \"#{config('sodir')}/#{File.dirname(rel)}\",\n                  0555\n  end\n\n  def install_dir_data(rel)\n    install_files targetfiles(), \"#{config('datadir')}/#{rel}\", 0644\n  end\n\n  def install_dir_conf(rel)\n    # FIXME: should not remove current config files\n    # (rename previous file to .old/.org)\n    install_files targetfiles(), \"#{config('sysconfdir')}/#{rel}\", 0644\n  end\n\n  def install_dir_man(rel)\n    install_files targetfiles(), \"#{config('mandir')}/#{rel}\", 0644\n  end\n\n  def install_files(list, dest, mode)\n    mkdir_p dest, @config.install_prefix\n    list.each do |fname|\n      install fname, dest, mode, @config.install_prefix\n    end\n  end\n\n  def libfiles\n    glob_reject(%w(*.y *.output), targetfiles())\n  end\n\n  def rubyextentions(dir)\n    ents = glob_select(\"*.#{@config.dllext}\", targetfiles())\n    if ents.empty?\n      setup_rb_error \"no ruby extention exists: 'ruby #{$0} setup' first\"\n    end\n    ents\n  end\n\n  def targetfiles\n    mapdir(existfiles() - hookfiles())\n  end\n\n  def mapdir(ents)\n    ents.map {|ent|\n      if File.exist?(ent)\n      then ent                         # objdir\n      else \"#{curr_srcdir()}/#{ent}\"   # srcdir\n      end\n    }\n  end\n\n  # picked up many entries from cvs-1.11.1/src/ignore.c\n  JUNK_FILES = %w( \n    core RCSLOG tags TAGS .make.state\n    .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb\n    *~ *.old *.bak *.BAK *.orig *.rej _$* *$\n\n    *.org *.in .*\n  )\n\n  def existfiles\n    glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))\n  end\n\n  def hookfiles\n    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|\n      %w( config setup install clean ).map {|t| sprintf(fmt, t) }\n    }.flatten\n  end\n\n  def glob_select(pat, ents)\n    re = globs2re([pat])\n    ents.select {|ent| re =~ ent }\n  end\n\n  def glob_reject(pats, ents)\n    re = globs2re(pats)\n    ents.reject {|ent| re =~ ent }\n  end\n\n  GLOB2REGEX = {\n    '.' => '\\.',\n    '$' => '\\$',\n    '#' => '\\#',\n    '*' => '.*'\n  }\n\n  def globs2re(pats)\n    /\\A(?:#{\n      pats.map {|pat| pat.gsub(/[\\.\\$\\#\\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')\n    })\\z/\n  end\n\n  #\n  # TASK test\n  #\n\n  TESTDIR = 'test'\n\n  def exec_test\n    unless File.directory?('test')\n      $stderr.puts 'no test in this package' if verbose?\n      return\n    end\n    $stderr.puts 'Running tests...' if verbose?\n    begin\n      require 'test/unit'\n    rescue LoadError\n      setup_rb_error 'test/unit cannot loaded.  You need Ruby 1.8 or later to invoke this task.'\n    end\n    runner = Test::Unit::AutoRunner.new(true)\n    runner.to_run << TESTDIR\n    runner.run\n  end\n\n  #\n  # TASK clean\n  #\n\n  def exec_clean\n    exec_task_traverse 'clean'\n    rm_f @config.savefile\n    rm_f 'InstalledFiles'\n  end\n\n  alias clean_dir_bin noop\n  alias clean_dir_lib noop\n  alias clean_dir_data noop\n  alias clean_dir_conf noop\n  alias clean_dir_man noop\n\n  def clean_dir_ext(rel)\n    return unless extdir?(curr_srcdir())\n    make 'clean' if File.file?('Makefile')\n  end\n\n  #\n  # TASK distclean\n  #\n\n  def exec_distclean\n    exec_task_traverse 'distclean'\n    rm_f @config.savefile\n    rm_f 'InstalledFiles'\n  end\n\n  alias distclean_dir_bin noop\n  alias distclean_dir_lib noop\n\n  def distclean_dir_ext(rel)\n    return unless extdir?(curr_srcdir())\n    make 'distclean' if File.file?('Makefile')\n  end\n\n  alias distclean_dir_data noop\n  alias distclean_dir_conf noop\n  alias distclean_dir_man noop\n\n  #\n  # Traversing\n  #\n\n  def exec_task_traverse(task)\n    run_hook \"pre-#{task}\"\n    FILETYPES.each do |type|\n      if type == 'ext' and config('without-ext') == 'yes'\n        $stderr.puts 'skipping ext/* by user option' if verbose?\n        next\n      end\n      traverse task, type, \"#{task}_dir_#{type}\"\n    end\n    run_hook \"post-#{task}\"\n  end\n\n  def traverse(task, rel, mid)\n    dive_into(rel) {\n      run_hook \"pre-#{task}\"\n      __send__ mid, rel.sub(%r[\\A.*?(?:/|\\z)], '')\n      directories_of(curr_srcdir()).each do |d|\n        traverse task, \"#{rel}/#{d}\", mid\n      end\n      run_hook \"post-#{task}\"\n    }\n  end\n\n  def dive_into(rel)\n    return unless File.dir?(\"#{@srcdir}/#{rel}\")\n\n    dir = File.basename(rel)\n    Dir.mkdir dir unless File.dir?(dir)\n    prevdir = Dir.pwd\n    Dir.chdir dir\n    $stderr.puts '---> ' + rel if verbose?\n    @currdir = rel\n    yield\n    Dir.chdir prevdir\n    $stderr.puts '<--- ' + rel if verbose?\n    @currdir = File.dirname(rel)\n  end\n\n  def run_hook(id)\n    path = [ \"#{curr_srcdir()}/#{id}\",\n             \"#{curr_srcdir()}/#{id}.rb\" ].detect {|cand| File.file?(cand) }\n    return unless path\n    begin\n      instance_eval File.read(path), path, 1\n    rescue\n      raise if $DEBUG\n      setup_rb_error \"hook #{path} failed:\\n\" + $!.message\n    end\n  end\n\nend   # class Installer\n\n\nclass SetupError < StandardError; end\n\ndef setup_rb_error(msg)\n  raise SetupError, msg\nend\n\nif $0 == __FILE__\n  begin\n    ToplevelInstaller.invoke\n  rescue SetupError\n    raise if $DEBUG\n    $stderr.puts $!.message\n    $stderr.puts \"Try 'ruby #{$0} --help' for detailed usage.\"\n    exit 1\n  end\nend\n"
  },
  {
    "path": "test/fixtures/correlation_matrix.rb",
    "content": "# Retrieve Correlation matrix for eigth variables\nmodule Statsample\n  module Fixtures\n    def harman_817\n      Matrix[\n    [1.0,   0.84,   0.62,   -0.53,   0.03,    0.57,   -0.33,  -0.63],\n    [0.84,  1.00,   0.84,   -0.68,  -0.05,    0.76,   -0.35,  -0.73],\n    [0.62,  0.84,   1.00,   -0.76,   0.08,    0.81,   -0.51,  -0.81],\n    [-0.53, -0.68,  -0.76,  1.00,    -0.25,  -0.80,    0.62,   0.88],\n    [0.03,  -0.05,  0.08,   -0.25,   1.00,    0.25,   -0.72,  -0.36],\n    [0.57,   0.76,  0.81,   -0.80,   0.25,    1.00,   -0.58,  -0.84],\n    [-0.33, -0.35, -0.51,    0.62,  -0.72,   -0.58,    1.00,   0.68],\n    [-0.63, -0.73, -0.81,    0.88,  -0.36,   -0.84,    0.68,   1.00]\n    ].extend(Statsample::CovariateMatrix)\n    end\n  end\nend\n"
  },
  {
    "path": "test/fixtures/hartman_23.matrix",
    "content": "\"height\" \"arm.span\" \"forearm\" \"lower.leg\" \"weight\" \"bitro.diameter\" \"chest.girth\" \"chest.width\"\n\"height\" 1 0.846 0.805 0.859 0.473 0.398 0.301 0.382\n\"arm.span\" 0.846 1 0.881 0.826 0.376 0.326 0.277 0.415\n\"forearm\" 0.805 0.881 1 0.801 0.38 0.319 0.237 0.345\n\"lower.leg\" 0.859 0.826 0.801 1 0.436 0.329 0.327 0.365\n\"weight\" 0.473 0.376 0.38 0.436 1 0.762 0.73 0.629\n\"bitro.diameter\" 0.398 0.326 0.319 0.329 0.762 1 0.583 0.577\n\"chest.girth\" 0.301 0.277 0.237 0.327 0.73 0.583 1 0.539\n\"chest.width\" 0.382 0.415 0.345 0.365 0.629 0.577 0.539 1\n"
  },
  {
    "path": "test/fixtures/repeated_fields.csv",
    "content": "\"id\",\"name\",\"age\",\"city\",\"a1\",\"name\",\"age\"\n1,\"Alex\",20,\"New York\",\"a,b\",\"a\",3\n2,\"Claude\",23,\"London\",\"b,c\",\"b\",4\n3,\"Peter\",25,\"London\",\"a\",\"c\",5\n4,\"Franz\",27,\"Paris\",,\"d\",6\n5,\"George\",\"5,5\",\"Tome\",\"a,b,c\",\"f\",\n6,\"Fernand\",20,\"London\",\"c,b\",\"f\",8\n"
  },
  {
    "path": "test/fixtures/stock_data.csv",
    "content": "17.66\n17.65\n17.68\n17.66\n17.68\n17.67\n17.68\n17.68\n17.67\n17.67\n17.68\n17.71\n17.74\n17.72\n17.73\n17.76\n17.74\n17.69\n17.69\n17.67\n17.66\n17.67\n17.69\n17.69\n17.68\n17.65\n17.65\n17.64\n17.63\n17.64\n17.67\n17.68\n17.7\n17.68\n17.69\n17.69\n17.72\n17.71\n17.71\n17.71\n17.69\n17.69\n17.71\n17.72\n17.71\n17.68\n17.68\n17.68\n17.69\n17.68\n17.68\n17.69\n17.67\n17.69\n17.71\n17.7\n17.7\n17.71\n17.73\n17.74\n17.74\n17.74\n17.76\n17.77\n17.55\n17.55\n17.5\n17.46\n17.49\n17.54\n17.51\n17.54\n17.57\n17.54\n17.52\n17.53\n17.56\n17.55\n17.55\n17.54\n17.55\n17.55\n17.55\n17.54\n17.52\n17.53\n17.51\n17.52\n17.5\n17.5\n17.5\n17.49\n17.46\n17.47\n17.48\n17.45\n17.41\n17.39\n17.38\n17.43\n17.44\n17.43\n17.43\n17.46\n17.46\n17.47\n17.47\n17.45\n17.48\n17.49\n17.5\n17.49\n17.48\n17.49\n17.47\n17.47\n17.44\n17.44\n17.43\n17.45\n17.42\n17.43\n17.43\n17.44\n17.44\n17.43\n17.41\n17.41\n17.38\n17.38\n17.37\n17.37\n17.37\n17.3\n17.28\n17.27\n17.19\n16.41\n16.44\n16.48\n16.53\n16.51\n16.57\n16.54\n16.59\n16.64\n16.6\n16.65\n16.69\n16.69\n16.68\n16.64\n16.65\n16.66\n16.64\n16.61\n16.65\n16.67\n16.66\n16.65\n16.61\n16.59\n16.57\n16.55\n16.55\n16.57\n16.54\n16.6\n16.62\n16.6\n16.59\n16.61\n16.66\n16.69\n16.67\n16.65\n16.66\n16.65\n16.65\n16.68\n16.68\n16.67\n16.64\n16.73\n16.76\n16.75\n16.79\n16.8\n16.77\n16.74\n16.76\n16.83\n16.84\n16.82\n16.89\n16.93\n16.94\n16.9\n16.92\n16.88\n16.85\n16.87\n16.8\n16.79\n16.85\n16.85\n16.8\n16.82\n16.85\n16.9\n16.86\n16.79\n16.75\n16.78\n17.06\n17.05\n17.04\n17.02\n17.01\n17.02\n17.05\n17.07\n17.08\n17.09\n17.1\n17.11\n17.09\n17.1\n17.1\n17.12\n17.17\n17.16\n17.17\n17.18\n17.18\n17.18\n17.17\n17.15\n17.14\n17.13\n17.14\n17.13\n17.12\n17.12\n17.09\n17.09\n17.11\n17.06\n17.07\n17.06\n17.07\n17.06\n17.09\n17.05\n17.04\n17.04\n16.99\n17\n17.03\n17\n16.97\n16.96\n16.98\n16.98\n16.98\n17.03\n17\n17\n17\n17.02\n17\n17.02\n17.01\n17.02\n17.03\n17.03\n17.01\n17.03\n17.03\n17.03\n17.01\n17.03\n17.05\n17.05\n17.08\n17.04\n17.01\n17.03\n17.02\n17.03\n17.04\n17.05\n17.37\n17.35\n17.34\n17.32\n17.29\n17.29\n17.22\n17.26\n17.3\n17.34\n17.33\n17.39\n17.4\n17.39\n17.48\n17.5\n17.47\n17.43\n17.4\n17.42\n17.46\n17.48\n17.48\n17.46\n17.46\n17.45\n17.43\n17.44\n17.48\n17.43\n17.45\n17.47\n17.46\n17.46\n17.48\n17.48\n17.48\n17.46\n17.5\n17.55\n17.58\n17.57\n17.56\n17.59\n17.61\n17.62\n17.63\n17.62\n17.61\n17.61\n17.62\n17.64\n17.65\n17.61\n17.62\n17.66\n17.65\n17.64\n17.63\n17.64\n17.64\n17.64\n17.63\n17.61\n17.61\n17.62\n17.63\n17.64\n17.65\n17.66\n17.68\n17.69\n17.69\n17.69\n17.66\n17.69\n17.69\n17.62\n17.68\n17.64\n17.65\n17.61\n17.52\n17.56\n17.55\n17.55\n17.48\n17.45\n17.46\n17.46\n17.44\n17.47\n17.5\n17.49\n17.5\n17.53\n17.53\n17.54\n17.51\n17.51\n17.53\n17.53\n17.53\n17.55\n17.55\n17.54\n17.56\n17.59\n17.57\n17.58\n17.58\n17.57\n17.59\n17.57\n17.55\n17.51\n17.51\n17.52\n17.52\n17.53\n17.55\n17.59\n17.61\n17.61\n17.6\n17.6\n17.62\n17.65\n17.62\n17.6\n17.6\n17.62\n17.61\n17.62\n17.63\n17.64\n17.65\n17.61\n17.62\n17.64\n17.63\n17.62\n17.6\n17.57\n17.57\n17.6\n17.59\n17.6\n17.61\n17.61\n17.63\n17.63\n17.59\n17.58\n17.76\n17.79\n17.76\n17.73\n17.74\n17.73\n17.67\n17.66\n17.66\n17.64\n17.63\n17.62\n17.61\n17.6\n17.61\n17.61\n17.6\n17.6\n17.64\n17.65\n17.65\n17.63\n17.61\n17.6\n17.63\n17.63\n17.62\n17.63\n17.64\n17.62\n17.63\n17.65\n17.64\n17.6\n17.59\n17.59\n17.58\n17.58\n17.6\n17.6\n17.6\n17.6\n17.6\n17.58\n17.59\n17.6\n17.6\n17.6\n17.59\n17.59\n17.58\n17.58\n17.65\n17.65\n"
  },
  {
    "path": "test/fixtures/test_csv.csv",
    "content": "\"id\",\"name\",\"age\",\"city\",\"a1\"\n1,\"Alex\",20,\"New York\",\"a,b\"\n2,\"Claude\",23,\"London\",\"b,c\"\n3,\"Peter\",25,\"London\",\"a\"\n4,\"Franz\",27,\"Paris\",\n5,\"George\",\"5,5\",\"Tome\",\"a,b,c\"\n6,\"Fernand\",,,\n"
  },
  {
    "path": "test/fixtures/tetmat_matrix.txt",
    "content": "   1.0000000   0.1703164   0.2275128   0.1071861   0.0665047\r\n   0.1703164   1.0000000   0.1890911   0.1111471   0.1724219\r\n   0.2275128   0.1890911   1.0000000   0.1866805   0.1055028\r\n   0.1071861   0.1111471   0.1866805   1.0000000   0.2009241\r\n   0.0665047   0.1724219   0.1055028   0.2009241   1.0000000\r\n"
  },
  {
    "path": "test/fixtures/tetmat_test.txt",
    "content": " 1 1 1 1 1\r\n 1 1 1 1 1\r\n 1 1 1 1 1\r\n 1 1 1 1 2\r\n 1 1 1 1 2\r\n 1 1 1 1 2\r\n 1 1 1 1 2\r\n 1 1 1 1 2\r\n 1 1 1 1 2\r\n 1 1 1 2 1\r\n 1 1 1 2 1\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 1 2 2\r\n 1 1 2 1 1\r\n 1 1 2 1 2\r\n 1 1 2 2 1\r\n 1 1 2 2 1\r\n 1 1 2 2 1\r\n 1 1 2 2 2\r\n 1 1 2 2 2\r\n 1 1 2 2 2\r\n 1 1 2 2 2\r\n 1 2 1 1 1\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 1 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 1 2 2\r\n 1 2 2 1 2\r\n 1 2 2 1 2\r\n 1 2 2 1 2\r\n 1 2 2 2 1\r\n 1 2 2 2 1\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 1 2 2 2 2\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 1\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 1 2\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 1\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 1 2 2\r\n 2 1 2 1 1\r\n 2 1 2 1 1\r\n 2 1 2 1 1\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 1 2\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 1\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 1 2 2 2\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 1\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 1 2\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 1\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 1 2 2\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 1\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 1 2\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 1\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n 2 2 2 2 2\r\n\u001a"
  },
  {
    "path": "test/helpers_tests.rb",
    "content": "$:.unshift(File.expand_path(File.dirname(__FILE__)+'/../lib/'))\n$:.unshift(File.expand_path(File.dirname(__FILE__)+'/'))\nrequire 'minitest'\nrequire 'minitest/unit'\nrequire 'mocha/setup'\nrequire 'tempfile'\nrequire 'tmpdir'\nrequire 'shoulda'\nrequire 'shoulda-context'\nrequire 'fixtures/correlation_matrix'\n\nrequire 'statsample'\n\n\nmodule MiniTest\n  class Test\n    include Shoulda::Context::Assertions\n    include Shoulda::Context::InstanceMethods\n    extend Shoulda::Context::ClassMethods\n      def self.should_with_gsl(name,&block)\n        should(name) do\n          if Statsample.has_gsl?\n            instance_eval(&block)\n          else\n            skip(\"Requires GSL\")\n          end\n         \n        end\n    \n      \n    end\n  end\n\n  module Assertions\n    def assert_similar_vector(exp, obs, delta=1e-10,msg=nil)\n      msg||=\"Different vectors #{exp} - #{obs}\"\n      assert_equal(exp.size, obs.size)\n      exp.data_with_nils.each_with_index {|v,i|\n        assert_in_delta(v,obs[i],delta)\n      }\n    end\n    def assert_equal_vector(exp,obs,delta=1e-10,msg=nil)\n      assert_equal(exp.size, obs.size, \"Different size.#{msg}\")\n      exp.size.times {|i|\n        assert_in_delta(exp[i],obs[i],delta, \"Different element #{i}. \\nExpected:\\n#{exp}\\nObserved:\\n#{obs}.#{msg}\")\n      }\n    end\n    def assert_equal_matrix(exp,obs,delta=1e-10,msg=nil)\n       assert_equal(exp.row_size, obs.row_size, \"Different row size.#{msg}\")\n       assert_equal(exp.column_size, obs.column_size, \"Different column size.#{msg}\")\n       exp.row_size.times {|i|\n         exp.column_size.times {|j|\n           assert_in_delta(exp[i,j],obs[i,j], delta, \"Different element #{i},#{j}\\nExpected:\\n#{exp}\\nObserved:\\n#{obs}.#{msg}\")\n         }\n       }\n    end\n    alias :assert_raise :assert_raises unless method_defined? :assert_raise\n    alias :assert_not_equal :refute_equal unless method_defined? :assert_not_equal\n    alias :assert_not_same :refute_same unless method_defined? :assert_not_same\n    unless method_defined? :assert_nothing_raised\n      def assert_nothing_raised(msg=nil)\n        msg||=\"Nothing should be raised, but raised %s\"\n        begin\n          yield\n          not_raised=true\n        rescue Exception => e\n          not_raised=false\n          msg=sprintf(msg,e)\n        end\n        assert(not_raised,msg)\n      end\n    end\n  end\nend\n\nMiniTest.autorun\n\n"
  },
  {
    "path": "test/test_analysis.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleAnalysisTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Analysis) do\n    setup do\n      Statsample::Analysis.clear_analysis\n    end\n    should \"store() should create and store Statsample::Analysis::Suite\" do\n      Statsample::Analysis.store(:first) do\n        a=1\n      end\n      assert(Statsample::Analysis.stored_analysis[:first])\n      assert(Statsample::Analysis.stored_analysis[:first].is_a? Statsample::Analysis::Suite)\n    end\n    \n    should \"ss_analysis should create an Statsample::Analysis\" do\n      ss_analysis(:first) {a=1}\n    end\n    should \"store last created analysis\" do\n      an=Statsample::Analysis.store(:first) do\n        a=1\n      end\n      assert_equal(an,Statsample::Analysis.last)\n    end\n    \n    should \"add_to_reportbuilder() add sections to reportbuilder object\" do\n      rb=mock()\n      rb.expects(:add).with {|value| value.is_a? ReportBuilder::Section and value.name==:first}\n      rb.expects(:add).with {|value| value.is_a? ReportBuilder::Section and value.name==:second}\n      \n      Statsample::Analysis.store(:first) do\n        echo \"first\",\"second\"\n      end\n      Statsample::Analysis.store(:second) do\n        echo \"third\"\n      end\n      Statsample::Analysis.add_to_reportbuilder(rb,:first,:second)\n    end\n    should \"to_text returns the same as a normal ReportBuilder object\" do\n      rb=ReportBuilder.new(:name=>:test)\n      section=ReportBuilder::Section.new(:name=>\"first\")\n      a=[1,2,3].to_scale\n      section.add(\"first\")\n      section.add(a)\n      rb.add(section)\n      exp=rb.to_text\n      an=ss_analysis(:first) {\n        echo 'first'\n        summary(a)\n      }\n      obs=Statsample::Analysis.to_text(:first)\n      \n      assert_equal(exp.split(\"\\n\")[1,exp.size], obs.split(\"\\n\")[1,obs.size])\n    end\n    \n    should \"run() execute all analysis by default\" do\n      m1=mock()\n      m1.expects(:run).once\n      m1.expects(:hide).once\n      \n      Statsample::Analysis.store(:first) do\n        m1.run\n      end\n      Statsample::Analysis.store(:second) do\n        m1.hide\n      end\n      \n      # Should run all test\n      Statsample::Analysis.run\n    end\n    \n    should \"run() execute blocks specificed on parameters\" do\n      m1=mock()\n      m1.expects(:run).once   \n      m1.expects(:hide).never\n      Statsample::Analysis.store(:first) do\n        m1.run\n      end\n      Statsample::Analysis.store(:second) do\n        m1.hide\n      end\n      # Should run all test\n      Statsample::Analysis.run(:first)\n    end\n   \n    context(Statsample::Analysis::Suite) do\n      should \"echo() uses output#puts with same arguments\" do\n        an=Statsample::Analysis::Suite.new(:output)\n        obj=mock()\n        obj.expects(:puts).with(:first,:second).once\n        an.output=obj\n        an.echo(:first,:second)\n      end\n      should \"summary() should call object.summary\" do\n        an=Statsample::Analysis::Suite.new(:summary)\n        obj=stub('summarizable',:summary=>'summary')\n        assert_equal(obj.summary,an.summary(obj))\n      end\n      should \"attach() allows to call objects on objects which respond to fields\" do\n        an=Statsample::Analysis::Suite.new(:summary)\n        ds={'x'=>stub(:mean=>10),'y'=>stub(:mean=>12)}\n        ds.expects(:fields).returns(%w{x y}).at_least_once\n        an.attach(ds)\n        assert_equal(10,an.x.mean)\n        assert_equal(12,an.y.mean)\n        assert_raise(RuntimeError) {\n          an.z\n        }\n      end\n      should \"attached objects should be called LIFO\" do\n        an=Statsample::Analysis::Suite.new(:summary)\n        ds1={'x'=>stub(:mean=>100),'y'=>stub(:mean=>120),'z'=>stub(:mean=>13)}\n        ds1.expects(:fields).returns(%w{x y z}).at_least_once\n        ds2={'x'=>stub(:mean=>10),'y'=>stub(:mean=>12)}\n        ds2.expects(:fields).returns(%w{x y}).at_least_once\n        an.attach(ds1)\n        an.attach(ds2)\n        assert_equal(10,an.x.mean)\n        assert_equal(12,an.y.mean)        \n        assert_equal(13,an.z.mean)        \n      end\n      \n      should \"detach() without arguments drop latest object\" do\n        an=Statsample::Analysis::Suite.new(:summary)\n        ds1={'x'=>stub(:mean=>100),'y'=>stub(:mean=>120),'z'=>stub(:mean=>13)}\n        ds1.expects(:fields).returns(%w{x y z}).at_least_once\n        ds2={'x'=>stub(:mean=>10),'y'=>stub(:mean=>12)}        \n        ds2.expects(:fields).returns(%w{x y}).at_least_once\n        an.attach(ds1)\n        an.attach(ds2)\n        assert_equal(10,an.x.mean)\n        an.detach\n        assert_equal(100, an.x.mean)\n      end\n      should \"detach() with argument drop select object\" do\n        an=Statsample::Analysis::Suite.new(:summary)\n        ds1={'x'=>1}\n        ds1.expects(:fields).returns(%w{x}).at_least_once\n        ds2={'x'=>2,'y'=>3}\n        ds2.expects(:fields).returns(%w{x y}).at_least_once\n        ds3={'y'=>4}\n        ds3.expects(:fields).returns(%w{y}).at_least_once\n        \n        an.attach(ds3)\n        an.attach(ds2)\n        an.attach(ds1)\n        assert_equal(1,an.x)\n        assert_equal(3,an.y)\n        an.detach(ds2)\n        assert_equal(4,an.y)\n      end\n      should \"perform a simple analysis\" do\n        output=mock()\n        output.expects(:puts).with(5.5)\n        an=Statsample::Analysis.store(:simple, :output=>output) do\n          ds=data_frame(:x=>vector(1..10),:y=>vector(1..10))\n          attach(ds)\n          echo x.mean\n        end\n        an.run\n      end\n    end\n    context(Statsample::Analysis::SuiteReportBuilder) do\n      should \"echo() use add on rb object\" do\n        an=Statsample::Analysis::SuiteReportBuilder.new(:puts_to_add)\n        an.rb.expects(:add).with(:first).twice\n        an.echo(:first, :first)\n      end\n      should \"summary() uses add on rb object\" do\n        an=Statsample::Analysis::SuiteReportBuilder.new(:summary_to_add)\n        an.rb.expects(:add).with(:first).once\n        an.summary(:first)\n      end\n    end\n    \n  end\nend\n"
  },
  {
    "path": "test/test_anova_contrast.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleAnovaContrastTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Anova::Contrast) do\n    setup do\n      constant=[12,13,11,12,12].to_scale\n      frequent=[9,10,9,13,14].to_scale\n      infrequent=[15,16,17,16,16].to_scale\n      never=[17,18,12,18,20].to_scale\n      @vectors=[constant, frequent, infrequent, never]\n      @c=Statsample::Anova::Contrast.new(:vectors=>@vectors)\n    end\n    should \"return correct value using c\" do\n      @c.c([1,-1.quo(3),-1.quo(3),-1.quo(3)])\n      #@c.c([1,-0.333,-0.333,-0.333])\n      assert_in_delta(-2.6667, @c.psi, 0.0001)\n      assert_in_delta(1.0165, @c.se, 0.0001)\n      assert_in_delta(-2.623, @c.t, 0.001)\n      assert_in_delta(-4.82, @c.confidence_interval[0],0.01)\n      assert_in_delta(-0.51, @c.confidence_interval[1],0.01)\n      assert(@c.summary.size>0)\n    end\n    should \"return correct values using c_by_index\" do\n      @c.c_by_index([0],[1,2,3])\n      assert_in_delta(-2.6667, @c.psi, 0.0001)\n      assert_in_delta(1.0165, @c.se, 0.0001)\n      assert_in_delta(-2.623, @c.t, 0.001)\n    end\n    should \"return correct values using incomplete c_by_index\" do\n      c1=Statsample::Anova::Contrast.new(:vectors=>@vectors, :c=>[0.5,0.5,-1,0])\n      c2=Statsample::Anova::Contrast.new(:vectors=>@vectors, :c1=>[0,1],:c2=>[2])\n      assert_equal(c1.psi,c2.psi)\n      assert_equal(c1.se,c2.se)\n      assert_equal(c1.t,c2.t)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_anovaoneway.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleAnovaOneWayTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Anova::OneWay) do\n    setup do\n      @ss_num=30.08\n      @ss_den=87.88\n      @df_num=2\n      @df_den=21\n      @anova=Statsample::Anova::OneWay.new(:ss_num=>@ss_num, :ss_den=>@ss_den, :df_num=>@df_num, :df_den=>@df_den)\n    end\n    should \"Statsample::Anova.oneway respond to #oneway\" do\n      assert(Statsample::Anova.respond_to? :oneway)\n    end\n    should \"return correct value for ms_num and ms_den\" do\n      assert_in_delta(15.04, @anova.ms_num, 0.01)\n      assert_in_delta(4.18, @anova.ms_den, 0.01)\n    end\n    should \"return correct value for f\" do\n      assert_in_delta(3.59, @anova.f, 0.01)\n    end\n    should \"respond to summary\" do\n      assert(@anova.respond_to? :summary)\n      assert(@anova.summary.size>0)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_anovatwoway.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleAnovaTwoWayTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Anova::TwoWay) do\n    setup do\n      @ss_a=192.2\n      @ss_b=57.8\n      @ss_axb=168.2\n      @ss_within=75.6\n      @df_a=@df_b=1\n      @df_within=16\n      @anova=Statsample::Anova::TwoWay.new(:ss_a=>@ss_a, :ss_b=>@ss_b, :ss_axb=>@ss_axb, :ss_within=>@ss_within , :df_a=>@df_a, :df_b=>@df_b, :df_within=>@df_within)\n    end\n    should \"Statsample::Anova.twoway respond to #twoway\" do\n    assert(Statsample::Anova.respond_to? :twoway)\n    end\n    should \"return correct value for ms_a, ms_b and ms_axb\" do\n      assert_in_delta(192.2, @anova.ms_a, 0.01)\n      assert_in_delta(57.8, @anova.ms_b, 0.01)\n      assert_in_delta(168.2, @anova.ms_axb, 0.01)\n      \n    end\n    should \"return correct value for f \" do\n      assert_in_delta(40.68, @anova.f_a, 0.01)\n      assert_in_delta(12.23, @anova.f_b, 0.01)\n      assert_in_delta(35.60, @anova.f_axb, 0.01)\n    end\n    should \"return correct value for probability for f \" do\n      assert(@anova.f_a_probability < 0.05)\n      assert(@anova.f_b_probability < 0.05)\n      assert(@anova.f_axb_probability < 0.05)\n    end\n\n    should \"respond to summary\" do\n      assert(@anova.respond_to? :summary)\n      assert(@anova.summary.size>0)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_anovatwowaywithdataset.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n# Reference:\n# * http://www.uwsp.edu/psych/Stat/13/anova-2w.htm#III\nclass StatsampleAnovaTwoWayWithVectorsTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Anova::TwoWayWithVectors) do\n    setup do\n      @pa=[5,4,3,4,2,18,19,14,12,15,6,7,5,8,4,6,9,5,9,3].to_scale\n      @pa.name=\"Passive Avoidance\"\n      @a=[0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1].to_vector\n      @a.labels={0=>'0%',1=>'35%'}\n      @a.name='Diet'\n      @b=[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1].to_vector\n      @b.labels={0=>'Young',1=>'Older'}\n      @b.name=\"Age\"\n      @anova=Statsample::Anova::TwoWayWithVectors.new(:a=>@a,:b=>@b, :dependent=>@pa)\n    end\n    should \"Statsample::Anova respond to #twoway_with_vectors\" do\n    assert(Statsample::Anova.respond_to? :twoway_with_vectors)\n    end\n    should \"#new returns the same as Statsample::Anova.twoway_with_vectors\" do\n      @anova2=Statsample::Anova.twoway_with_vectors(:a=>@a,:b=>@b, :dependent=>@pa)\n      assert_equal(@anova.summary, @anova2.summary)\n    end\n    should \"return correct value for ms_a, ms_b and ms_axb\" do\n      assert_in_delta(192.2, @anova.ms_a, 0.01)\n      assert_in_delta(57.8, @anova.ms_b, 0.01)\n      assert_in_delta(168.2, @anova.ms_axb, 0.01)\n      \n    end\n    should \"return correct value for f \" do\n      assert_in_delta(40.68, @anova.f_a, 0.01)\n      assert_in_delta(12.23, @anova.f_b, 0.01)\n      assert_in_delta(35.60, @anova.f_axb, 0.01)\n    end\n    should \"return correct value for probability for f \" do\n      assert(@anova.f_a_probability < 0.05)\n      assert(@anova.f_b_probability < 0.05)\n      assert(@anova.f_axb_probability < 0.05)\n    end\n\n    should \"respond to summary\" do\n      \n      @anova.summary_descriptives=true\n      @anova.summary_levene=true\n      assert(@anova.respond_to? :summary)\n      assert(@anova.summary.size>0)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_anovawithvectors.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleAnovaOneWayWithVectorsTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Anova::OneWayWithVectors) do\n    \n    context(\"when initializing\") do\n      setup do\n        @v1=10.times.map {rand(100)}.to_scale\n        @v2=10.times.map {rand(100)}.to_scale\n        @v3=10.times.map {rand(100)}.to_scale\n      end\n      should \"be the same using [] or args*\" do\n        a1=Statsample::Anova::OneWayWithVectors.new(@v1,@v2,@v3)\n        a2=Statsample::Anova::OneWayWithVectors.new([@v1,@v2,@v3])\n        assert_equal(a1.f,a2.f)\n      end\n      should \"be the same using module method or object instantiation\" do\n        a1=Statsample::Anova::OneWayWithVectors.new(@v1,@v2,@v3)\n        a2=Statsample::Anova.oneway_with_vectors(@v1,@v2,@v3)\n        assert_equal(a1.f,a2.f)\n      end\n      should \"detect optional hash\" do\n        a1=Statsample::Anova::OneWayWithVectors.new(@v1,@v2,@v3, {:name=>'aaa'})\n        assert_equal('aaa', a1.name)\n      end\n      should \"omit incorrect arguments\" do\n        a1=Statsample::Anova::OneWayWithVectors.new(@v1,@v2,@v3, {:name=>'aaa'})\n        a2=Statsample::Anova::OneWayWithVectors.new(@v1,nil,nil,@v2,@v3, {:name=>'aaa'})\n        assert_equal(a1.f,a2.f)\n      end\n    end\n    setup do\n      @v1=[3,3,2,3,6].to_vector(:scale)\n      @v2=[7,6,5,6,7].to_vector(:scale)\n      @v3=[9,8,9,7,8].to_vector(:scale)\n      @name=\"Anova testing\"\n      @anova=Statsample::Anova::OneWayWithVectors.new(@v1,@v2,@v3, :name=>@name)\n    end\n    should \"store correctly contrasts\" do\n      c1=Statsample::Anova::Contrast.new(:vectors=>[@v1,@v2,@v3], :c=>[1,-0.5, -0.5])\n      \n      c2=@anova.contrast(:c=>[1,-0.5,-0.5])\n      assert_equal(c1.t,c2.t)\n      \n    end\n    should \"respond to #summary\" do\n      assert(@anova.respond_to? :summary)\n    end\n    should \"have correct name of analysis on #summary\" do\n      assert_match(/#{@name}/, @anova.summary)\n    end\n    should \"returns same levene values as direct Levene creation\" do\n      assert_equal(@anova.levene.f, Statsample::Test.levene([@v1,@v2,@v3]).f)\n    end\n    should \"have correct value for levene\" do\n      assert_in_delta(0.604,@anova.levene.f, 0.001)\n      assert_in_delta(0.562,@anova.levene.probability, 0.001)\n    end\n    should \"have correct value for sst\" do\n     assert_in_delta(72.933, @anova.sst,0.001)\n    end\n    should \"have correct value for sswg\" do\n      assert_in_delta(14.8,@anova.sswg,0.001)\n    end\n    should \"have correct value for ssb\" do\n      assert_in_delta(58.133,@anova.ssbg,0.001)\n    end\n    should \"sst=sswg+ssbg\" do\n      assert_in_delta(@anova.sst,@anova.sswg+@anova.ssbg,0.00001)\n    end\n    should \"df total equal to number of n-1\" do\n      assert_equal(@v1.n+@v2.n+@v3.n-1,@anova.df_total)\n    end\n    should \"df wg equal to number of n-k\" do\n      assert_equal(@v1.n+@v2.n+@v3.n-3,@anova.df_wg)\n    end\n    should \"df bg equal to number of k-1\" do\n      assert_equal(2,@anova.df_bg)\n    end\n    should \"f=(ssbg/df_bg)/(sswt/df_wt)\" do\n      assert_in_delta((@anova.ssbg.quo(@anova.df_bg)).quo( @anova.sswg.quo(@anova.df_wg)), @anova.f, 0.001)\n    end\n    should \"p be correct\" do\n      assert(@anova.probability<0.01)\n    end\n    should \"be correct using different test values\" do\n      anova2=Statsample::Anova::OneWayWithVectors.new([@v1,@v1,@v1,@v1,@v2])\n      assert_in_delta(3.960, anova2.f,0.001)\n      assert_in_delta(0.016, anova2.probability,0.001)\n    end\n    context \"with extra information on summary\" do\n      setup do\n        @anova.summary_descriptives=true\n        @anova.summary_levene=true\n        @summary=@anova.summary\n      end\n      should \"have section with levene statistics\" do\n        assert_match(/Levene/, @summary)\n      end\n      should \"have section with descriptives\" do\n        assert_match(/Min/, @summary)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_awesome_print_bug.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleAwesomePrintBug < MiniTest::Test\n  context(\"Awesome Print integration\") do\n    setup do\n      require \"awesome_print\"\n    end\n    should \"should be flawless\" do\n      a=[1,2,3].to_scale\n      \n      assert(a!=[1,2,3])\n      assert_nothing_raised do \n        ap a\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_bartlettsphericity.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleBartlettSphericityTestCase < MiniTest::Test\n  include Statsample::Test\n  context Statsample::Test::BartlettSphericity do\n    setup do\n      @v1=[1 ,2 ,3 ,4 ,7 ,8 ,9 ,10,14,15,20,50,60,70].to_scale\n      @v2=[5 ,6 ,11,12,13,16,17,18,19,20,30,0,0,0].to_scale\n      @v3=[10,3 ,20,30,40,50,80,10,20,30,40,2,3,4].to_scale\n      # KMO: 0.490\n      ds={'v1'=>@v1,'v2'=>@v2,'v3'=>@v3}.to_dataset\n      cor=Statsample::Bivariate.correlation_matrix(ds)\n      @bs=Statsample::Test::BartlettSphericity.new(cor, 14)\n    end\n    should \"have correct value for chi\" do\n      assert_in_delta(9.477, @bs.value,0.001)\n    end\n    should \"have correct value for df\" do\n      assert_equal(3, @bs.df)\n    end\n    should \"have correct value for probability\" do\n      assert_in_delta(0.024,@bs.probability,0.001)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_bivariate.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleBivariateTestCase < MiniTest::Test\n  should \"method sum of squares should be correct\" do\n    v1=[1,2,3,4,5,6].to_vector(:scale)\n    v2=[6,2,4,10,12,8].to_vector(:scale)\n    assert_equal(23.0, Statsample::Bivariate.sum_of_squares(v1,v2))\n  end\n  should_with_gsl \"return same covariance with ruby and gls implementation\" do\n    v1=20.times.collect {|a| rand()}.to_scale\n    v2=20.times.collect {|a| rand()}.to_scale\n    assert_in_delta(Statsample::Bivariate.covariance(v1,v2), Statsample::Bivariate.covariance_slow(v1,v2), 0.001)\n  end\n\n  should_with_gsl \"return same correlation with ruby and gls implementation\" do\n    v1=20.times.collect {|a| rand()}.to_scale\n    v2=20.times.collect {|a| rand()}.to_scale\n\n    assert_in_delta(GSL::Stats::correlation(v1.gsl, v2.gsl), Statsample::Bivariate.pearson_slow(v1,v2), 1e-10)\n  end\n  should \"return correct pearson correlation\" do\n    v1=[6,5,4,7,8,4,3,2].to_vector(:scale)\n    v2=[2,3,7,8,6,4,3,2].to_vector(:scale)\n    assert_in_delta(0.525,Statsample::Bivariate.pearson(v1,v2), 0.001)\n    assert_in_delta(0.525,Statsample::Bivariate.pearson_slow(v1,v2), 0.001)\n\n    v3=[6,2,  1000,1000,5,4,7,8,4,3,2,nil].to_vector(:scale)\n    v4=[2,nil,nil,nil,  3,7,8,6,4,3,2,500].to_vector(:scale)\n    assert_in_delta(0.525,Statsample::Bivariate.pearson(v3,v4),0.001)\n    # Test ruby method\n    v3a,v4a=Statsample.only_valid v3, v4\n    assert_in_delta(0.525, Statsample::Bivariate.pearson_slow(v3a,v4a),0.001)\n  end\n  should \"return correct values for t_pearson and prop_pearson\" do\n    v1=[6,5,4,7,8,4,3,2].to_vector(:scale)\n    v2=[2,3,7,8,6,4,3,2].to_vector(:scale)\n    r=Statsample::Bivariate::Pearson.new(v1,v2)\n    assert_in_delta(0.525,r.r, 0.001)\n    assert_in_delta(Statsample::Bivariate.t_pearson(v1,v2), r.t, 0.001)\n    assert_in_delta(Statsample::Bivariate.prop_pearson(r.t,8,:both), r.probability, 0.001)\n    assert(r.summary.size>0)\n  end\n  should \"return correct correlation_matrix with nils values\" do\n    v1=[6,5,4,7,8,4,3,2].to_vector(:scale)\n    v2=[2,3,7,8,6,4,3,2].to_vector(:scale)\n    v3=[6,2,  1000,1000,5,4,7,8].to_vector(:scale)\n    v4=[2,nil,nil,nil,  3,7,8,6].to_vector(:scale)\n    ds={'v1'=>v1,'v2'=>v2,'v3'=>v3,'v4'=>v4}.to_dataset\n    c=Proc.new {|n1,n2|Statsample::Bivariate.pearson(n1,n2)}\n    expected=Matrix[ [c.call(v1,v1),c.call(v1,v2),c.call(v1,v3),c.call(v1,v4)], [c.call(v2,v1),c.call(v2,v2),c.call(v2,v3),c.call(v2,v4)], [c.call(v3,v1),c.call(v3,v2),c.call(v3,v3),c.call(v3,v4)],\n      [c.call(v4,v1),c.call(v4,v2),c.call(v4,v3),c.call(v4,v4)]\n    ]\n    obt=Statsample::Bivariate.correlation_matrix(ds)\n    for i in 0...expected.row_size\n      for j in 0...expected.column_size\n        #puts expected[i,j].inspect\n        #puts obt[i,j].inspect\n        assert_in_delta(expected[i,j], obt[i,j],0.0001, \"#{expected[i,j].class}!=#{obt[i,j].class}  \")\n      end\n    end\n    #assert_equal(expected,obt)\n  end\n  should_with_gsl \"return same values for optimized and pairwise covariance matrix\" do\n      cases=100\n      v1=Statsample::Vector.new_scale(cases) {rand()}\n      v2=Statsample::Vector.new_scale(cases) {rand()}\n      v3=Statsample::Vector.new_scale(cases) {rand()}\n      v4=Statsample::Vector.new_scale(cases) {rand()}\n      v5=Statsample::Vector.new_scale(cases) {rand()}\n\n      ds={'v1'=>v1,'v2'=>v2,'v3'=>v3,'v4'=>v4,'v5'=>v5}.to_dataset\n      \n      cor_opt=Statsample::Bivariate.covariance_matrix_optimized(ds)\n      \n      cor_pw =Statsample::Bivariate.covariance_matrix_pairwise(ds)\n      assert_equal_matrix(cor_opt,cor_pw,1e-15)\n  end\n  should_with_gsl \"return same values for optimized and pairwise correlation matrix\" do\n    \n    cases=100\n    v1=Statsample::Vector.new_scale(cases) {rand()}\n    v2=Statsample::Vector.new_scale(cases) {rand()}\n    v3=Statsample::Vector.new_scale(cases) {rand()}\n    v4=Statsample::Vector.new_scale(cases) {rand()}\n    v5=Statsample::Vector.new_scale(cases) {rand()}\n\n    ds={'v1'=>v1,'v2'=>v2,'v3'=>v3,'v4'=>v4,'v5'=>v5}.to_dataset\n    \n    cor_opt=Statsample::Bivariate.correlation_matrix_optimized(ds)\n    \n    cor_pw =Statsample::Bivariate.correlation_matrix_pairwise(ds)\n    assert_equal_matrix(cor_opt,cor_pw,1e-15)\n    \n  end\n  should \"return correct correlation_matrix without nils values\" do\n    v1=[6,5,4,7,8,4,3,2].to_vector(:scale)\n    v2=[2,3,7,8,6,4,3,2].to_vector(:scale)\n    v3=[6,2,  1000,1000,5,4,7,8].to_vector(:scale)\n    v4=[2,4,6,7,  3,7,8,6].to_vector(:scale)\n    ds={'v1'=>v1,'v2'=>v2,'v3'=>v3,'v4'=>v4}.to_dataset\n    c=Proc.new {|n1,n2|Statsample::Bivariate.pearson(n1,n2)}\n    expected=Matrix[ [c.call(v1,v1),c.call(v1,v2),c.call(v1,v3),c.call(v1,v4)], [c.call(v2,v1),c.call(v2,v2),c.call(v2,v3),c.call(v2,v4)], [c.call(v3,v1),c.call(v3,v2),c.call(v3,v3),c.call(v3,v4)],\n      [c.call(v4,v1),c.call(v4,v2),c.call(v4,v3),c.call(v4,v4)]\n    ]\n    obt=Statsample::Bivariate.correlation_matrix(ds)\n    for i in 0...expected.row_size\n      for j in 0...expected.column_size\n        #puts expected[i,j].inspect\n        #puts obt[i,j].inspect\n        assert_in_delta(expected[i,j], obt[i,j],0.0001, \"#{expected[i,j].class}!=#{obt[i,j].class}  \")\n      end\n    end\n    #assert_equal(expected,obt)\n  end\n\n  \n  should \"return correct value for prop pearson\" do\n    assert_in_delta(0.42, Statsample::Bivariate.prop_pearson(Statsample::Bivariate.t_r(0.084,94), 94),0.01)\n    assert_in_delta(0.65, Statsample::Bivariate.prop_pearson(Statsample::Bivariate.t_r(0.046,95), 95),0.01)\n    r=0.9\n    n=100\n    t=Statsample::Bivariate.t_r(r,n)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:both)<0.05)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:right)<0.05)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:left)>0.05)\n\n    r=-0.9\n    n=100\n    t=Statsample::Bivariate.t_r(r,n)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:both)<0.05)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:right)>0.05)\n    assert(Statsample::Bivariate.prop_pearson(t,n,:left)<0.05)\n  end\n\n  should \"return correct value for Spearman's rho\" do\n    v1=[86,97,99,100,101,103,106,110,112,113].to_vector(:scale)\n    v2=[0,20,28,27,50,29,7,17,6,12].to_vector(:scale)\n    assert_in_delta(-0.175758,Statsample::Bivariate.spearman(v1,v2),0.0001)\n\n  end\n  should \"return correct value for point_biserial correlation\" do\n    c=[1,3,5,6,7,100,200,300,400,300].to_vector(:scale)\n    d=[1,1,1,1,1,0,0,0,0,0].to_vector(:scale)\n    assert_raises TypeError do\n      Statsample::Bivariate.point_biserial(c,d)\n    end\n    assert_in_delta(Statsample::Bivariate.point_biserial(d,c), Statsample::Bivariate.pearson(d,c), 0.0001)\n  end\n  should \"return correct value for tau_a and tau_b\" do\n    v1=[1,2,3,4,5,6,7,8,9,10,11].to_vector(:ordinal)\n    v2=[1,3,4,5,7,8,2,9,10,6,11].to_vector(:ordinal)\n    assert_in_delta(0.6727,Statsample::Bivariate.tau_a(v1,v2),0.001)\n    assert_in_delta(0.6727,Statsample::Bivariate.tau_b((Statsample::Crosstab.new(v1,v2).to_matrix)),0.001)\n    v1=[12,14,14,17,19,19,19,19,19,20,21,21,21,21,21,22,23,24,24,24,26,26,27].to_vector(:ordinal)\n    v2=[11,4,4,2,0,0,0,0,0,0,4,0,4,0,0,0,0,4,0,0,0,0,0].to_vector(:ordinal)\n    assert_in_delta(-0.376201540231705, Statsample::Bivariate.tau_b(Statsample::Crosstab.new(v1,v2).to_matrix),0.001)\n  end\n  should \"return correct value for gamma correlation\" do\n    m=Matrix[[10,5,2],[10,15,20]]\n    assert_in_delta(0.636,Statsample::Bivariate.gamma(m),0.001)\n    m2=Matrix[[15,12,6,5],[12,8,10,8],[4,6,9,10]]\n    assert_in_delta(0.349,Statsample::Bivariate.gamma(m2),0.001)\n  end\nend\n"
  },
  {
    "path": "test/test_codification.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleCodificationTestCase < MiniTest::Unit::TestCase\n\n  def initialize(*args)\n    v1=%w{run walk,run walking running sleep sleeping,dreaming sleep,dream}.to_vector\n    @dict={'run'=>'r','walk'=>'w','walking'=>'w','running'=>'r','sleep'=>'s', 'sleeping'=>'s', 'dream'=>'d', 'dreaming'=>'d'}\n    @ds={\"v1\"=>v1}.to_dataset\n    super\n  end\n  def test_create_hash\n    expected_keys_v1=%w{run walk walking running sleep sleeping dream dreaming}.sort\n    hash=Statsample::Codification.create_hash(@ds,['v1'])\n    assert_equal(['v1'],hash.keys)\n    assert_equal(expected_keys_v1,hash['v1'].keys.sort)\n    assert_equal(expected_keys_v1,hash['v1'].values.sort)\n  end\n  def test_create_excel\n    filename=Dir::tmpdir+\"/test_excel\"+Time.now().to_s+\".xls\"\n    #filename = Tempfile.new(\"test_codification_\"+Time.now().to_s)\n    Statsample::Codification.create_excel(@ds, ['v1'], filename)\n    field=([\"v1\"]*8).to_vector\n    keys=%w{dream dreaming run running sleep sleeping walk walking}.to_vector\n    ds=Statsample::Excel.read(filename)\n    assert_equal(field, ds['field'])\n    assert_equal(keys, ds['original'])\n    assert_equal(keys, ds['recoded'])\n    hash=Statsample::Codification.excel_to_recoded_hash(filename)\n    assert_equal(keys.data, hash['v1'].keys.sort)\n    assert_equal(keys.data, hash['v1'].values.sort)\n\n  end\n  def test_create_yaml\n    assert_raise  ArgumentError do\n      Statsample::Codification.create_yaml(@ds,[])\n    end\n    expected_keys_v1=%w{run walk walking running sleep sleeping dream dreaming}.sort\n    yaml_hash=Statsample::Codification.create_yaml(@ds,['v1'])\n    h=YAML::load(yaml_hash)\n    assert_equal(['v1'],h.keys)\n    assert_equal(expected_keys_v1,h['v1'].keys.sort)\n    tf = Tempfile.new(\"test_codification\")\n    yaml_hash=Statsample::Codification.create_yaml(@ds,['v1'],tf, Statsample::SPLIT_TOKEN)\n    tf.close\n    tf.open\n    h=YAML::load(tf)\n    assert_equal(['v1'],h.keys)\n    assert_equal(expected_keys_v1,h['v1'].keys.sort)\n    tf.close(true)\n  end\n  def test_recodification\n    expected=[['r'],['w','r'],['w'],['r'],['s'],['s','d'], ['s','d']]\n    assert_equal(expected,Statsample::Codification.recode_vector(@ds['v1'],@dict))\n    v2=['run','walk,dreaming',nil,'walk,dream,dreaming,walking'].to_vector\n    expected=[['r'],['w','d'],nil,['w','d']]\n    assert_equal(expected,Statsample::Codification.recode_vector(v2,@dict))\n  end\n  def test_recode_dataset_simple\n    Statsample::Codification.recode_dataset_simple!(@ds,{'v1'=>@dict})\n    expected_vector=['r','w,r','w','r','s','s,d', 's,d'].to_vector\n    assert_not_equal(expected_vector,@ds['v1'])\n    assert_equal(expected_vector,@ds['v1_recoded'])\n  end\n  def test_recode_dataset_split\n    Statsample::Codification.recode_dataset_split!(@ds,{'v1'=>@dict})\n    e={}\n    e['r']=[1,1,0,1,0,0,0].to_vector\n    e['w']=[0,1,1,0,0,0,0].to_vector\n    e['s']=[0,0,0,0,1,1,1].to_vector\n    e['d']=[0,0,0,0,0,1,1].to_vector\n    e.each{|k,expected|\n      assert_equal(expected,@ds['v1_'+k],\"Error on key #{k}\")\n\n    }\n  end\n\nend\n"
  },
  {
    "path": "test/test_crosstab.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleCrosstabTestCase < MiniTest::Unit::TestCase\n\n  def initialize(*args)\n    @v1=%w{black blonde black black red black brown black blonde black red black blonde}.to_vector\n    @v2=%w{woman man man woman man man man woman man woman woman man man}.to_vector\n    @ct=Statsample::Crosstab.new(@v1,@v2)\n    super\n  end\n  def test_crosstab_errors\n    e1=%w{black blonde black black red black brown black blonde black}\n    assert_raise ArgumentError do\n      Statsample::Crosstab.new(e1,@v2)\n    end\n    e2=%w{black blonde black black red black brown black blonde black black}.to_vector\n\n    assert_raise ArgumentError do\n      Statsample::Crosstab.new(e2,@v2)\n    end\n    assert_nothing_raised do\n      Statsample::Crosstab.new(@v1,@v2)\n    end\n  end\n  def test_crosstab_basic\n    assert_equal(%w{black blonde brown red}, @ct.rows_names)\n    assert_equal(%w{man woman}, @ct.cols_names)\n    assert_equal({'black'=>7,'blonde'=>3,'red'=>2,'brown'=>1}, @ct.rows_total)\n    assert_equal({'man'=>8,'woman'=>5}, @ct.cols_total)\n  end\n  def test_crosstab_frequencies\n    fq=@ct.frequencies\n    assert_equal(8,fq.size)\n    sum=fq.inject(0) {|s,x| s+x[1]}\n    assert_equal(13,sum)\n    fr=@ct.frequencies_by_row\n    assert_equal(4,fr.size)\n    assert_equal(%w{black blonde brown red},fr.keys.sort)\n    fc=@ct.frequencies_by_col\n    assert_equal(2,fc.size)\n    assert_equal(%w{man woman},fc.keys.sort)\n    assert_equal(Matrix.rows([[3,4],[3,0],[1,0],[1,1]]),@ct.to_matrix)\n  end\n  def test_summary\n    @ct.percentage_row=true\n    @ct.percentage_column=true\n    @ct.percentage_total=true\n    assert(@ct.summary.size>0)\n  end\n  def test_expected\n    v1=%w{1 1 1 1 1 0 0 0 0 0}.to_vector\n    v2=%w{0 0 0 0 0 1 1 1 1 1}.to_vector\n    ct=Statsample::Crosstab.new(v1,v2)\n    assert_equal(Matrix[[2.5,2.5],[2.5,2.5]],ct.matrix_expected)\n  end\n  def test_crosstab_with_scale\n    v1=%w{1 1 1 1 1 0 0 0 0 0}.to_scale\n    v2=%w{0 0 0 0 0 1 1 1 1 1}.to_scale\n    ct=Statsample::Crosstab.new(v1,v2)\n    assert_equal(Matrix[[0,5],[5,0]],ct.to_matrix)\n    assert_nothing_raised { ct.summary }  \n  end\n\nend\n"
  },
  {
    "path": "test/test_csv.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleCSVTestCase < MiniTest::Unit::TestCase\n  def setup\n    @ds=Statsample::CSV.read(File.dirname(__FILE__)+\"/fixtures/test_csv.csv\")\n  end\n  def test_read\n    assert_equal(6,@ds.cases)\n    assert_equal(%w{id name age city a1}, @ds.fields)\n    id=[1,2,3,4,5,6].to_vector(:scale)\n    name=[\"Alex\",\"Claude\",\"Peter\",\"Franz\",\"George\",\"Fernand\"].to_vector(:nominal)\n    age=[20,23,25,27,5.5,nil].to_vector(:scale)\n    city=[\"New York\",\"London\",\"London\",\"Paris\",\"Tome\",nil].to_vector(:nominal)\n    a1=[\"a,b\",\"b,c\",\"a\",nil,\"a,b,c\",nil].to_vector(:nominal)\n    ds_exp=Statsample::Dataset.new({'id'=>id,'name'=>name,'age'=>age,'city'=>city,'a1'=>a1}, %w{id name age city a1})\n    ds_exp.fields.each{|f|\n      assert_equal(ds_exp[f],@ds[f])\n    }\n    assert_equal(ds_exp,@ds)\n  end\n  def test_nil\n    assert_equal(nil,@ds['age'][5])\n  end\n  def test_repeated\n    ds=Statsample::CSV.read(File.dirname(__FILE__)+\"/fixtures/repeated_fields.csv\")\n    assert_equal(%w{id name_1 age_1 city a1 name_2 age_2},ds.fields)\n    age=[3,4,5,6,nil,8].to_vector(:scale)\n    assert_equal(age,ds['age_2'])\n  end\n  def test_write\n    filename=Tempfile.new(\"afile\")\n    #  filename=Dir::tmpdir+\"/test_write.csv\"\n    Statsample::CSV.write(@ds, filename.path)\n    ds2=Statsample::CSV.read(filename.path)\n    i=0\n    ds2.each_array{|row|\n      assert_equal(@ds.case_as_array(i),row)\n      i+=1\n    }\n  end\nend\n=begin\nclass StatsampleCSVTestCase2 < MiniTest::Unit::TestCase\n  def setup\n    @ds=Statsample::CSV.read19(File.dirname(__FILE__)+\"/fixtures/test_csv.csv\")\n  end\n  def test_read\n    assert_equal(6,@ds.cases)\n    assert_equal(%w{id name age city a1}, @ds.fields)\n    id=[1,2,3,4,5,6].to_vector(:scale)\n    name=[\"Alex\",\"Claude\",\"Peter\",\"Franz\",\"George\",\"Fernand\"].to_vector(:nominal)\n    age=[20,23,25,27,5.5,nil].to_vector(:scale)\n    city=[\"New York\",\"London\",\"London\",\"Paris\",\"Tome\",nil].to_vector(:nominal)\n    a1=[\"a,b\",\"b,c\",\"a\",nil,\"a,b,c\",nil].to_vector(:nominal)\n    ds_exp=Statsample::Dataset.new({'id'=>id,'name'=>name,'age'=>age,'city'=>city,'a1'=>a1}, %w{id name age city a1})\n    ds_exp.fields.each{|f|\n      assert_equal(ds_exp[f],@ds[f])\n    }\n    assert_equal(ds_exp,@ds)\n  end\n  def test_nil\n    assert_equal(nil,@ds['age'][5])\n  end\n  def test_repeated\n    ds=Statsample::CSV.read19(File.dirname(__FILE__)+\"/fixtures/repeated_fields.csv\")\n    assert_equal(%w{id name_1 age_1 city a1 name_2 age_2},ds.fields)\n    age=[3,4,5,6,nil,8].to_vector(:scale)\n    assert_equal(age,ds['age_2'])\n  end\n  def test_write\n    filename=Tempfile.new(\"afile\")\n    #  filename=Dir::tmpdir+\"/test_write.csv\"\n    Statsample::CSV.write(@ds, filename.path)\n    ds2=Statsample::CSV.read19(filename.path)\n    i=0\n    ds2.each_array{|row|\n      assert_equal(@ds.case_as_array(i),row)\n      i+=1\n    }\n  end\nend\n=end\n"
  },
  {
    "path": "test/test_dataset.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleDatasetTestCase < MiniTest::Unit::TestCase\n  def setup\n    @ds=Statsample::Dataset.new({'id' => Statsample::Vector.new([1,2,3,4,5]), 'name'=>Statsample::Vector.new(%w{Alex Claude Peter Franz George}), 'age'=>Statsample::Vector.new([20,23,25,27,5]),\n      'city'=>Statsample::Vector.new(['New York','London','London','Paris','Tome']),\n    'a1'=>Statsample::Vector.new(['a,b','b,c','a',nil,'a,b,c'])}, ['id','name','age','city','a1'])\n  end\n  def test_nest\n    ds={\n      'a'=>%w{a a a b b b}.to_vector,\n      'b'=>%w{c c d d e e}.to_vector,\n      'c'=>%w{f g h i j k}.to_vector\n    }.to_dataset\n    nest=ds.nest('a','b')\n    assert_equal([{'c'=>'f'},{'c'=>'g'}], nest['a']['c'])\n    assert_equal([{'c'=>'h'}], nest['a']['d'])\n    assert_equal([{'c'=>'j'},{'c'=>'k'}], nest['b']['e'])\n   \n  end\n  def test_should_have_summary\n    assert(@ds.summary.size>0)\n  end\n  def test_basic\n    assert_equal(5,@ds.cases)\n    assert_equal(%w{id name age city a1}, @ds.fields)\n  end\n  def test_saveload\n    outfile=Tempfile.new(\"dataset.ds\")\n    @ds.save(outfile.path)\n    a=Statsample.load(outfile.path)\n    assert_equal(@ds,a)\n  end\n  def test_gsl\n    if Statsample.has_gsl?\n      matrix=GSL::Matrix[[1,2],[3,4],[5,6]]\n      ds=Statsample::Dataset.new('v1'=>[1,3,5].to_vector,'v2'=>[2,4,6].to_vector)\n      assert_equal(matrix,ds.to_gsl)\n    else\n      skip(\"Gsl needed\")\n    end\n  end\n  def test_matrix\n    matrix=Matrix[[1,2],[3,4],[5,6]]\n    ds=Statsample::Dataset.new('v1'=>[1,3,5].to_vector,'v2'=>[2,4,6].to_vector)\n    assert_equal(matrix,ds.to_matrix)\n  end\n\n  def test_fields\n    @ds.fields=%w{name a1 id age city}\n    assert_equal(%w{name a1 id age city}, @ds.fields)\n    @ds.fields=%w{id name age}\n    assert_equal(%w{id name age a1 city}, @ds.fields)\n  end\n  def test_merge\n    a=[1,2,3].to_scale\n    b=[3,4,5].to_vector\n    c=[4,5,6].to_scale\n    d=[7,8,9].to_vector\n    e=[10,20,30].to_vector\n    ds1={'a'=>a,'b'=>b}.to_dataset\n    ds2={'c'=>c,'d'=>d}.to_dataset\n    exp={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n\n    assert_equal(exp,ds1.merge(ds2))\n    exp.fields=%w{c d a b}\n    assert_equal(exp,ds2.merge(ds1))\n    ds3={'a'=>e}.to_dataset\n    exp={'a_1'=>a,'b'=>b,'a_2'=>e}.to_dataset\n    exp.fields=%w{a_1 b a_2}\n    assert_equal(exp,ds1.merge(ds3))\n  end\n  def test_each_vector\n    a=[1,2,3].to_vector\n    b=[3,4,5].to_vector\n    fields=[\"a\",\"b\"]\n    ds=Statsample::Dataset.new({'a'=>a,'b'=>b},fields)\n    res=[]\n    ds.each_vector{|k,v|\n      res.push([k,v])\n    }\n    assert_equal([[\"a\",a],[\"b\",b]],res)\n    ds.fields=[\"b\",\"a\"]\n    res=[]\n    ds.each_vector{|k,v|\n      res.push([k,v])\n    }\n    assert_equal([[\"b\",b],[\"a\",a]],res)\n  end\n  def test_equality\n    v1=[1,2,3,4].to_vector\n    v2=[5,6,7,8].to_vector\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2}, %w{v2 v1})\n    v3=[1,2,3,4].to_vector\n    v4=[5,6,7,8].to_vector\n    ds2=Statsample::Dataset.new({'v1'=>v3,'v2'=>v4}, %w{v2 v1})\n    assert_equal(ds1,ds2)\n    ds2.fields=%w{v1 v2}\n    assert_not_equal(ds1,ds2)\n  end\n  def test_add_vector\n    v=Statsample::Vector.new(%w{a b c d e})\n    @ds.add_vector('new',v)\n    assert_equal(%w{id name age city a1 new},@ds.fields)\n    x=Statsample::Vector.new(%w{a b c d e f g})\n    assert_raise ArgumentError do\n      @ds.add_vector('new2',x)\n    end\n  end\n  def test_vector_by_calculation\n    a1=[1,2,3,4,5,6,7].to_vector(:scale)\n    a2=[10,20,30,40,50,60,70].to_vector(:scale)\n    a3=[100,200,300,400,500,600,700].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'a3'=>a3}.to_dataset\n    total=ds.vector_by_calculation() {|row|\n      row['a1']+row['a2']+row['a3']\n    }\n    expected=[111,222,333,444,555,666,777].to_vector(:scale)\n    assert_equal(expected,total)\n  end\n  def test_vector_sum\n    a1=[1  ,2 ,3 ,4  , 5,nil].to_vector(:scale)\n    a2=[10 ,10,20,20 ,20,30].to_vector(:scale)\n    b1=[nil,1 ,1 ,1  ,1 ,2].to_vector(:scale)\n    b2=[2  ,2 ,2 ,nil,2 ,3].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'b1'=>b1,'b2'=>b2}.to_dataset\n    total=ds.vector_sum\n    a=ds.vector_sum(['a1','a2'])\n    b=ds.vector_sum(['b1','b2'])\n    expected_a=[11,12,23,24,25,nil].to_vector(:scale)\n    expected_b=[nil,3,3,nil,3,5].to_vector(:scale)\n    expected_total=[nil,15,26,nil,28,nil].to_vector(:scale)\n    assert_equal(expected_a, a)\n    assert_equal(expected_b, b)\n    assert_equal(expected_total, total)\n  end\n  def test_vector_missing_values\n    a1=[1  ,nil ,3 ,4  , 5,nil].to_vector(:scale)\n    a2=[10 ,nil ,20,20 ,20,30].to_vector(:scale)\n    b1=[nil,nil ,1 ,1  ,1 ,2].to_vector(:scale)\n    b2=[2  ,2   ,2 ,nil,2 ,3].to_vector(:scale)\n    c= [nil,2   , 4,2   ,2 ,2].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'b1'=>b1,'b2'=>b2,'c'=>c}.to_dataset\n    mva=[2,3,0,1,0,1].to_vector(:scale)\n    assert_equal(mva,ds.vector_missing_values)\n  end\n  \n  def test_has_missing_values\n    a1=[1  ,nil ,3 ,4  , 5,nil].to_vector(:scale)\n    a2=[10 ,nil ,20,20 ,20,30].to_vector(:scale)\n    b1=[nil,nil ,1 ,1  ,1 ,2].to_vector(:scale)\n    b2=[2  ,2   ,2 ,nil,2 ,3].to_vector(:scale)\n    c= [nil,2   , 4,2   ,2 ,2].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'b1'=>b1,'b2'=>b2,'c'=>c}.to_dataset\n    assert(ds.has_missing_data?)\n    clean=ds.dup_only_valid\n    assert(!clean.has_missing_data?)\n  end\n  \n  \n  def test_vector_count_characters\n    a1=[1  ,\"abcde\"  ,3  ,4  , 5,nil].to_vector(:scale)\n    a2=[10 ,20.3     ,20 ,20 ,20,30].to_vector(:scale)\n    b1=[nil,\"343434\" ,1  ,1  ,1 ,2].to_vector(:scale)\n    b2=[2  ,2        ,2  ,nil,2 ,3].to_vector(:scale)\n    c= [nil,2        ,\"This is a nice example\",2   ,2 ,2].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'b1'=>b1,'b2'=>b2,'c'=>c}.to_dataset\n    exp=[4,17,27,5,6,5].to_vector(:scale)\n    assert_equal(exp,ds.vector_count_characters)\n\n  end\n  def test_vector_mean\n    a1=[1  ,2 ,3 ,4  , 5,nil].to_vector(:scale)\n    a2=[10 ,10,20,20 ,20,30].to_vector(:scale)\n    b1=[nil,1 ,1 ,1  ,1 ,2].to_vector(:scale)\n    b2=[2  ,2 ,2 ,nil,2 ,3].to_vector(:scale)\n    c= [nil,2, 4,2   ,2 ,2].to_vector(:scale)\n    ds={'a1'=>a1,'a2'=>a2,'b1'=>b1,'b2'=>b2,'c'=>c}.to_dataset\n    total=ds.vector_mean\n    a=ds.vector_mean(['a1','a2'],1)\n    b=ds.vector_mean(['b1','b2'],1)\n    c=ds.vector_mean(['b1','b2','c'],1)\n    expected_a=[5.5,6,11.5,12,12.5,30].to_vector(:scale)\n    expected_b=[2,1.5,1.5,1,1.5,2.5].to_vector(:scale)\n    expected_c=[nil, 5.0/3,7.0/3,1.5,5.0/3,7.0/3].to_vector(:scale)\n    expected_total=[nil,3.4,6,nil,6.0,nil].to_vector(:scale)\n    assert_equal(expected_a, a)\n    assert_equal(expected_b, b)\n    assert_equal(expected_c, c)\n    assert_equal(expected_total, total)\n  end\n\n  def test_each_array\n    expected=[[1,'Alex',20,'New York','a,b'], [2,'Claude',23,'London','b,c'], [3,'Peter',25,'London','a'],[4,'Franz', 27,'Paris',nil],[5,'George',5,'Tome','a,b,c']]\n    out=[]\n    @ds.each_array{ |a|\n      out.push(a)\n    }\n    assert_equal(expected,out)\n  end\n  def test_recode\n    @ds['age'].type=:scale\n    @ds.recode!(\"age\") {|c| c['id']*2}\n    expected=[2,4,6,8,10].to_vector(:scale)\n    assert_equal(expected,@ds['age'])\n  end\n  def test_case_as\n    assert_equal({'id'=>1,'name'=>'Alex','city'=>'New York','age'=>20,'a1'=>'a,b'},@ds.case_as_hash(0))\n    assert_equal([5,'George',5,'Tome','a,b,c'],@ds.case_as_array(4))\n    # Native methods\n    assert_equal({'id'=>1,'name'=>'Alex','city'=>'New York','age'=>20,'a1'=>'a,b'},@ds._case_as_hash(0))\n    assert_equal([5,'George',5,'Tome','a,b,c'],@ds._case_as_array(4))\n\n\n\n  end\n  def test_delete_vector\n    @ds.delete_vector('name')\n    assert_equal(%w{id age city a1},@ds.fields)\n    assert_equal(%w{a1 age city id},@ds.vectors.keys.sort)\n  end\n  def test_change_type\n    @ds.col('age').type=:scale\n    assert_equal(:scale,@ds.col('age').type)\n  end\n  def test_split_by_separator_recode\n    @ds.add_vectors_by_split_recode(\"a1\",\"_\")\n    assert_equal(%w{id name age city a1 a1_1 a1_2 a1_3},@ds.fields)\n    assert_equal([1,0,1,nil,1],@ds.col('a1_1').to_a)\n    assert_equal([1,1,0,nil,1],@ds.col('a1_2').to_a)\n    assert_equal([0,1,0,nil,1],@ds.col('a1_3').to_a)\n    {'a1_1'=>'a1:a', 'a1_2'=>'a1:b', 'a1_3'=>'a1:c'}.each do |k,v|\n      assert_equal(v, @ds[k].name)\n    end\n  end\n  def test_split_by_separator\n    @ds.add_vectors_by_split(\"a1\",\"_\")\n    assert_equal(%w{id name age city a1 a1_a a1_b a1_c},@ds.fields)\n    assert_equal([1,0,1,nil,1],@ds.col('a1_a').to_a)\n    assert_equal([1,1,0,nil,1],@ds.col('a1_b').to_a)\n    assert_equal([0,1,0,nil,1],@ds.col('a1_c').to_a)\n  end\n  def test_percentiles\n    v1=(1..100).to_a.to_scale\n    assert_equal(50.5,v1.median)\n    assert_equal(25.5, v1.percentil(25))\n    v2=(1..99).to_a.to_scale\n    assert_equal(50,v2.median)\n    assert_equal(25,v2.percentil(25))\n    v3=(1..50).to_a.to_scale\n    assert_equal(25.5, v3.median)\n    assert_equal(13, v3.percentil(25))\n\n  end\n  def test_add_case\n    ds=Statsample::Dataset.new({'a'=>[].to_vector, 'b'=>[].to_vector, 'c'=>[].to_vector})\n    ds.add_case([1,2,3])\n    ds.add_case({'a'=>4,'b'=>5,'c'=>6})\n    ds.add_case([[7,8,9],%w{a b c}])\n    assert_equal({'a'=>1,'b'=>2,'c'=>3},ds.case_as_hash(0))\n    assert_equal([4,5,6],ds.case_as_array(1))\n    assert_equal([7,8,9],ds.case_as_array(2))\n    assert_equal(['a','b','c'],ds.case_as_array(3))\n    ds.add_case_array([6,7,1])\n    ds.update_valid_data\n    assert_equal([6,7,1],ds.case_as_array(4))\n\n  end\n  def test_marshaling\n    ds_marshal=Marshal.load(Marshal.dump(@ds))\n    assert_equal(ds_marshal,@ds)\n  end\n  def test_range\n    v1=[1,2,3,4].to_vector\n    v2=[5,6,7,8].to_vector\n    v3=[9,10,11,12].to_vector\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2,'v3'=>v3}, %w{v3 v2 v1})\n    assert_same(v1,ds1['v1'])\n    ds2=ds1[\"v2\"..\"v1\"]\n    assert_equal(%w{v2 v1},ds2.fields)\n    assert_same(ds1['v1'],ds2['v1'])\n    assert_same(ds1['v2'],ds2['v2'])\n\n\n  end\n  def test_clone\n    v1=[1,2,3,4].to_vector\n    v2=[5,6,7,8].to_vector\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2}, %w{v2 v1})\n    ds2=ds1.clone\n    assert_equal(ds1,ds2)\n    assert_not_same(ds1,ds2)\n    assert_equal(ds1['v1'],ds2['v1'])\n    assert_same(ds1['v1'], ds2['v1'])\n    assert_equal(ds1.fields,ds2.fields)\n    assert_not_same(ds1.fields,ds2.fields)\n    assert_equal(ds1.cases,ds2.cases)\n\n    # partial clone\n    ds3=ds1.clone('v1')\n    ds_exp=Statsample::Dataset.new({'v1'=>v1},%w{v1})\n    assert_equal(ds_exp,ds3)\n    assert_not_same(ds_exp,ds3)\n    assert_equal(ds3['v1'],ds_exp['v1'])\n    assert_same(ds3['v1'],ds_exp['v1'])\n    assert_equal(ds3.fields,ds_exp.fields)\n    assert_equal(ds3.cases,ds_exp.cases)\n\n    assert_not_same(ds3.fields,ds_exp.fields)\n     \n  end\n  def test_dup\n    v1=[1,2,3,4].to_vector\n    v2=[5,6,7,8].to_vector\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2}, %w{v2 v1})\n    ds2=ds1.dup\n    assert_equal(ds1,ds2)\n    assert_not_same(ds1,ds2)\n    assert_equal(ds1['v1'],ds2['v1'])\n    assert_not_same(ds1['v1'],ds2['v1'])\n    assert_equal(ds1.cases,ds2.cases)\n\n    assert_equal(ds1.fields,ds2.fields)\n    assert_not_same(ds1.fields,ds2.fields)\n    ds1['v1'].type=:scale\n    # dup partial\n    ds3=ds1.dup('v1')\n    ds_exp=Statsample::Dataset.new({'v1'=>v1},%w{v1})\n    assert_equal(ds_exp,ds3)\n    assert_not_same(ds_exp,ds3)\n    assert_equal(ds3['v1'],ds_exp['v1'])\n    assert_not_same(ds3['v1'],ds_exp['v1'])\n    assert_equal(ds3.fields,ds_exp.fields)\n    assert_equal(ds3.cases,ds_exp.cases)\n\n    assert_not_same(ds3.fields,ds_exp.fields)\n\n\n    # empty\n    ds3=ds1.dup_empty\n    assert_not_equal(ds1,ds3)\n    assert_not_equal(ds1['v1'],ds3['v1'])\n    assert_equal([],ds3['v1'].data)\n    assert_equal([],ds3['v2'].data)\n    assert_equal(:scale,ds3['v1'].type)\n    assert_equal(ds1.fields,ds2.fields)\n    assert_not_same(ds1.fields,ds2.fields)\n  end\n  def test_from_to\n    assert_equal(%w{name age city}, @ds.from_to(\"name\",\"city\"))\n    assert_raise ArgumentError do\n      @ds.from_to(\"name\",\"a2\")\n    end\n  end\n  def test_each_array_with_nils\n    v1=[1,-99,3,4,\"na\"].to_vector(:scale,:missing_values=>[-99,\"na\"])\n    v2=[5,6,-99,8,20].to_vector(:scale,:missing_values=>[-99])\n    v3=[9,10,11,12,20].to_vector(:scale,:missing_values=>[-99])\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2,'v3'=>v3})\n    ds2=ds1.dup_empty\n    ds1.each_array_with_nils {|row|\n      ds2.add_case_array(row)\n    }\n    ds2.update_valid_data\n    assert_equal([1,nil,3,4,nil],ds2['v1'].data)\n    assert_equal([5,6,nil,8,20],ds2['v2'].data)\n  end\n  def test_dup_only_valid\n    v1=[1,nil,3,4].to_vector(:scale)\n    v2=[5,6,nil,8].to_vector(:scale)\n    v3=[9,10,11,12].to_vector(:scale)\n    ds1=Statsample::Dataset.new({'v1'=>v1,'v2'=>v2,'v3'=>v3})\n    ds2=ds1.dup_only_valid\n    expected=Statsample::Dataset.new({'v1'=>[1,4].to_vector(:scale), 'v2'=> [5,8].to_vector(:scale), 'v3'=>[9, 12].to_vector(:scale)})\n    assert_equal(expected,ds2)\n    assert_equal(expected.vectors.values,Statsample::only_valid(v1,v2,v3))\n    expected_partial=Statsample::Dataset.new({'v1'=>[1,3,4].to_vector(:scale), 'v3'=>[9, 11,12].to_vector(:scale)})\n    assert_equal(expected_partial, ds1.dup_only_valid(%w{v1 v3}))\n    \n    \n  end\n  def test_filter\n    @ds['age'].type=:scale\n    filtered=@ds.filter{|c| c['id']==2 or c['id']==4}\n    expected=Statsample::Dataset.new({'id' => Statsample::Vector.new([2,4]), 'name'=>Statsample::Vector.new(%w{Claude Franz}), 'age'=>Statsample::Vector.new([23,27],:scale),\n      'city'=>Statsample::Vector.new(['London','Paris']),\n    'a1'=>Statsample::Vector.new(['b,c',nil,])}, ['id','name','age','city','a1'])\n    assert_equal(expected,filtered)\n  end\n  def test_filter_field\n    @ds['age'].type=:scale\n    filtered=@ds.filter_field('id') {|c| c['id']==2 or c['id']==4}\n    expected=[2,4].to_vector\n    assert_equal(expected,filtered)\n\n  end\n  def test_verify\n    name=%w{r1 r2 r3 r4}.to_vector(:nominal)\n    v1=[1,2,3,4].to_vector(:scale)\n    v2=[4,3,2,1].to_vector(:scale)\n    v3=[10,20,30,40].to_vector(:scale)\n    v4=%w{a b a b}.to_vector(:nominal)\n    ds={'v1'=>v1,'v2'=>v2,'v3'=>v3,'v4'=>v4,'id'=>name}.to_dataset\n    ds.fields=%w{v1 v2 v3 v4 id}\n    #Correct\n    t1=create_test(\"If v4=a, v1 odd\") {|r| r['v4']=='b' or (r['v4']=='a' and r['v1']%2==1)}\n    t2=create_test(\"v3=v1*10\")  {|r| r['v3']==r['v1']*10}\n    # Fail!\n    t3=create_test(\"v4='b'\") {|r| r['v4']=='b'}\n    exp1=[\"1 [1]: v4='b'\", \"3 [3]: v4='b'\"]\n    exp2=[\"1 [r1]: v4='b'\", \"3 [r3]: v4='b'\"]\n    res=ds.verify(t3,t1,t2)\n    assert_equal(exp1,res)\n    res=ds.verify('id',t1,t2,t3)\n    assert_equal(exp2,res)\n  end\n  def test_compute_operation\n    v1=[1,2,3,4].to_vector(:scale)\n    v2=[4,3,2,1].to_vector(:scale)\n    v3=[10,20,30,40].to_vector(:scale)\n    vscale=[1.quo(2),1,3.quo(2),2].to_vector(:scale)\n    vsum=[1+4+10.0,2+3+20.0,3+2+30.0,4+1+40.0].to_vector(:scale)\n    vmult=[1*4,2*3,3*2,4*1].to_vector(:scale)\n    ds={'v1'=>v1,'v2'=>v2,'v3'=>v3}.to_dataset\n    assert_equal(vscale,ds.compute(\"v1/2\"))\n    assert_equal(vsum,ds.compute(\"v1+v2+v3\"))\n    assert_equal(vmult,ds.compute(\"v1*v2\"))\n\n  end\n  def test_crosstab_with_asignation\n    v1=%w{a a a b b b c c c}.to_vector\n    v2=%w{a b c a b c a b c}.to_vector\n    v3=%w{0 1 0 0 1 1 0 0 1}.to_scale\n    ds=Statsample::Dataset.crosstab_by_asignation(v1,v2,v3)\n    assert_equal(:nominal, ds['_id'].type)\n    assert_equal(:scale, ds['a'].type)\n    assert_equal(:scale, ds['b'].type)\n    ev_id=%w{a b c}.to_vector\n    ev_a =%w{0 0 0}.to_scale\n    ev_b =%w{1 1 0}.to_scale\n    ev_c =%w{0 1 1}.to_scale\n    ds2={'_id'=>ev_id, 'a'=>ev_a, 'b'=>ev_b, 'c'=>ev_c}.to_dataset\n    assert_equal(ds, ds2)\n  end\n  def test_one_to_many\n    cases=[\n      ['1','george','red',10,'blue',20,nil,nil],\n      ['2','fred','green',15,'orange',30,'white',20],\n      ['3','alfred',nil,nil,nil,nil,nil,nil]\n    ]\n    ds=Statsample::Dataset.new(%w{id name car_color1 car_value1 car_color2 car_value2 car_color3 car_value3})\n    cases.each {|c| ds.add_case_array c }\n    ds.update_valid_data\n    ids=%w{1 1 2 2 2}.to_vector\n    colors=%w{red blue green orange white}.to_vector\n    values=[10,20,15,30,20].to_vector\n    col_ids=[1,2,1,2,3].to_scale\n    ds_expected={'id'=>ids, '_col_id'=>col_ids, 'color'=>colors, 'value'=>values}.to_dataset(['id','_col_id', 'color','value'])\n    assert_equal(ds_expected, ds.one_to_many(%w{id}, \"car_%v%n\"))\n\n  end\n\nend\n"
  },
  {
    "path": "test/test_dominance_analysis.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleDominanceAnalysisTestCase < MiniTest::Unit::TestCase\n  def test_dominance_univariate\n    # Example from Budescu (1993)\n    m=Matrix[[1, 0.683, 0.154, 0.460, 0.618],[0.683, 1, -0.050, 0.297, 0.461], [0.154, -0.050, 1, 0.006, 0.262],[0.460, 0.297, 0.006, 1, 0.507],[0.618, 0.461, 0.262, 0.507, 1]]\n    m.extend Statsample::CovariateMatrix\n    m.fields=%w{x1 x2 x3 x4 y}\n    da=Statsample::DominanceAnalysis.new(m,'y')\n\n    contr_x1={'x2'=>0.003, 'x3'=>0.028, 'x4'=>0.063}\n    contr_x1.each  do |k,v|\n      assert_in_delta(v, da.models_data[['x1']].contributions[k], 0.001)\n    end\n    assert_in_delta(0.052, da.models_data[['x2','x3','x4']].contributions['x1'], 0.001)\n    expected_dominances=[1, 1, 0.5, 0.5, 0,0]\n    expected_g_dominances=[1, 1, 1, 1, 0,0]\n\n    da.pairs.each_with_index do |a,i|\n      assert_equal(expected_dominances[i], da.total_dominance_pairwise(a[0],a[1]))\n      assert_equal(expected_dominances[i], da.conditional_dominance_pairwise(a[0],a[1]))\n      assert_equal(expected_g_dominances[i], da.general_dominance_pairwise(a[0],a[1]))\n    end\n    assert(da.summary.size>0)\n  end\n  def test_dominance_multivariate\n    m=Matrix[[1.0, -0.19, -0.358, -0.343, 0.359, 0.257], [-0.19, 1.0, 0.26, 0.29, -0.11, -0.11], [-0.358, 0.26, 1.0, 0.54, -0.49, -0.23], [-0.343, 0.29, 0.54, 1.0, -0.22, -0.41], [0.359, -0.11, -0.49, -0.22, 1.0, 0.62], [0.257, -0.11, -0.23, -0.41, 0.62, 1]]\n    m.extend Statsample::CovariateMatrix\n    m.fields=%w{y1 y2 x1 x2 x3 x4}\n    m2=m.submatrix(%w{y1 x1 x2 x3 x4})\n\n\n    da=Statsample::DominanceAnalysis.new(m, ['y1','y2'], :cases=>683, :method_association=>:p2yx)\n\n    contr_x1={'x2'=>0.027, 'x3'=>0.024, 'x4'=>0.017}\n    contr_x1.each  do |k,v|\n      assert_in_delta(v, da.models_data[['x1']].contributions[k], 0.003)\n    end\n\n\n  end\nend\n"
  },
  {
    "path": "test/test_factor.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n#require 'rserve'\n#require 'statsample/rserve_extension'\n\nclass StatsampleFactorTestCase < MiniTest::Unit::TestCase\n  include Statsample::Fixtures\n  # Based on Hardle and Simar\n  def setup\n    @fixtures_dir=File.expand_path(File.dirname(__FILE__)+\"/fixtures\")\n  end\n  # Based on Hurdle example\n  def test_covariance_matrix\n    ds=Statsample::PlainText.read(@fixtures_dir+\"/bank2.dat\", %w{v1 v2 v3 v4 v5 v6})\n    ds.fields.each {|f|\n      ds[f]=ds[f].centered\n    }\n    cm=ds.covariance_matrix\n    pca =Statsample::Factor::PCA.new( cm, :m=>6)\n    #puts pca.summary\n    #puts pca.feature_matrix\n    exp_eig=[2.985, 0.931,0.242, 0.194, 0.085, 0.035].to_scale\n    assert_similar_vector(exp_eig, pca.eigenvalues.to_scale, 0.1)\n    pcs=pca.principal_components(ds)\n    k=6\n    comp_matrix=pca.component_matrix()\n    k.times {|i|\n      pc_id=\"PC_#{i+1}\"\n      k.times {|j| # variable\n          ds_id=\"v#{j+1}\"\n          r= Statsample::Bivariate.correlation(ds[ds_id], pcs[pc_id])\n          assert_in_delta( r, comp_matrix[j,i]) \n        }\n    }\n    \n  end\n  def test_principalcomponents_ruby_gsl\n    \n    ran=Distribution::Normal.rng\n    \n#    @r=::Rserve::Connection.new\n\n    samples=20\n    [3,5,7].each {|k|\n      v={}\n      v[\"x0\"]=samples.times.map { ran.call()}.to_scale.centered\n      (1...k).each {|i|\n        v[\"x#{i}\"]=samples.times.map {|ii| ran.call()*0.5+v[\"x#{i-1}\"][ii]*0.5}.to_scale.centered\n      }\n      \n      ds=v.to_dataset\n      cm=ds.covariance_matrix\n#      @r.assign('ds',ds)\n#      @r.eval('cm<-cor(ds);sm<-eigen(cm, sym=TRUE);v<-sm$vectors')\n#      puts \"eigenvalues\"\n#      puts @r.eval('v').to_ruby.to_s\n      pca_ruby=Statsample::Factor::PCA.new( cm, :m=>k, :use_gsl=>false )\n      pca_gsl =Statsample::Factor::PCA.new( cm, :m=>k, :use_gsl=>true  )\n      pc_ruby = pca_ruby.principal_components(ds)\n      pc_gsl  = pca_gsl.principal_components(ds)\n      # Test component matrix correlation!\n      cm_ruby=pca_ruby.component_matrix\n      #puts cm_ruby.summary\n      k.times {|i|\n        pc_id=\"PC_#{i+1}\"\n        assert_in_delta(pca_ruby.eigenvalues[i], pca_gsl.eigenvalues[i],1e-10)\n        # Revert gsl component values\n        pc_gsl_data= (pc_gsl[pc_id][0]-pc_ruby[pc_id][0]).abs>1e-6 ? pc_gsl[pc_id].recode {|v| -v} : pc_gsl[pc_id] \n        assert_similar_vector(pc_gsl_data, pc_ruby[pc_id], 1e-6,\"PC for #{k} variables\")\n        if false\n        k.times {|j| # variable\n          ds_id=\"x#{j}\"\n          r= Statsample::Bivariate.correlation(ds[ds_id],pc_ruby[pc_id])\n          puts \"#{pc_id}-#{ds_id}:#{r}\"\n        }\n        end\n      }\n    }\n    #@r.close\n  end\n  def test_principalcomponents()\n  principalcomponents(true)\n  principalcomponents(false)\n  \n  end  \n  def principalcomponents(gsl)\n    ran=Distribution::Normal.rng\n    samples=50\n    x1=samples.times.map { ran.call()}.to_scale\n    x2=samples.times.map {|i| ran.call()*0.5+x1[i]*0.5}.to_scale\n    ds={'x1'=>x1,'x2'=>x2}.to_dataset\n    \n    cm=ds.correlation_matrix\n    r=cm[0,1]\n    pca=Statsample::Factor::PCA.new(cm,:m=>2,:use_gsl=>gsl)\n    assert_in_delta(1+r,pca.eigenvalues[0],1e-10)\n    assert_in_delta(1-r,pca.eigenvalues[1],1e-10)\n    hs=1.0 / Math.sqrt(2)\n    assert_equal_vector(Vector[1, 1]*hs, pca.eigenvectors[0])\n    m_1=gsl ? Vector[-1,1] : Vector[1,-1]\n    \n    assert_equal_vector(hs*m_1, pca.eigenvectors[1])    \n    \n    pcs=pca.principal_components(ds)\n    exp_pc_1=ds.collect_with_index {|row,i|\n      hs*(row['x1']+row['x2'])\n    }\n    exp_pc_2=ds.collect_with_index {|row,i|\n      gsl ? hs*(row['x2']-row['x1']) : hs*(row['x1']-row['x2'])\n\n    }\n    assert_similar_vector(exp_pc_1, pcs[\"PC_1\"])\n    assert_similar_vector(exp_pc_2, pcs[\"PC_2\"])\n  end\n  def test_antiimage\n    cor=Matrix[[1,0.964, 0.312],[0.964,1,0.411],[0.312,0.411,1]]\n    expected=Matrix[[0.062,-0.057, 0.074],[-0.057, 0.057, -0.089], [0.074, -0.089, 0.729]]\n    ai=Statsample::Factor.anti_image_covariance_matrix(cor)\n    assert(Matrix.equal_in_delta?(expected, ai, 0.01), \"#{expected.to_s} not equal to #{ai.to_s}\")\n  end\n  def test_kmo\n      @v1=[1 ,2 ,3 ,4 ,7 ,8 ,9 ,10,14,15,20,50,60,70].to_scale\n      @v2=[5 ,6 ,11,12,13,16,17,18,19,20,30,0,0,0].to_scale\n      @v3=[10,3 ,20,30,40,50,80,10,20,30,40,2,3,4].to_scale\n      # KMO: 0.490\n      ds={'v1'=>@v1,'v2'=>@v2,'v3'=>@v3}.to_dataset\n      cor=Statsample::Bivariate.correlation_matrix(ds)\n     kmo=Statsample::Factor.kmo(cor)\n     assert_in_delta(0.667, kmo,0.001)\n     assert_in_delta(0.81, Statsample::Factor.kmo(harman_817),0.01)\n     \n  end\n  def test_kmo_univariate\n    m=harman_817\n    expected=[0.73,0.76,0.84,0.87,0.53,0.93,0.78,0.86]\n    m.row_size.times.map {|i|\n      assert_in_delta(expected[i], Statsample::Factor.kmo_univariate(m,i),0.01)\n    }\n  end\n  # Tested with SPSS and R\n  def test_pca\n      a=[2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2.0, 1.0, 1.5, 1.1].to_scale\n      b=[2.4, 0.7, 2.9, 2.2, 3.0, 2.7, 1.6, 1.1, 1.6, 0.9].to_scale\n      a.recode! {|c| c-a.mean}\n      b.recode! {|c| c-b.mean}\n      ds={'a'=>a,'b'=>b}.to_dataset\n      cov_matrix=Statsample::Bivariate.covariance_matrix(ds)\n      if Statsample.has_gsl?\n        pca=Statsample::Factor::PCA.new(cov_matrix,:use_gsl=>true)\n        pca_set(pca,\"gsl\")\n      else\n        skip(\"Eigenvalues could be calculated with GSL (requires gsl)\")\n      end\n      pca=Statsample::Factor::PCA.new(cov_matrix,:use_gsl=>false)\n      pca_set(pca,\"ruby\")\n  end\n  def pca_set(pca,type)\n      expected_eigenvalues=[1.284, 0.0490]\n      expected_eigenvalues.each_with_index{|ev,i|\n        assert_in_delta(ev,pca.eigenvalues[i],0.001)\n      }\n      expected_communality=[0.590, 0.694]\n      expected_communality.each_with_index{|ev,i|\n        assert_in_delta(ev,pca.communalities[i],0.001)\n      }\n      expected_cm=[0.768, 0.833]\n      obs=pca.component_matrix_correlation(1).column(0).to_a\n      expected_cm.each_with_index{|ev,i|\n        assert_in_delta(ev,obs[i],0.001)\n      }\n\n      assert(pca.summary)\n  end\n\n  # Tested with R\n  def test_principalaxis\n      matrix=::Matrix[\n      [1.0, 0.709501601093587, 0.877596585880047, 0.272219316266807],  [0.709501601093587, 1.0, 0.291633797330304, 0.871141831433844], [0.877596585880047, 0.291633797330304, 1.0, -0.213373722977167], [0.272219316266807, 0.871141831433844, -0.213373722977167, 1.0]]\n      \n      \n      fa=Statsample::Factor::PrincipalAxis.new(matrix,:m=>1, :max_iterations=>50)\n\n      cm=::Matrix[[0.923],[0.912],[0.507],[0.483]]\n      \n      assert_equal_matrix(cm,fa.component_matrix,0.001)\n      \n      h2=[0.852,0.832,0.257,0.233]\n      h2.each_with_index{|ev,i|\n        assert_in_delta(ev,fa.communalities[i],0.001)\n      }\n      eigen1=2.175\n      assert_in_delta(eigen1, fa.eigenvalues[0],0.001)\n      assert(fa.summary.size>0)\n      fa=Statsample::Factor::PrincipalAxis.new(matrix,:smc=>false)\n            \n      assert_raise RuntimeError do\n        fa.iterate\n      end\n\n  end\n\n\n  def test_rotation_varimax\n    a = Matrix[ [ 0.4320,  0.8129,  0.3872]  ,\n      [0.7950, -0.5416,  0.2565]  ,\n      [0.5944,  0.7234, -0.3441],\n    [0.8945, -0.3921, -0.1863] ]\n\n    expected= Matrix[[-0.0204423,     0.938674,    -0.340334],\n      [0.983662, 0.0730206, 0.134997],\n      [0.0826106, 0.435975, -0.893379],\n    [0.939901, -0.0965213, -0.309596]]\n    varimax=Statsample::Factor::Varimax.new(a)\n    assert(!varimax.rotated.nil?, \"Rotated shouldn't be empty\")\n    assert(!varimax.component_transformation_matrix.nil?, \"Component matrix shouldn't be empty\")\n    assert(!varimax.h2.nil?, \"H2 shouldn't be empty\")\n    \n    assert_equal_matrix(expected,varimax.rotated,1e-6)\n    assert(varimax.summary.size>0)\n  end\n  \n\nend\n"
  },
  {
    "path": "test/test_factor_map.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n#require 'rserve'\n#require 'statsample/rserve_extension'\n\nclass StatsampleFactorMpaTestCase < MiniTest::Unit::TestCase\n  context Statsample::Factor::MAP do\n    setup do\n      m=Matrix[ \n            [ 1, 0.846, 0.805, 0.859, 0.473, 0.398, 0.301, 0.382],\n            [ 0.846, 1, 0.881, 0.826, 0.376, 0.326, 0.277, 0.415],\n            [ 0.805, 0.881, 1, 0.801, 0.38, 0.319, 0.237, 0.345],\n            [ 0.859, 0.826, 0.801, 1, 0.436, 0.329, 0.327, 0.365],\n            [ 0.473, 0.376, 0.38, 0.436, 1, 0.762, 0.73, 0.629],\n            [ 0.398, 0.326, 0.319, 0.329, 0.762, 1, 0.583, 0.577],\n            [ 0.301, 0.277, 0.237, 0.327, 0.73, 0.583, 1, 0.539],\n            [ 0.382, 0.415, 0.345, 0.365, 0.629, 0.577, 0.539, 1]\n      ]\n      @map=Statsample::Factor::MAP.new(m)\n    end\n    should \"return correct values with pure ruby\" do\n      @map.use_gsl=false\n      map_assertions(@map)\n    end\n    should_with_gsl \"return correct values with gsl\" do\n      #require 'ruby-prof'\n\n      @map.use_gsl=true\n      map_assertions(@map)    \n    end\n    \n    \n  end\n  \n  def map_assertions(map)\n      assert_in_delta(map.minfm, 0.066445,0.00001)\n      assert_equal(map.number_of_factors, 2)\n      assert_in_delta(map.fm[0], 0.312475,0.00001)\n      assert_in_delta(map.fm[1], 0.245121,0.00001)  \n    end\n  \n  \nend\n\n"
  },
  {
    "path": "test/test_factor_pa.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n#require 'rserve'\n#require 'statsample/rserve_extension'\n\nclass StatsampleFactorTestCase < MiniTest::Unit::TestCase\n  include Statsample::Fixtures\n  # Based on Hardle and Simar\n  def setup\n    @fixtures_dir=File.expand_path(File.dirname(__FILE__)+\"/fixtures\")\n  end\n  def test_parallelanalysis_with_data\n    if Statsample.has_gsl?\n      samples=100\n      variables=10\n      iterations=50\n      rng = Distribution::Normal.rng\n      f1=samples.times.collect {rng.call}.to_scale\n      f2=samples.times.collect {rng.call}.to_scale    \n      vectors={}\n      variables.times do |i|\n        if i<5\n          vectors[\"v#{i}\"]=samples.times.collect {|nv|\n            f1[nv]*5+f2[nv]*2+rng.call\n          }.to_scale\n        else\n          vectors[\"v#{i}\"]=samples.times.collect {|nv|\n            f2[nv]*5+f1[nv]*2+rng.call\n          }.to_scale\n        end\n        \n      end\n      ds=vectors.to_dataset\n      \n      pa1=Statsample::Factor::ParallelAnalysis.new(ds, :bootstrap_method=>:data, :iterations=>iterations)\n      pa2=Statsample::Factor::ParallelAnalysis.with_random_data(samples,variables,:iterations=>iterations,:percentil=>95)\n      3.times do |n|\n        var=\"ev_0000#{n+1}\"\n        assert_in_delta(pa1.ds_eigenvalues[var].mean, pa2.ds_eigenvalues[var].mean,0.05)\n      end\n    else\n      skip(\"Too slow without GSL\")\n    end\n    \n  end\n  def test_parallelanalysis\n    pa=Statsample::Factor::ParallelAnalysis.with_random_data(305,8,:iterations=>100,:percentil=>95)\n    assert_in_delta(1.2454, pa.ds_eigenvalues['ev_00001'].mean, 0.01)\n    assert_in_delta(1.1542, pa.ds_eigenvalues['ev_00002'].mean, 0.01)\n    assert_in_delta(1.0836, pa.ds_eigenvalues['ev_00003'].mean, 0.01)\n    assert(pa.summary.size>0)\n  end  \nend\n"
  },
  {
    "path": "test/test_ggobi.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nrequire 'ostruct'\nclass StatsampleGGobiTestCase < MiniTest::Unit::TestCase\n\n  def setup\n    v1=([10.2,20.3,10,20,30,40,30,20,30,40]*10).to_vector(:scale)\n    @v2=(%w{a b c a a a b b c d}*10).to_vector(:nominal)\n    @v2.labels={\"a\"=>\"letter a\",\"d\"=>\"letter d\"}\n    v3=([1,2,3,4,5,4,3,2,1,2]*10).to_vector(:ordinal)\n    @ds={'v1'=>v1,'v2'=>@v2,'v3'=>v3}.to_dataset\n  end\n  def test_values_definition\n    a=[1.0,2,\"a\",nil]\n    assert_equal(\"1.0 2 a NA\", Statsample::GGobi.values_definition(a,\"NA\"))\n  end\n  def test_variable_definition\n    carrier=OpenStruct.new\n    carrier.categorials=[]\n    carrier.conversions={}\n    real_var_definition=Statsample::GGobi.variable_definition(carrier,@v2,'variable 2',\"v2\")\n\t\texpected=<<-EOS\n<categoricalvariable name=\"variable 2\" nickname=\"v2\">\n<levels count=\"4\">\n<level value=\"1\">letter a</level>\n<level value=\"2\">b</level>\n<level value=\"3\">c</level>\n<level value=\"4\">letter d</level></levels>\n</categoricalvariable>\n    EOS\n    assert_equal(expected.gsub(/\\s/,\" \"),real_var_definition.gsub(/\\s/,\" \"))\n    assert_equal({'variable 2'=>{'a'=>1,'b'=>2,'c'=>3,'d'=>4}},carrier.conversions)\n    assert_equal(['variable 2'],carrier.categorials)\n  end\nend\n"
  },
  {
    "path": "test/test_gsl.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleGSLTestCase < MiniTest::Unit::TestCase\n  should_with_gsl \"matrix with gsl\" do\n    a=[1,2,3,4,20].to_vector(:scale)\n    b=[3,2,3,4,50].to_vector(:scale)\n    c=[6,2,3,4,3].to_vector(:scale)\n    ds={'a'=>a,'b'=>b,'c'=>c}.to_dataset\n    gsl=ds.to_matrix.to_gsl\n    assert_equal(5,gsl.size1)\n    assert_equal(3,gsl.size2)\n    matrix=gsl.to_matrix\n    assert_equal(5,matrix.row_size)\n    assert_equal(3,matrix.column_size)\n  end\nend\n\n\n"
  },
  {
    "path": "test/test_histogram.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\n\nclass StatsampleHistogramTestCase < MiniTest::Unit::TestCase\n  context Statsample::Histogram do\n    should \"alloc correctly with integer\" do\n      h = Statsample::Histogram.alloc(4)\n      assert_equal([0.0]*4, h.bin)\n      assert_equal([0.0]*5, h.range)\n    end\n    should \"alloc correctly with array\" do\n      h = Statsample::Histogram.alloc([1, 3, 7, 9, 20])\n      assert_equal([0.0]*4, h.bin)\n      assert_equal([1,3,7,9,20], h.range)\n    end\n    should \"alloc correctly with integer and min, max array\" do\n      h = Statsample::Histogram.alloc(5, [0, 5])\n      assert_equal([0.0,1.0,2.0,3.0,4.0,5.0], h.range)\n      assert_equal([0.0]*5,h.bin)\n    end\n    should \"bin() method return correct number of bins\" do\n      h = Statsample::Histogram.alloc(4)\n      assert_equal(4,h.bins)\n    end\n    should \"increment correctly\" do \n      h = Statsample::Histogram.alloc(5, [0, 5])      \n      h.increment 2.5\n      assert_equal([0.0,0.0,1.0,0.0,0.0], h.bin)\n      h.increment [0.5,0.5,3.5,3.5]\n      assert_equal([2.0,0.0,1.0,2.0,0.0], h.bin)\n      h.increment 0\n      assert_equal([3.0,0.0,1.0,2.0,0.0], h.bin)\n      h.increment 5\n      assert_equal([3.0,0.0,1.0,2.0,0.0], h.bin)\n    end\n    \n    should \"alloc_uniform correctly with n, min,max\" do\n      h = Statsample::Histogram.alloc_uniform(5,0,10)\n      assert_equal(5,h.bins)\n      assert_equal([0.0]*5,h.bin)\n      assert_equal([0.0,2.0,4.0,6.0,8.0,10.0], h.range)\n    end\n    should \"alloc_uniform correctly with n, [min,max]\" do\n      h = Statsample::Histogram.alloc_uniform(5, [0, 10])\n      assert_equal(5,h.bins)\n      assert_equal([0.0]*5,h.bin)\n      assert_equal([0.0,2.0,4.0,6.0,8.0,10.0], h.range)\n    end\n    should \"get_range()\" do\n      h = Statsample::Histogram.alloc_uniform(5,2,12)\n      5.times {|i|\n        assert_equal([2+i*2, 4+i*2], h.get_range(i))\n      }\n    end\n    should \"min() and max()\" do\n      h=Statsample::Histogram.alloc_uniform(5,2,12)\n      assert_equal(2,h.min)\n      assert_equal(12,h.max)\n    end\n    should \"max_val()\" do\n       h = Statsample::Histogram.alloc(5, [0, 5])\n       100.times {h.increment(rand*5)}\n       max=h.bin[0]\n       (1..4).each {|i|\n         max = h.bin[i] if h.bin[i] > max\n       }\n       assert_equal(max,h.max_val)\n    end\n    should \"min_val()\" do\n       h = Statsample::Histogram.alloc(5, [0, 5])\n       100.times {h.increment(rand*5)}\n       min=h.bin[0]\n       (1..4).each {|i|\n         min = h.bin[i] if h.bin[i]<min\n       }\n       assert_equal(min,h.min_val)\n    end\n    should \"return correct estimated mean\" do\n      a=[1.5,1.5,1.5,3.5,3.5,3.5].to_scale\n      h=Statsample::Histogram.alloc(5,[0,5])\n      h.increment(a)\n      assert_equal(2.5, h.estimated_mean)\n    end\n    should \"return correct estimated standard deviation\" do\n      a=[0.5,1.5,1.5,1.5,2.5, 3.5,3.5,3.5,4.5].to_scale\n      h=Statsample::Histogram.alloc(5,[0,5])\n      h.increment(a)\n      assert_equal(a.sd, h.estimated_standard_deviation)\n    end\n    should \"return correct sum for all values\" do\n      h=Statsample::Histogram.alloc(5,[0,5])\n      n=rand(100)\n      n.times { h.increment(1)}\n      assert_equal(n, h.sum)\n    end\n    should \"return correct sum for a subset of values\" do\n      h=Statsample::Histogram.alloc(5,[0,5])\n      h.increment([0.5,2.5,4.5])\n      assert_equal(1,h.sum(0,1))\n      assert_equal(2,h.sum(1,4))\n\n    end\n    should \"not raise exception when all values equal\" do\n      assert_nothing_raised do\n        a = [5,5,5,5,5,5].to_scale\n        h=Statsample::Graph::Histogram.new(a)\n        h.to_svg\n      end\n    end\n    \n  end\nend\n"
  },
  {
    "path": "test/test_matrix.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleMatrixTestCase < MiniTest::Unit::TestCase\n  \n  def test_to_dataset\n    m=Matrix[[1,4],[2,5],[3,6]]\n    m.extend Statsample::NamedMatrix\n    m.fields_y=%w{x1 x2}\n    m.name=\"test\"\n    samples=100\n    x1=[1,2,3].to_scale\n    x2=[4,5,6].to_scale\n    ds={'x1'=>x1,'x2'=>x2}.to_dataset\n    ds.name=\"test\"\n    obs=m.to_dataset\n    assert_equal(ds['x1'],obs['x1'])\n    assert_equal(ds['x2'],obs['x2'])\n    assert_equal(ds['x1'].mean,obs['x1'].mean)\n    \n    \n  end\n  def test_covariate\n    a=Matrix[[1.0, 0.3, 0.2], [0.3, 1.0, 0.5], [0.2, 0.5, 1.0]]\n    a.extend Statsample::CovariateMatrix\n    a.fields=%w{a b c}\n    assert_equal(:correlation, a._type)\n\n    assert_equal(Matrix[[0.5],[0.3]], a.submatrix(%w{c a}, %w{b}))\n    assert_equal(Matrix[[1.0, 0.2] , [0.2, 1.0]], a.submatrix(%w{c a}))\n    assert_equal(:correlation, a.submatrix(%w{c a})._type)\n\n    a=Matrix[[20,30,10], [30,60,50], [10,50,50]]\n\n    a.extend Statsample::CovariateMatrix\n\n    assert_equal(:covariance, a._type)\n\n    a=50.times.collect {rand()}.to_scale\n    b=50.times.collect {rand()}.to_scale\n    c=50.times.collect {rand()}.to_scale\n    ds={'a'=>a,'b'=>b,'c'=>c}.to_dataset\n    corr=Statsample::Bivariate.correlation_matrix(ds)\n    real=Statsample::Bivariate.covariance_matrix(ds).correlation\n    corr.row_size.times do |i|\n      corr.column_size.times do |j|\n        assert_in_delta(corr[i,j], real[i,j],1e-15)\n      end\n    end\n  end  \nend\n"
  },
  {
    "path": "test/test_multiset.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\n\nclass StatsampleMultisetTestCase < MiniTest::Unit::TestCase\n  def setup\n    @x=%w{a a a a b b b b}.to_vector\n    @y=[1,2,3,4,5,6,7,8].to_scale\n    @z=[10,11,12,13,14,15,16,17].to_scale\n    @ds={'x'=>@x,'y'=>@y,'z'=>@z}.to_dataset\n    @ms=@ds.to_multiset_by_split('x')\n  end\n  def test_creation\n    v1a=[1,2,3,4,5].to_vector\n    v2b=[11,21,31,41,51].to_vector\n    v3c=[21,23,34,45,56].to_vector\n    ds1={'v1'=>v1a,'v2'=>v2b,'v3'=>v3c}.to_dataset\n    v1b=[15,25,35,45,55].to_vector\n    v2b=[11,21,31,41,51].to_vector\n    v3b=[21,23,34,45,56].to_vector\n    ds2={'v1'=>v1b,'v2'=>v2b,'v3'=>v3b}.to_dataset\n    ms=Statsample::Multiset.new(['v1','v2','v3'])\n    ms.add_dataset('ds1',ds1)\n    ms.add_dataset('ds2',ds2)\n    assert_equal(ds1,ms['ds1'])\n    assert_equal(ds2,ms['ds2'])\n    assert_equal(v1a,ms['ds1']['v1'])\n    assert_not_equal(v1b,ms['ds1']['v1'])\n    ds3={'v1'=>v1b,'v2'=>v2b}.to_dataset\n    assert_raise ArgumentError do\n      ms.add_dataset(ds3)\n    end\n  end\n  def test_creation_empty\n    ms=Statsample::Multiset.new_empty_vectors(%w{id age name},%w{male female})\n    ds_male={'id'=>[].to_vector,'age'=>[].to_vector, 'name'=>[].to_vector}.to_dataset(%w{id age name})\n    ds_female={'id'=>[].to_vector,'age'=>[].to_vector, 'name'=>[].to_vector}.to_dataset(%w{id age name})\n    ms2=Statsample::Multiset.new(%w{id age name})\n    ms2.add_dataset('male',ds_male)\n    ms2.add_dataset('female',ds_female)\n    assert_equal(ms2.fields,ms.fields)\n    assert_equal(ms2['male'],ms['male'])\n    assert_equal(ms2['female'],ms['female'])\n  end\n  def test_to_multiset_by_split_one\n    sex=%w{m m m m m f f f f m}.to_vector(:nominal)\n    city=%w{London Paris NY London Paris NY London Paris NY Tome}.to_vector(:nominal)\n    age=[10,10,20,30,34,34,33,35,36,40].to_vector(:scale)\n    ds={'sex'=>sex,'city'=>city,'age'=>age}.to_dataset\n    ms=ds.to_multiset_by_split('sex')\n    assert_equal(2,ms.n_datasets)\n    assert_equal(%w{f m},ms.datasets.keys.sort)\n    assert_equal(6,ms['m'].cases)\n    assert_equal(4,ms['f'].cases)\n    assert_equal(%w{London Paris NY London Paris Tome},ms['m']['city'].to_a)\n    assert_equal([34,33,35,36],ms['f']['age'].to_a)\n  end\n  def test_to_multiset_by_split_multiple\n    sex=%w{m m m m m m m m m m f f f f f f f f f f}.to_vector(:nominal)\n    city=%w{London London London Paris Paris London London London Paris Paris London London London Paris Paris London London London Paris Paris}.to_vector(:nominal)\n    hair=%w{blonde blonde black black blonde blonde black black blonde blonde black black blonde blonde black black blonde blonde black black}.to_vector(:nominal)\n    age=[10,10,20,30,34,34,33,35,36,40, 10,10,20,30,34,34,33,35,36,40].to_vector(:scale)\n    ds={'sex'=>sex,'city'=>city,'hair'=>hair,'age'=>age}.to_dataset(%w{sex city hair age})\n    ms=ds.to_multiset_by_split('sex','city','hair')\n    assert_equal(8,ms.n_datasets)\n    assert_equal(3,ms[%w{m London blonde}].cases)\n    assert_equal(3,ms[%w{m London blonde}].cases)\n    assert_equal(1,ms[%w{m Paris black}].cases)\n  end\n\n  def test_stratum_proportion\n    ds1={'q1'=>[1,1,1,1,1,0,0,0,0,0,0,0].to_vector}.to_dataset\n    ds2={'q1'=>[1,1,1,1,1,1,1,0,0].to_vector}.to_dataset\n    assert_equal(5.0/12, ds1['q1'].proportion )\n    assert_equal(7.0/9, ds2['q1'].proportion )\n    ms=Statsample::Multiset.new(['q1'])\n    ms.add_dataset('d1',ds1)\n    ms.add_dataset('d2',ds2)\n    ss=Statsample::StratifiedSample.new(ms,{'d1'=>50,'d2'=>100})\n    assert_in_delta(0.655, ss.proportion('q1'),0.01)\n    assert_in_delta(0.345, ss.proportion('q1',0),0.01)\n\n  end\n  def test_stratum_scale\n    boys={'test'=>[50, 55, 60, 62, 62, 65, 67, 67, 70, 70, 73, 73, 75, 78, 78, 80, 85, 90].to_vector(:scale)}.to_dataset\n    girls={'test'=>[70, 70, 72, 72, 75, 75, 78, 78, 80, 80, 82, 82, 85, 85, 88, 88, 90, 90].to_vector(:scale)}.to_dataset\n    ms=Statsample::Multiset.new(['test'])\n    ms.add_dataset('boys',boys)\n    ms.add_dataset('girls',girls)\n    ss=Statsample::StratifiedSample.new(ms,{'boys'=>10000,'girls'=>10000})\n    assert_equal(2,ss.strata_number)\n    assert_equal(20000,ss.population_size)\n    assert_equal(10000,ss.stratum_size('boys'))\n    assert_equal(10000,ss.stratum_size('girls'))\n    assert_equal(36,ss.sample_size)\n    assert_equal(75,ss.mean('test'))\n    assert_in_delta(1.45,ss.standard_error_wor('test'),0.01)\n    assert_in_delta(ss.standard_error_wor('test'), ss.standard_error_wor_2('test'),0.00001)\n  end\n  def test_each\n    xpe={\n      'a'=>%w{a a a a}.to_vector,\n      'b'=>%w{b b b b}.to_vector\n    }\n    ype={\n      'a'=>[1,2,3,4].to_scale,\n      'b'=>[5,6,7,8].to_scale,\n    }\n    zpe={\n      'a'=>[10,11,12,13].to_scale,\n      'b'=>[14,15,16,17].to_scale,\n    }\n    xp,yp,zp=Hash.new(),Hash.new(),Hash.new()\n    @ms.each {|k,ds|\n      xp[k]=ds['x']\n      yp[k]=ds['y']\n      zp[k]=ds['z']\n    }\n    assert_equal(xpe,xp)\n    assert_equal(ype,yp)\n    assert_equal(zpe,zp)\n\n  end\n  def test_multiset_union_with_block\n    \n    r1=rand()\n    r2=rand()\n    ye=[1*r1,2*r1,3*r1,4*r1,5*r2,6*r2,7*r2,8*r2].to_scale\n    \n    ze=[10*r1,11*r1,12*r1,13*r1, 14*r2,15*r2,16*r2,17*r2].to_scale\n    \n    ds2=@ms.union {|k,ds|\n      ds['y'].recode!{|v| \n      k=='a' ? v*r1 : v*r2}\n      ds['z'].recode!{|v| \n      k=='a' ? v*r1 : v*r2}\n    }\n    assert_equal(ye,ds2['y'])\n    assert_equal(ze,ds2['z'])\n  end\n  def test_multiset_union\n    r1=rand()\n    r2=rand()\n    ye=[1*r1,2*r1,3*r1,4*r1,5*r2,6*r2,7*r2,8*r2].to_scale\n    \n    ze=[10*r1,11*r1,12*r1,13*r1, 14*r2,15*r2,16*r2,17*r2].to_scale\n    @ms.each {|k,ds|\n      ds['y'].recode!{|v| \n      k=='a' ? v*r1 : v*r2}\n      ds['z'].recode!{|v| \n      k=='a' ? v*r1 : v*r2}\n      \n    }\n    ds2=@ms.union\n    assert_equal(ye,ds2['y'])\n    assert_equal(ze,ds2['z'])\n    \n  end\nend\n"
  },
  {
    "path": "test/test_regression.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleRegressionTestCase < MiniTest::Unit::TestCase\n  context \"Example with missing data\" do\n    setup do \n      @x=[0.285714285714286, 0.114285714285714, 0.314285714285714, 0.2, 0.2, 0.228571428571429, 0.2, 0.4, 0.714285714285714, 0.285714285714286, 0.285714285714286, 0.228571428571429, 0.485714285714286, 0.457142857142857, 0.257142857142857, 0.228571428571429, 0.285714285714286, 0.285714285714286, 0.285714285714286, 0.142857142857143, 0.285714285714286, 0.514285714285714, 0.485714285714286, 0.228571428571429, 0.285714285714286, 0.342857142857143, 0.285714285714286, 0.0857142857142857].to_scale\n\n      @y=[nil, 0.233333333333333, nil, 0.266666666666667, 0.366666666666667, nil, 0.333333333333333, 0.3, 0.666666666666667, 0.0333333333333333, 0.333333333333333, nil, nil, 0.533333333333333, 0.433333333333333, 0.4, 0.4, 0.5, 0.4, 0.266666666666667, 0.166666666666667, 0.666666666666667, 0.433333333333333, 0.166666666666667, nil, 0.4, 0.366666666666667, nil].to_scale      \n      @ds={'x'=>@x,'y'=>@y}.to_dataset\n      @lr=Statsample::Regression::Multiple::RubyEngine.new(@ds,'y')\n    end\n    should \"have correct values\" do\n      assert_in_delta(0.455,@lr.r2,0.001)\n      assert_in_delta(0.427,@lr.r2_adjusted, 0.001)\n      assert_in_delta(0.1165,@lr.se_estimate,0.001)\n      assert_in_delta(15.925,@lr.f,0.0001)\n      assert_in_delta(0.675, @lr.standarized_coeffs['x'],0.001)\n      assert_in_delta(0.778, @lr.coeffs['x'],0.001, \"coeff x\")\n      assert_in_delta(0.132, @lr.constant,0.001,\"constant\")\n      assert_in_delta(0.195, @lr.coeffs_se['x'],0.001,\"coeff x se\")\n      assert_in_delta(0.064, @lr.constant_se,0.001,\"constant se\")\n  end\n  end\n  should \"return an error if data is linearly dependent\" do \n    samples=100\n    \n    a,b=rand,rand\n    \n    x1=samples.times.map { rand}.to_scale\n    x2=samples.times.map {rand}.to_scale\n    x3=samples.times.map {|i| x1[i]*(1+a)+x2[i]*(1+b)}.to_scale\n    y=samples.times.map {|i| x1[i]+x2[i]+x3[i]+rand}.to_scale\n\n    ds={'x1'=>x1,'x2'=>x2,'x3'=>x3,'y'=>y}.to_dataset\n\n    assert_raise(Statsample::Regression::LinearDependency) {\n        Statsample::Regression::Multiple::RubyEngine.new(ds,'y')\n    }\n  end\n  def test_parameters\n    @x=[13,20,10,33,15].to_vector(:scale)\n    @y=[23,18,35,10,27\t].to_vector(:scale)\n    reg=Statsample::Regression::Simple.new_from_vectors(@x,@y)\n    _test_simple_regression(reg)\n    ds={'x'=>@x,'y'=>@y}.to_dataset\n    reg=Statsample::Regression::Simple.new_from_dataset(ds,'x','y')\n    _test_simple_regression(reg)\n    reg=Statsample::Regression.simple(@x,@y)\n    _test_simple_regression(reg)\n\n  end\n  def _test_simple_regression(reg)\n  \n    assert_in_delta(40.009, reg.a,0.001)\n    assert_in_delta(-0.957, reg.b,0.001)\n    assert_in_delta(4.248,reg.standard_error,0.002)\n    assert(reg.summary)\n  end\n  \n  def test_summaries\n    a=10.times.map{rand(100)}.to_scale\n    b=10.times.map{rand(100)}.to_scale\n    y=10.times.map{rand(100)}.to_scale\n    ds={'a'=>a,'b'=>b,'y'=>y}.to_dataset\n    lr=Statsample::Regression::Multiple::RubyEngine.new(ds,'y')\n    assert(lr.summary.size>0)\n  end\n  def test_multiple_dependent\n    complete=Matrix[\n      [1,0.53,0.62,0.19,-0.09,0.08,0.02,-0.12,0.08],\n      [0.53,1,0.61,0.23,0.1,0.18,0.02,-0.1,0.15],\n      [0.62,0.61,1,0.03,0.1,0.12,0.03,-0.06,0.12],\n      [0.19,0.23,0.03,1,-0.02,0.02,0,-0.02,-0.02],\n      [-0.09,0.1,0.1,-0.02,1,0.05,0.06,0.18,0.02],\n      [0.08,0.18,0.12,0.02,0.05,1,0.22,-0.07,0.36],\n      [0.02,0.02,0.03,0,0.06,0.22,1,-0.01,-0.05],\n      [-0.12,-0.1,-0.06,-0.02,0.18,-0.07,-0.01,1,-0.03],\n    [0.08,0.15,0.12,-0.02,0.02,0.36,-0.05,-0.03,1]]\n    complete.extend Statsample::CovariateMatrix\n    complete.fields=%w{adhd cd odd sex age monly mwork mage poverty}\n\n    lr=Statsample::Regression::Multiple::MultipleDependent.new(complete, %w{adhd cd odd})\n\n\n    assert_in_delta(0.197, lr.r2yx,0.001)\n    assert_in_delta(0.197, lr.r2yx_covariance,0.001)\n    assert_in_delta(0.07, lr.p2yx,0.001)\n\n  end\n  \n  def test_multiple_regression_pairwise_2\n    @a=[1,3,2,4,3,5,4,6,5,7,3,nil,3,nil,3].to_vector(:scale)\n    @b=[3,3,4,4,5,5,6,6,4,4,2,2,nil,6,2].to_vector(:scale)\n    @c=[11,22,30,40,50,65,78,79,99,100,nil,3,7,nil,7].to_vector(:scale)\n    @y=[3,4,5,6,7,8,9,10,20,30,30,40,nil,50,nil].to_vector(:scale)\n    ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n    lr=Statsample::Regression::Multiple::RubyEngine.new(ds,'y')\n    assert_in_delta(2407.436,lr.sst,0.001)\n    assert_in_delta(0.752,lr.r,0.001, \"pairwise r\")\n    assert_in_delta(0.565,lr.r2,0.001)\n    assert_in_delta(1361.130,lr.ssr,0.001)\n    assert_in_delta(1046.306,lr.sse,0.001)\n    assert_in_delta(3.035,lr.f,0.001)\n  end\n\n\n  def test_multiple_regression_gsl\n    if Statsample.has_gsl?\n      @a=[1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n      @b=[3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n      @c=[11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n      @y=[3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n      ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n      lr=Statsample::Regression::Multiple::GslEngine.new(ds,'y')\n      assert(lr.summary.size>0)\n      model_test(lr,'gsl')\n      predicted=[1.7857, 6.0989, 3.2433, 7.2908, 4.9667, 10.3428, 8.8158, 10.4717, 23.6639, 25.3198]\n      c_predicted=lr.predicted\n      predicted.each_index{|i|\n        assert_in_delta(predicted[i],c_predicted[i],0.001)\n      }\n      residuals=[1.2142, -2.0989, 1.7566, -1.29085, 2.033, -2.3428, 0.18414, -0.47177, -3.66395, 4.6801]\n      c_residuals=lr.residuals\n      residuals.each_index{|i|\n        assert_in_delta(residuals[i],c_residuals[i],0.001)\n      }\n    else\n      skip \"Regression::Multiple::GslEngine not tested (no Gsl)\"\n    end\n  end\n\n\n\n  def model_test_matrix(lr,name='undefined')\n\n    stan_coeffs={'a'=>0.151,'b'=>-0.547,'c'=>0.997}\n    unstan_coeffs={'a'=>0.695, 'b'=>-4.286, 'c'=>0.266}\n\n    unstan_coeffs.each_key{|k|\n      assert_in_delta(unstan_coeffs[k], lr.coeffs[k],0.001,\"b coeffs - #{name}\")\n    }\n\n    stan_coeffs.each_key{|k|\n      assert_in_delta(stan_coeffs[k], lr.standarized_coeffs[k],0.001, \"beta coeffs - #{name}\")\n    }\n\n    assert_in_delta(11.027,lr.constant,0.001)\n\n    assert_in_delta(0.955,lr.r,0.001)\n    assert_in_delta(0.913,lr.r2,0.001)\n\n    assert_in_delta(20.908, lr.f,0.001)\n    assert_in_delta(0.001, lr.probability, 0.001)\n    assert_in_delta(0.226,lr.tolerance(\"a\"),0.001)\n\n    coeffs_se={\"a\"=>1.171,\"b\"=>1.129,\"c\"=>0.072}\n\n\n\n    ccoeffs_se=lr.coeffs_se\n    coeffs_se.each_key{|k|\n      assert_in_delta(coeffs_se[k],ccoeffs_se[k],0.001)\n    }\n    coeffs_t={\"a\"=>0.594,\"b\"=>-3.796,\"c\"=>3.703}\n    ccoeffs_t=lr.coeffs_t\n    coeffs_t.each_key{|k|\n      assert_in_delta(coeffs_t[k], ccoeffs_t[k],0.001)\n    }\n\n    assert_in_delta(639.6,lr.sst,0.001)\n    assert_in_delta(583.76,lr.ssr,0.001)\n    assert_in_delta(55.840,lr.sse,0.001)\n\tassert(lr.summary.size>0, \"#{name} without summary\")\n  end\n  def model_test(lr,name='undefined')\n    model_test_matrix(lr,name)\n    assert_in_delta(4.559, lr.constant_se,0.001)\n    assert_in_delta(2.419, lr.constant_t,0.001)\n\n    assert_in_delta(1.785,lr.process([1,3,11]),0.001)\n  end\n  def test_regression_matrix\n    @a=[1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n    @b=[3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n    @c=[11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n    @y=[3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n    ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n    cor=Statsample::Bivariate.correlation_matrix(ds)\n    \n    lr=Statsample::Regression::Multiple::MatrixEngine.new(cor,'y', :y_mean=>@y.mean, :x_mean=>{'a'=>ds['a'].mean, 'b'=>ds['b'].mean, 'c'=>ds['c'].mean}, :cases=>@a.size, :y_sd=>@y.sd , :x_sd=>{'a' => @a.sd, 'b' => @b.sd, 'c' => @c.sd})\n    assert_nil(lr.constant_se)\n    assert_nil(lr.constant_t)\n    model_test_matrix(lr, \"correlation matrix\")\n\n    covariance=Statsample::Bivariate.covariance_matrix(ds)\n    lr=Statsample::Regression::Multiple::MatrixEngine.new(covariance,'y', :y_mean=>@y.mean, :x_mean=>{'a'=>ds['a'].mean, 'b'=>ds['b'].mean, 'c'=>ds['c'].mean}, :cases=>@a.size)\n    assert(lr.summary.size>0)\n\n    model_test(lr , \"covariance matrix\")\n  end\n  def test_regression_rubyengine\n    @a=[nil,1,3,2,4,3,5,4,6,5,7].to_vector(:scale)\n    @b=[nil,3,3,4,4,5,5,6,6,4,4].to_vector(:scale)\n    @c=[nil,11,22,30,40,50,65,78,79,99,100].to_vector(:scale)\n    @y=[nil,3,4,5,6,7,8,9,10,20,30].to_vector(:scale)\n    ds={'a'=>@a,'b'=>@b,'c'=>@c,'y'=>@y}.to_dataset\n    lr=Statsample::Regression::Multiple::RubyEngine.new(ds,'y')\n    assert_equal(11, lr.total_cases)\n    assert_equal(10, lr.valid_cases)\n    model_test(lr, 'rubyengine with missing data')\n\n    predicted=[nil,1.7857, 6.0989, 3.2433, 7.2908, 4.9667, 10.3428, 8.8158, 10.4717, 23.6639, 25.3198]\n    c_predicted = lr.predicted\n    predicted.each_index do |i|\n      if c_predicted[i].nil?\n        assert(predicted[i].nil?, \"Actual #{i} is nil, but expected #{predicted[i]}\")\n      else\n        assert_in_delta(predicted[i], c_predicted[i], 0.001)\n      end\n    end\n    residuals=[nil,1.2142, -2.0989, 1.7566, -1.29085, 2.033, -2.3428, 0.18414, -0.47177, -3.66395, 4.6801]\n    c_residuals=lr.residuals\n    residuals.each_index do |i|\n      if c_residuals[i].nil?\n        assert(residuals[i].nil?)\n      else\n        assert_in_delta(residuals[i],c_residuals[i],0.001)\n      end\n    end\n\n  end\nend\n"
  },
  {
    "path": "test/test_reliability.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleReliabilityTestCase < MiniTest::Unit::TestCase\n  context Statsample::Reliability do\n    should \"return correct r according to Spearman-Brown prophecy\" do\n      r=0.6849\n      n=62.quo(15)\n      assert_in_delta(0.9, Statsample::Reliability.sbp(r,n), 0.001)\n    end\n    should \"return correct n for desired realiability\" do\n        r=0.6849\n        r_d=0.9\n        assert_in_delta(62, Statsample::Reliability.n_for_desired_reliability(r, r_d, 15),0.5)\n      end\n    context \"Cronbach's alpha\" do \n      setup do\n        @samples=40\n        @n_variables=rand(10)+2\n        @ds=Statsample::Dataset.new()\n        base=@samples.times.collect {|a| rand()}.to_scale\n        @n_variables.times do |i|\n          @ds[i]=base.collect {|v| v+rand()}.to_scale\n        end\n        \n        @ds.update_valid_data\n        @k=@ds.fields.size\n        @cm=Statsample::Bivariate.covariance_matrix(@ds)\n        @dse=@ds.dup\n        @dse.fields.each do |f|\n          @dse[f]=@dse[f].standarized\n        end\n        @cme=Statsample::Bivariate.covariance_matrix(@dse)\n        @a=Statsample::Reliability.cronbach_alpha(@ds)\n        @as=Statsample::Reliability.cronbach_alpha_standarized(@ds)\n      end\n      should \"alpha will be equal to sum of matrix covariance less the individual variances\" do\n        total_sum=@cm.total_sum\n        ind_var=@ds.fields.inject(0) {|ac,v| ac+@ds[v].variance}\n        expected = @k.quo(@k-1) * (1-(ind_var.quo(total_sum)))\n        assert_in_delta(expected, @a,1e-10)\n      end\n      should \"method cronbach_alpha_from_n_s2_cov return correct values\" do\n        sa=Statsample::Reliability::ScaleAnalysis.new(@ds)\n        vm, cm = sa.variances_mean, sa.covariances_mean\n        assert_in_delta(sa.alpha, Statsample::Reliability.cronbach_alpha_from_n_s2_cov(@n_variables, vm,cm), 1e-10)        \n      end\n      should \"method cronbach_alpha_from_covariance_matrix returns correct value\" do\n        cov=Statsample::Bivariate.covariance_matrix(@ds)\n        assert_in_delta(@a, Statsample::Reliability.cronbach_alpha_from_covariance_matrix(cov),0.0000001)\n      end\n      should \"return correct n for desired alpha, covariance and variance\" do\n        sa=Statsample::Reliability::ScaleAnalysis.new(@ds)\n        vm, cm = sa.variances_mean, sa.covariances_mean\n        n_obtained=Statsample::Reliability.n_for_desired_alpha(@a, vm,cm)\n        #p n_obtained\n        assert_in_delta(Statsample::Reliability.cronbach_alpha_from_n_s2_cov(n_obtained, vm,cm) ,@a,0.001) \n      end\n      \n      should \"standarized alpha will be equal to sum of matrix covariance less the individual variances on standarized values\" do\n        total_sum=@cme.total_sum\n        ind_var=@dse.fields.inject(0) {|ac,v| ac+@dse[v].variance}\n        expected = @k.quo(@k-1) * (1-(ind_var.quo(total_sum)))\n        assert_in_delta(expected, @as, 1e-10)\n      end\n    end\n    context Statsample::Reliability::ItemCharacteristicCurve do\n      setup do\n        @samples=100\n        @points=rand(10)+3\n        @max_point=(@points-1)*3\n        @x1=@samples.times.map{rand(@points)}.to_scale\n        @x2=@samples.times.map{rand(@points)}.to_scale\n        @x3=@samples.times.map{rand(@points)}.to_scale\n        @ds={'a'=>@x1,'b'=>@x2,'c'=>@x3}.to_dataset\n        @icc=Statsample::Reliability::ItemCharacteristicCurve.new(@ds)\n      end\n      should \"have a correct automatic vector_total\" do\n        assert_equal(@ds.vector_sum, @icc.vector_total)\n      end\n      should \"have a correct different vector_total\" do\n        x2=@samples.times.map{rand(10)}.to_scale\n        @icc=Statsample::Reliability::ItemCharacteristicCurve.new(@ds,x2)\n        assert_equal(x2, @icc.vector_total)\n        assert_raises(ArgumentError) do\n          inc=(@samples+10).times.map{rand(10)}.to_scale\n          @icc=Statsample::Reliability::ItemCharacteristicCurve.new(@ds,inc)          \n        end\n      end\n      should \"have 0% for 0 points on maximum value values\" do\n        max=@icc.curve_field('a',0)[@max_point.to_f]\n        max||=0\n        assert_in_delta(0, max)\n      end\n      should \"have 0 for max value on minimum value\" do\n        max=@icc.curve_field('a',@max_point)[0.0]\n        max||=0\n        assert_in_delta(0, max)\n      end\n      should \"have correct values of % for any value\" do\n        sum=@icc.vector_total\n        total={}\n        total_g=sum.frequencies\n        index=rand(@points)\n        @x1.each_with_index do |v,i|\n          total[sum[i]]||=0\n          total[sum[i]]+=1 if v==index\n        end\n        expected=total.each {|k,v|\n          total[k]=v.quo(total_g[k])\n        }\n        assert_equal(expected, @icc.curve_field('a',index))\n        \n      end\n      \n    end\n    \n    context Statsample::Reliability::MultiScaleAnalysis do\n      \n      setup do\n        size=100\n        @scales=3\n        @items_per_scale=10\n        h={}\n        @scales.times {|s|\n          @items_per_scale.times {|i|\n            h[\"#{s}_#{i}\"] = (size.times.map {(s*2)+rand}).to_scale\n          }\n        }\n        @ds=h.to_dataset\n        @msa=Statsample::Reliability::MultiScaleAnalysis.new(:name=>'Multiple Analysis') do |m|\n          m.scale \"complete\", @ds\n          @scales.times {|s|\n            m.scale \"scale_#{s}\", @ds.clone(@items_per_scale.times.map {|i| \"#{s}_#{i}\"}), {:name=>\"Scale #{s}\"}\n          }\n        end\n      end\n      should \"Retrieve correct ScaleAnalysis for whole scale\" do\n        sa=Statsample::Reliability::ScaleAnalysis.new(@ds, :name=>\"Scale complete\") \n        assert_equal(sa.variances_mean, @msa.scale(\"complete\").variances_mean)\n      end\n      should \"Retrieve correct ScaleAnalysis for each scale\" do\n        @scales.times {|s|\n          sa=Statsample::Reliability::ScaleAnalysis.new(@ds.dup(@items_per_scale.times.map {|i| \"#{s}_#{i}\"}), :name=>\"Scale #{s}\")\n          assert_equal(sa.variances_mean,@msa.scale(\"scale_#{s}\").variances_mean)\n        }\n      end\n      should \"retrieve correct correlation matrix for each scale\" do\n        vectors={'complete' => @ds.vector_sum}\n        @scales.times {|s|\n         vectors[\"scale_#{s}\"]=@ds.dup(@items_per_scale.times.map {|i| \"#{s}_#{i}\"}).vector_sum \n        }\n        ds2=vectors.to_dataset\n        assert_equal(Statsample::Bivariate.correlation_matrix(ds2), @msa.correlation_matrix)\n      end\n      should \"delete scale using delete_scale\" do\n        @msa.delete_scale(\"complete\")\n        assert_equal(@msa.scales.keys.sort, @scales.times.map {|s| \"scale_#{s}\"})\n      end\n      should \"retrieve pca for scales\" do\n        @msa.delete_scale(\"complete\")\n        vectors=Hash.new\n        @scales.times {|s|\n         vectors[\"scale_#{s}\"]=@ds.dup(@items_per_scale.times.map {|i| \"#{s}_#{i}\"}).vector_sum \n        }\n        ds2=vectors.to_dataset\n        cor_matrix=Statsample::Bivariate.correlation_matrix(ds2)\n        m=3\n        pca=Statsample::Factor::PCA.new(cor_matrix, :m=>m)\n        assert_equal(pca.component_matrix, @msa.pca(:m=>m).component_matrix)\n      end\n      should \"retrieve acceptable summary\" do\n        @msa.delete_scale(\"scale_0\")\n        @msa.delete_scale(\"scale_1\")\n        @msa.delete_scale(\"scale_2\")\n        \n        \n        #@msa.summary_correlation_matrix=true\n        #@msa.summary_pca=true\n        \n        \n        assert(@msa.summary.size>0)\n      end\n    end\n    context Statsample::Reliability::ScaleAnalysis do\n      setup do \n        @x1=[1,1,1,1,2,2,2,2,3,3,3,30].to_scale\n        @x2=[1,1,1,2,2,3,3,3,3,4,4,50].to_scale\n        @x3=[2,2,1,1,1,2,2,2,3,4,5,40].to_scale\n        @x4=[1,2,3,4,4,4,4,3,4,4,5,30].to_scale\n        @ds={'x1'=>@x1,'x2'=>@x2,'x3'=>@x3,'x4'=>@x4}.to_dataset\n        @ia=Statsample::Reliability::ScaleAnalysis.new(@ds)\n        @cov_matrix=@ia.cov_m\n      end     \n      should \"return correct values for item analysis\" do \n        assert_in_delta(0.980,@ia.alpha,0.001)\n        assert_in_delta(0.999,@ia.alpha_standarized,0.001)\n        var_mean=4.times.map{|m| @cov_matrix[m,m]}.to_scale.mean \n        assert_in_delta(var_mean, @ia.variances_mean)\n        assert_equal(@x1.mean, @ia.item_statistics['x1'][:mean])\n        assert_equal(@x4.mean, @ia.item_statistics['x4'][:mean])\n        assert_in_delta(@x1.sds, @ia.item_statistics['x1'][:sds],1e-14)\n        assert_in_delta(@x4.sds, @ia.item_statistics['x4'][:sds],1e-14)\n        ds2=@ds.clone\n        ds2.delete_vector('x1')\n        vector_sum=ds2.vector_sum\n        assert_equal(vector_sum.mean, @ia.stats_if_deleted['x1'][:mean])\n        assert_equal(vector_sum.sds, @ia.stats_if_deleted['x1'][:sds])\n        assert_in_delta(vector_sum.variance, @ia.stats_if_deleted['x1'][:variance_sample],1e-10)\n\n        assert_equal(Statsample::Reliability.cronbach_alpha(ds2), @ia.stats_if_deleted['x1'][:alpha])\n        \n        covariances=[]\n        4.times.each {|i|\n          4.times.each {|j|\n            if i!=j \n              covariances.push(@cov_matrix[i,j])\n            end\n          }\n        }\n        assert_in_delta(covariances.to_scale.mean, @ia.covariances_mean)\n        assert_in_delta(0.999,@ia.item_total_correlation()['x1'],0.001)\n        assert_in_delta(1050.455,@ia.stats_if_deleted()['x1'][:variance_sample],0.001)\n      end\n      should \"return a summary\" do \n        assert(@ia.summary.size>0)\n      end\n      \n    end\n  end\nend\n"
  },
  {
    "path": "test/test_reliability_icc.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\n$reliability_icc=nil\n\nclass StatsampleReliabilityIccTestCase < MiniTest::Test\n  context Statsample::Reliability::ICC do\n    setup do\n      a=[9,6,8,7,10,6].to_scale\n      b=[2,1,4,1,5,2].to_scale\n      c=[5,3,6,2,6,4].to_scale\n      d=[8,2,8,6,9,7].to_scale\n      @ds={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n      @icc=Statsample::Reliability::ICC.new(@ds)\n    end\n    should \"basic method be correct\" do\n      assert_equal(6,@icc.n)\n      assert_equal(4,@icc.k)\n    end\n    should \"total mean be correct\" do\n      assert_in_delta(5.291, @icc.total_mean, 0.001)\n    end\n    should \"df methods be correct\" do\n      assert_equal(5,  @icc.df_bt)\n      assert_equal(18, @icc.df_wt)\n      assert_equal(3,  @icc.df_bj)\n      assert_equal(15, @icc.df_residual)\n    end\n    should \"ms between targets be correct\" do\n      assert_in_delta(11.24, @icc.ms_bt, 0.01)\n    end\n    should \"ms within targets be correct\" do\n      assert_in_delta(6.26,  @icc.ms_wt, 0.01)\n    end\n    should \"ms between judges be correct\" do \n      assert_in_delta(32.49, @icc.ms_bj, 0.01)\n    end\n    should \"ms residual be correct\" do\n      assert_in_delta(1.02,  @icc.ms_residual, 0.01)\n    end\n    context \"with McGraw and Wong denominations,\" do \n      \n    end\n    context \"with Shrout & Fleiss denominations, \" do \n      should \"icc(1,1) method be correct\" do\n        assert_in_delta(0.17, @icc.icc_1_1, 0.01)\n      end\n      # Verified on SPSS and R\n      should \"icc(2,1) method be correct\" do    \n        assert_in_delta(0.29, @icc.icc_2_1, 0.01)\n      end\n      should \"icc(3,1) method be correct\" do\n        assert_in_delta(0.71, @icc.icc_3_1, 0.01)\n      end\n      should \"icc(1,k) method be correct\" do\n        assert_in_delta(0.44, @icc.icc_1_k, 0.01)\n      end\n      # Verified on SPSS and R\n      should \"icc(2,k) method be correct\" do\n        assert_in_delta(0.62, @icc.icc_2_k, 0.01)\n      end \n      should \"icc(3,k) method be correct\" do\n        assert_in_delta(0.91, @icc.icc_3_k, 0.01)\n      end\n      \n      should \"icc(1,1) F be correct\" do\n        assert_in_delta(1.795, @icc.icc_1_f.f)\n      end\n      should \"icc(1,1) confidence interval should be correct\" do\n        assert_in_delta(-0.133, @icc.icc_1_1_ci[0], 0.001)\n        assert_in_delta(0.723, @icc.icc_1_1_ci[1], 0.001)\n      end\n      should \"icc(1,k) confidence interval should be correct\" do\n        assert_in_delta(-0.884, @icc.icc_1_k_ci[0], 0.001)\n        assert_in_delta(0.912, @icc.icc_1_k_ci[1], 0.001)\n      end\n      \n      should \"icc(2,1) F be correct\" do\n        assert_in_delta(11.027, @icc.icc_2_f.f)\n      end\n      should \"icc(2,1) confidence interval should be correct\" do\n        #skip(\"Not yet operational\")\n        assert_in_delta(0.019, @icc.icc_2_1_ci[0], 0.001)\n        assert_in_delta(0.761, @icc.icc_2_1_ci[1], 0.001)\n      end\n      \n      # Verified on SPSS and R      \n      should \"icc(2,k) confidence interval should be correct\" do\n        #skip(\"Not yet operational\")\n        #p @icc.icc_2_k_ci\n        assert_in_delta(0.039, @icc.icc_2_k_ci[0], 0.001)\n        assert_in_delta(0.929, @icc.icc_2_k_ci[1], 0.001)\n\n      end\n      #should \"Shrout icc(2,k) and McGraw icc(a,k) ci be equal\" do\n      #  assert_in_delta(@icc.icc_2_k_ci_shrout[0], @icc.icc_2_k_ci_mcgraw[0], 10e-5)\n      #end\n      \n      should \"icc(3,1) F be correct\" do\n        assert_in_delta(11.027, @icc.icc_3_f.f)\n      end\n      \n      should \"icc(3,1) confidence interval should be correct\" do\n        assert_in_delta(0.342, @icc.icc_3_1_ci[0], 0.001)\n        assert_in_delta(0.946, @icc.icc_3_1_ci[1], 0.001)\n      end\n      should \"icc(3,k) confidence interval should be correct\" do\n        assert_in_delta(0.676, @icc.icc_3_k_ci[0], 0.001)\n        assert_in_delta(0.986, @icc.icc_3_k_ci[1], 0.001)\n      end\n      should \"incorrect type raises an error\" do\n        assert_raise(::RuntimeError) do \n          @icc.type=:nonexistant_type\n        end\n      end\n    end\n    \n    begin\n      require 'rserve'\n      require 'statsample/rserve_extension'\n      context \"McGraw and Wong\" do\n        teardown do\n          @r=$reliability_icc[:r].close unless $reliability_icc[:r].nil?\n        end\n        setup do\n          if($reliability_icc.nil?)\n            size=100\n            a=size.times.map {rand(10)}.to_scale\n            b=a.recode{|i|i+rand(4)-2}\n            c=a.recode{|i|i+rand(4)-2}\n            d=a.recode{|i|i+rand(4)-2}\n            @ds={'a'=>a,'b'=>b,'c'=>c,'d'=>d}.to_dataset\n            \n            @icc=Statsample::Reliability::ICC.new(@ds)\n            @r=Rserve::Connection.new\n            \n            @r.assign('ds',@ds)\n          \n            @r.void_eval(\"library(irr);\n              iccs=list(\n              icc_1=icc(ds,'o','c','s'),\n              icc_k=icc(ds,'o','c','a'),\n              icc_c_1=icc(ds,'t','c','s'),\n              icc_c_k=icc(ds,'t','c','a'),\n              icc_a_1=icc(ds,'t','a','s'),\n              icc_a_k=icc(ds,'t','a','a'))\n              \")\n            @iccs=@r.eval('iccs').to_ruby\n            $reliability_icc={ :icc=>@icc, :iccs=>@iccs, :r=>@r\n            }\n            \n          end\n          @icc=$reliability_icc[:icc]\n          @iccs=$reliability_icc[:iccs]\n          @r=$reliability_icc[:r]\n\n        end\n        [:icc_1, :icc_k, :icc_c_1, :icc_c_k, :icc_a_1, :icc_a_k].each do |t|\n          context \"ICC Type #{t} \" do\n            should \"value be correct\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['value'],@icc.r)\n            end\n            should \"fvalue be correct\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['Fvalue'],@icc.f.f)\n            end\n            should \"num df be correct\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['df1'],@icc.f.df_num)\n            end\n            should \"den df be correct\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['df2'],@icc.f.df_den)\n            end\n\n            should \"f probability be correct\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['p.value'],@icc.f.probability)\n            end\n            should \"bounds be equal\" do\n              @icc.type=t\n              @r_icc=@iccs[t.to_s]\n              assert_in_delta(@r_icc['lbound'],@icc.lbound)\n              assert_in_delta(@r_icc['ubound'],@icc.ubound)  \n            end\n            should \"summary generated\" do\n              assert(@icc.summary.size>0)\n            end\n          end\n        end\n      end\n    rescue\n      puts \"requires rserve\"\n    end\n    \n  end\nend\n"
  },
  {
    "path": "test/test_reliability_skillscale.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\n\nclass StatsampleReliabilitySkillScaleTestCase < MiniTest::Unit::TestCase\n  context Statsample::Reliability::SkillScaleAnalysis do\n    setup do\n      options=%w{a b c d e}\n      cases=20\n      @id=cases.times.map {|v| v}.to_scale\n      @a=cases.times.map {options[rand(5)]}.to_vector\n      @b=cases.times.map {options[rand(5)]}.to_vector\n      @c=cases.times.map {options[rand(5)]}.to_vector\n      @d=cases.times.map {options[rand(5)]}.to_vector\n      @e=cases.times.map {|i|\n        i==0 ? options[rand(0)] : \n          rand()>0.8 ? nil : options[rand(5)]\n      }.to_vector\n      @ds={'id'=>@id,'a'=>@a,'b'=>@b,'c'=>@c,'d'=>@d,'e'=>@e}.to_dataset\n      @key={'a'=>\"a\", 'b'=>options[rand(5)], 'c'=>options[rand(5)], 'd'=>options[rand(5)],'e'=>options[rand(5)]}\n      @ssa=Statsample::Reliability::SkillScaleAnalysis.new(@ds, @key)\n      @ac=@a.map {|v| v==@key['a'] ? 1 : 0}.to_scale\n      @bc=@b.map {|v| v==@key['b'] ? 1 : 0}.to_scale\n      @cc=@c.map {|v| v==@key['c'] ? 1 : 0}.to_scale\n      @dc=@d.map {|v| v==@key['d'] ? 1 : 0}.to_scale\n      @ec=@e.map {|v| v.nil? ? nil : (v==@key['e'] ? 1 : 0)}.to_scale\n\n    end\n    should \"return proper corrected dataset\" do\n      cds={'id'=>@id, 'a'=>@ac,'b'=>@bc,'c'=>@cc,'d'=>@dc, 'e'=>@ec}.to_dataset\n      assert_equal(cds, @ssa.corrected_dataset)\n    end\n    should \"return proper corrected minimal dataset\" do\n      cdsm={'a'=>@ac,'b'=>@bc,'c'=>@cc,'d'=>@dc, 'e'=>@ec}.to_dataset\n      assert_equal(cdsm, @ssa.corrected_dataset_minimal)\n    end\n    should \"return correct vector_sum and vector_sum\" do\n      cdsm=@ssa.corrected_dataset_minimal\n      assert_equal(cdsm.vector_sum, @ssa.vector_sum)\n      assert_equal(cdsm.vector_mean, @ssa.vector_mean)\n    end\n    should \"not crash on rare case\" do\n      a=Statsample::Vector[\"c\",\"c\",\"a\",\"a\",\"c\",\"a\",\"b\",\"c\",\"c\",\"b\",\"a\",\"d\",\"a\",\"d\",\"a\",\"a\",\"d\",\"e\",\"c\",\"d\"]\n      b=Statsample::Vector[\"e\",\"b\",\"e\",\"b\",\"c\",\"d\",\"a\",\"e\",\"e\",\"c\",\"b\",\"e\",\"e\",\"b\",\"d\",\"c\",\"e\",\"b\",\"b\",\"d\"]\n      c=Statsample::Vector[\"e\",\"b\",\"e\",\"c\",\"e\",\"c\",\"b\",\"d\",\"e\",\"c\",\"a\",\"a\",\"b\",\"d\",\"e\",\"c\",\"b\",\"a\",\"a\",\"e\"]\n      d=Statsample::Vector[\"a\",\"b\",\"d\",\"d\",\"e\",\"b\",\"e\",\"b\",\"d\",\"c\",\"e\",\"a\",\"c\",\"d\",\"c\",\"c\",\"e\",\"d\",\"d\",\"b\"]\n      e=Statsample::Vector[\"a\",\"b\",nil,\"d\",\"c\",\"c\",\"d\",nil,\"d\",\"d\",\"e\",\"e\",nil,nil,nil,\"d\",\"c\",nil,\"e\",\"d\"]\n      key={\"a\"=>\"a\", \"b\"=>\"e\", \"c\"=>\"d\", \"d\"=>\"c\", \"e\"=>\"d\"}\n      ds=Statsample::Dataset.new(\"a\"=>a,\"b\"=>b,\"c\"=>c,\"d\"=>d,\"e\"=>e)\n      ssa=Statsample::Reliability::SkillScaleAnalysis.new(ds, key)\n      assert(ssa.summary)\n    end\n    \n    should \"return valid summary\" do\n      assert(@ssa.summary.size>0)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_resample.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleResampleTestCase < MiniTest::Unit::TestCase\n  def initialize(*args)\n    super\n  end\n  def test_basic\n    r=Statsample::Resample.generate(20,1,10)\n    assert_equal(20,r.size)\n    assert(r.min>=1)\n    assert(r.max<=10)\n  end\n  def test_repeat_and_save\n    r=Statsample::Resample.repeat_and_save(400) {\n      Statsample::Resample.generate(20,1,10).count(1)\n    }\n    assert_equal(400,r.size)\n    v=Statsample::Vector.new(r,:scale)\n    a=v.count {|x|  x > 3}\n    assert(a>=30 && a<=70)\n  end\nend\n"
  },
  {
    "path": "test/test_rserve_extension.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nbegin\n  require 'rserve'\n  require 'statsample/rserve_extension'\n\nclass StatsampleRserveExtensionTestCase < MiniTest::Unit::TestCase\n  context \"Statsample Rserve extensions\" do\n    setup do\n      @r=Rserve::Connection.new\n    end\n    teardown do\n      @r.close\n    end\n    should \"return a valid rexp for numeric vector\" do\n      a=100.times.map {|i| rand()>0.9 ? nil : i+rand() }.to_scale\n      rexp=a.to_REXP\n      assert(rexp.is_a? Rserve::REXP::Double)\n      assert_equal(rexp.to_ruby,a.data_with_nils)\n      @r.assign 'a',rexp\n      assert_equal(a.data_with_nils, @r.eval('a').to_ruby)\n    end\n    should \"return a valid rserve dataframe for statsample datasets\" do\n      a=100.times.map {|i| rand()>0.9 ? nil : i+rand() }.to_scale\n      b=100.times.map {|i| rand()>0.9 ? nil : i+rand() }.to_scale\n      c=100.times.map {|i| rand()>0.9 ? nil : i+rand() }.to_scale\n      ds={'a'=>a,'b'=>b,'c'=>c}.to_dataset\n      rexp=ds.to_REXP\n      assert(rexp.is_a? Rserve::REXP::GenericVector)\n      ret=rexp.to_ruby\n      assert_equal(a.data_with_nils, ret['a']) \n      @r.assign 'df', rexp\n      out_df=@r.eval('df').to_ruby\n      assert_equal('data.frame', out_df.attributes['class'])\n      assert_equal(['a','b','c'], out_df.attributes['names'])\n      assert_equal(a.data_with_nils, out_df['a'])\n    end\n  end\nend\n\nrescue LoadError\n  puts \"Require rserve extension\"\nend\n"
  },
  {
    "path": "test/test_srs.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleSrsTestCase < MiniTest::Unit::TestCase\n  def test_std_error\n    assert_equal(384,Statsample::SRS.estimation_n0(0.05,0.5,0.95).to_i)\n    assert_equal(108,Statsample::SRS.estimation_n(0.05,0.5,150,0.95).to_i)\n    assert_in_delta(0.0289,Statsample::SRS.proportion_sd_kp_wor(0.5,100,150),0.001)\n  end\nend\n"
  },
  {
    "path": "test/test_statistics.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleStatisicsTestCase < MiniTest::Unit::TestCase\n\n  def initialize(*args)\n    super\n  end\n  def test_p_using_cdf\n    assert_equal(0.25, Statsample::Test.p_using_cdf(0.25, tails=:left))\n    assert_equal(0.75, Statsample::Test.p_using_cdf(0.25, tails=:right))\n    assert_equal(0.50, Statsample::Test.p_using_cdf(0.25, tails=:both))\n    assert_equal(1, Statsample::Test.p_using_cdf(0.50, tails=:both))\n    assert_equal(0.05, Statsample::Test.p_using_cdf(0.025, tails=:both))\n    assert_in_delta(0.05, Statsample::Test.p_using_cdf(0.975, tails=:both),0.0001)\n    \n  end\n  def test_recode_repeated\n    a=%w{a b c c d d d e}\n    exp=[\"a\",\"b\",\"c_1\",\"c_2\",\"d_1\",\"d_2\",\"d_3\",\"e\"]\n    assert_equal(exp,a.recode_repeated)\n  end\n  def test_is_number\n    assert(\"10\".is_number?)\n    assert(\"-10\".is_number?)\n    assert(\"0.1\".is_number?)\n    assert(\"-0.1\".is_number?)\n    assert(\"10e3\".is_number?)\n    assert(\"10e-3\".is_number?)\n    assert(!\"1212-1212-1\".is_number?)\n    assert(!\"a10\".is_number?)\n    assert(!\"\".is_number?)\n\n  end\n  def test_estimation_mean\n    v=([42]*23+[41]*4+[36]*1+[32]*1+[29]*1+[27]*2+[23]*1+[19]*1+[16]*2+[15]*2+[14,11,10,9,7]+ [6]*3+[5]*2+[4,3]).to_vector(:scale)\n    assert_equal(50,v.size)\n    assert_equal(1471,v.sum())\n    #limits=Statsample::SRS.mean_confidence_interval_z(v.mean(), v.sds(), v.size,676,0.80)\n  end\n  def test_estimation_proportion\n    # total\n    pop=3042\n    sam=200\n    prop=0.19\n    assert_in_delta(81.8, Statsample::SRS.proportion_total_sd_ep_wor(prop, sam, pop), 0.1)\n\n    # confidence limits\n    pop=500\n    sam=100\n    prop=0.37\n    a=0.95\n    l= Statsample::SRS.proportion_confidence_interval_z(prop, sam, pop, a)\n    assert_in_delta(0.28,l[0],0.01)\n    assert_in_delta(0.46,l[1],0.01)\n  end\n  def test_ml\n    if(true)\n      #real=[1,1,1,1].to_vector(:scale)\n\n      #pred=[0.0001,0.0001,0.0001,0.0001].to_vector(:scale)\n      # puts  Statsample::Bivariate.maximum_likehood_dichotomic(pred,real)\n\n    end\n  end\n\n\n  def test_simple_linear_regression\n    a=[1,2,3,4,5,6].to_vector(:scale)\n    b=[6,2,4,10,12,8].to_vector(:scale)\n    reg = Statsample::Regression::Simple.new_from_vectors(a,b)\n    assert_in_delta((reg.ssr+reg.sse).to_f,reg.sst,0.001)\n    assert_in_delta(Statsample::Bivariate.pearson(a,b),reg.r,0.001)\n    assert_in_delta(2.4,reg.a,0.01)\n    assert_in_delta(1.314,reg.b,0.001)\n    assert_in_delta(0.657,reg.r,0.001)\n    assert_in_delta(0.432,reg.r2,0.001)\n  end\nend\n"
  },
  {
    "path": "test/test_stest.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleTestTestCase < MiniTest::Unit::TestCase\n  def test_chi_square_matrix_with_expected\n    real=Matrix[[95,95],[45,155]]\n    expected=Matrix[[68,122],[72,128]]\n    assert_nothing_raised do\n      Statsample::Test.chi_square(real,expected)\n    end\n    chi=Statsample::Test.chi_square(real,expected).chi_square\n    assert_in_delta(32.53,chi,0.1)\n    \n  end\n  def test_chi_square_matrix_only_observed\n    observed=Matrix[[20,30,40],[30,40,50],[60,70,80],[10,20,40]]\n    assert_nothing_raised do\n      Statsample::Test.chi_square(observed)\n    end\n    chi=Statsample::Test.chi_square(observed)\n    assert_in_delta(9.5602, chi.chi_square, 0.0001)\n    assert_in_delta(0.1444, chi.probability, 0.0001)\n\n    assert_equal(6, chi.df)\n    \n  end\n  \n  def test_u_mannwhitney\n    a=[1,2,3,4,5,6].to_scale\n    b=[0,5,7,9,10,11].to_scale\n    assert_equal(7.5, Statsample::Test.u_mannwhitney(a,b).u)\n    assert_equal(7.5, Statsample::Test.u_mannwhitney(b,a).u)\n    a=[1, 7,8,9,10,11].to_scale\n    b=[2,3,4,5,6,12].to_scale\n    assert_equal(11, Statsample::Test.u_mannwhitney(a,b).u)\n  end\n\n\n  def test_levene\n    a=[1,2,3,4,5,6,7,8,100,10].to_scale\n    b=[30,40,50,60,70,80,90,100,110,120].to_scale\n    levene=Statsample::Test::Levene.new([a,b])\n    assert_levene(levene)\n  end\n  def test_levene_dataset\n    a=[1,2,3,4,5,6,7,8,100,10].to_scale\n    b=[30,40,50,60,70,80,90,100,110,120].to_scale\n    ds={'a'=>a,'b'=>b}.to_dataset\n    levene=Statsample::Test::Levene.new(ds)\n    assert_levene(levene)\n  end\n  def assert_levene(levene)\n    assert_in_delta(0.778, levene.f, 0.001)\n    assert_in_delta(0.389, levene.probability, 0.001)\n  end\n \nend\n"
  },
  {
    "path": "test/test_stratified.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleStratifiedTestCase < MiniTest::Unit::TestCase\n\n  def initialize(*args)\n    super\n  end\n  def test_mean\n    a=[10,20,30,40,50]\n    b=[110,120,130,140]\n    pop=a+b\n    av=a.to_vector(:scale)\n    bv=b.to_vector(:scale)\n    popv=pop.to_vector(:scale)\n    assert_equal(popv.mean,Statsample::StratifiedSample.mean(av,bv))\n  end\nend\n"
  },
  {
    "path": "test/test_test_f.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleTestFTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Test::F) do \n    setup do\n      @ssb=84\n      @ssw=68\n      @df_num=2\n      @df_den=15\n      @f=Statsample::Test::F.new(@ssb.quo(@df_num),@ssw.quo(@df_den), @df_num, @df_den)\n    end\n    should \"have #f equal to msb/msw\" do\n      assert_equal((@ssb.quo(@df_num)).quo(@ssw.quo(@df_den)), @f.f)\n    end\n    should \"have df total equal to df_num+df_den\" do\n      assert_equal(@df_num + @df_den, @f.df_total)\n    end\n    should \"have probability near 0.002\" do \n      assert_in_delta(0.002, @f.probability, 0.0005)\n    end\n    should \"be coerced into float\" do\n      assert_equal(@f.to_f, @f.f)\n    end\n    \n    context(\"method summary\") do\n      setup do\n        @summary=@f.summary\n      end\n      should \"have size > 0\" do\n        assert(@summary.size>0)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_test_kolmogorovsmirnov.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleTestKolmogorovSmirnovTestCase < MiniTest::Unit::TestCase\n  context(Statsample::Test::KolmogorovSmirnov) do \n    should \"calculate correctly D for two given samples\" do\n      a=[1.1,2.5,5.6,9]\n      b=[1,2.3,5.8,10]\n      ks=Statsample::Test::KolmogorovSmirnov.new(a,b)\n      assert_equal(0.25,ks.d)\n    end\n    should \"calculate correctly D for a normal sample and Normal Distribution\" do\n      a=[0.30022510,-0.36664035,0.08593404,1.29881130,-0.49878633,-0.63056010, 0.28397638, -0.04913700,0.03566644,-1.33414346]\n      ks=Statsample::Test::KolmogorovSmirnov.new(a,Distribution::Normal)\n      assert_in_delta(0.282, ks.d,0.001)\n    end\n    should \"calculate correctly D for a variable normal and Normal Distribution\" do\n      rng=Distribution::Normal.rng\n      a=100.times.map {rng.call}\n      ks=Statsample::Test::KolmogorovSmirnov.new(a,Distribution::Normal)\n      assert(ks.d<0.15)\n    end\n    \n    context(Statsample::Test::KolmogorovSmirnov::EmpiricDistribution) do\n      should \"Create a correct empirical distribution for an array\" do\n        a=[10,9,8,7,6,5,4,3,2,1]\n        ed=Statsample::Test::KolmogorovSmirnov::EmpiricDistribution.new(a)\n        assert_equal(0, ed.cdf(-2))\n        assert_equal(0.5, ed.cdf(5))\n        assert_equal(0.5, ed.cdf(5.5))\n        assert_equal(0.9, ed.cdf(9))\n        assert_equal(1, ed.cdf(11))\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_test_t.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleTestTTestCase < MiniTest::Unit::TestCase\n  include Statsample::Test\n  include Math\n  context T do \n    setup do\n      @a=[30.02, 29.99, 30.11, 29.97, 30.01, 29.99].to_scale\n      @b=[29.89, 29.93, 29.72, 29.98, 30.02, 29.98].to_scale\n      @x1=@a.mean\n      @x2=@b.mean\n      @s1=@a.sd\n      @s2=@b.sd\n      @n1=@a.n\n      @n2=@b.n\n    end\n    should \"calculate correctly standard t\" do\n      t=Statsample::Test::T.new(@x1, @s1.quo(Math.sqrt(@a.n)), @a.n-1)\n      assert_equal((@x1).quo(@s1.quo(Math.sqrt(@a.n))), t.t)\n      assert_equal(@a.n-1, t.df)\n      assert(t.summary.size>0)\n    end\n    should \"calculate correctly t for one sample\" do\n      t1=[6, 4, 6, 7, 4,5,5,12,6,1].to_scale\n      t2=[9, 6, 5,10,10,8,7,10,6,5].to_scale\n      d=t1-t2\n      t=Statsample::Test::T::OneSample.new(d)\n      assert_in_delta(-2.631, t.t, 0.001)\n      assert_in_delta( 0.027, t.probability, 0.001)\n      assert_in_delta( 0.76012, t.se, 0.0001)\n      assert(t.summary.size>0)\n    end\n    should \"calculate correctly t for two samples\" do\n      assert_in_delta(1.959, T.two_sample_independent(@x1, @x2, @s1, @s2, @n1, @n2),0.001)\n      assert_in_delta(1.959, T.two_sample_independent(@x1, @x2, @s1, @s2, @n1, @n2,true),0.001)\n    end\n    should \"calculate correctly df for equal and unequal variance\" do\n      assert_equal(10,  T.df_equal_variance(@n1,@n2))\n      assert_in_delta(7.03,  T.df_not_equal_variance(@s1,@s2,@n1,@n2),0.001)    \n    end\n    should \"calculate all values for T object\" do\n      t=Statsample::Test.t_two_samples_independent(@a,@b)\n      assert(t.summary.size>0)\n      assert_in_delta(1.959, t.t_equal_variance,0.001)\n      assert_in_delta(1.959, t.t_not_equal_variance,0.001)\n      assert_in_delta(10, t.df_equal_variance,0.001)\n      assert_in_delta(7.03, t.df_not_equal_variance,0.001)\n      assert_in_delta(0.07856, t.probability_equal_variance,0.001)\n      assert_in_delta(0.09095, t.probability_not_equal_variance,0.001)\n    end\n    should \"be the same using shorthand\" do\n      v=100.times.map {rand(100)}.to_scale\n      assert_equal(Statsample::Test.t_one_sample(v).t, T::OneSample.new(v).t)\n    end\n    should \"calculate all values for one sample T test\" do\n      u=@a.mean+(1-rand*2)\n      tos=T::OneSample.new(@a,{:u=>u})\n      assert_equal((@a.mean-u).quo(@a.sd.quo(sqrt(@a.n))), tos.t)\n      assert_equal(@a.n-1, tos.df)\n      assert(tos.summary.size>0)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_umannwhitney.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleUMannWhitneyTestCase < MiniTest::Unit::TestCase\n  include Statsample::Test\n  context Statsample::Test::UMannWhitney do\n    setup do\n      @v1=[1,2,3,4,7,8,9,10,14,15].to_scale\n      @v2=[5,6,11,12,13,16,17,18,19].to_scale\n      @u=Statsample::Test::UMannWhitney.new(@v1,@v2)\n    end\n    should \"have same result using class or Test#u_mannwhitney\" do \n      assert_equal(Statsample::Test.u_mannwhitney(@v1,@v2).u, @u.u) \n    end\n    should \"have correct U values\" do\n      assert_equal(73,@u.r1)\n      assert_equal(117,@u.r2)\n      assert_equal(18,@u.u)\n    end\n    should \"have correct value for z\" do\n      assert_in_delta(-2.205,@u.z,0.001)\n    end\n    should \"have correct value for z and exact probability\" do\n      assert_in_delta(0.027,@u.probability_z,0.001)\n      assert_in_delta(0.028,@u.probability_exact,0.001)\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_vector.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleTestVector < MiniTest::Unit::TestCase\n  include Statsample::Shorthand\n\n  def setup\n    @c = Statsample::Vector.new([5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99], :nominal)\n    @c.name=\"Test Vector\"\n    @c.missing_values=[-99]\n  end\n  def assert_counting_tokens(b)\n    assert_equal([1,1,0,1,0,nil],b['a'].to_a)\n    assert_equal([0,1,0,0,0,nil],b['b'].to_a)\n    assert_equal([0,0,1,0,0,nil],b['c'].to_a)\n    assert_equal([0,0,1,1,0,nil],b['d'].to_a)\n    assert_equal([0,0,0,0,1,nil],b[10].to_a)\n  end\n  context Statsample do\n    setup do\n      @sample=100\n      @a=@sample.times.map{|i| (i+rand(10)) %10 ==0 ? nil : rand(100)}.to_scale\n      @b=@sample.times.map{|i| (i+rand(10)) %10 ==0 ? nil : rand(100)}.to_scale\n      @correct_a=Array.new\n      @correct_b=Array.new\n      @a.each_with_index do |v,i|\n        if !@a[i].nil? and !@b[i].nil?\n          @correct_a.push(@a[i])\n          @correct_b.push(@b[i])\n        end\n      end\n      @correct_a=@correct_a.to_scale\n      @correct_b=@correct_b.to_scale\n\n      @common=lambda  do |av,bv|\n        assert_equal(@correct_a, av, \"A no es esperado\")\n        assert_equal(@correct_b, bv, \"B no es esperado\")\n        assert(!av.has_missing_data?, \"A tiene datos faltantes\")\n        assert(!bv.has_missing_data?, \"b tiene datos faltantes\")\n      end\n    end\n    should \"return correct only_valid\" do\n      av,bv=Statsample.only_valid @a,@b\n      av2,bv2=Statsample.only_valid av,bv\n      @common.call(av,bv)\n      assert_equal(av,av2)\n      assert_not_same(av,av2)\n      assert_not_same(bv,bv2)\n    end\n    should \"return correct only_valid_clone\" do\n      av,bv=Statsample.only_valid_clone @a,@b\n      @common.call(av,bv)\n      av2,bv2=Statsample.only_valid_clone av,bv\n      assert_equal(av,av2)\n      assert_same(av,av2)\n      assert_same(bv,bv2)\n    end\n  end\n  context Statsample::Vector do\n    setup do\n      @c = Statsample::Vector.new([5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99], :nominal)\n      @c.name=\"Test Vector\"\n      @c.missing_values=[-99]\n    end\n    should_with_gsl \"be created with GSL::Vector\" do\n      gsl=GSL::Vector[1,2,3,4,5]\n      v=Statsample::Vector.new(gsl)\n      assert_equal([1,2,3,4,5], v.to_a)\n      refute(v.flawed?)\n\n    end\n\n    context \"using matrix operations\" do\n      setup do\n        @a=[1,2,3,4,5].to_scale\n      end\n      should \"to_matrix returns a matrix with 1 row\" do\n        mh=Matrix[[1,2,3,4,5]]\n        assert_equal(mh,@a.to_matrix)\n      end\n      should \"to_matrix(:vertical) returns a matrix with 1 column\" do\n        mv=Matrix.columns([[1,2,3,4,5]])\n        assert_equal(mv,@a.to_matrix(:vertical))\n      end\n      should \"returns valid submatrixes\" do\n        # 3*4 + 2*5 = 22\n        a=[3,2].to_vector(:scale)\n        b=[4,5].to_vector(:scale)\n        assert_equal(22,(a.to_matrix*b.to_matrix(:vertical))[0,0])\n      end\n    end\n    context \"when initializing\" do\n      setup do\n        @data=(10.times.map{rand(100)})+[nil]\n        @original=Statsample::Vector.new(@data, :scale)\n      end\n      should \"be the sample using []\" do\n        second=Statsample::Vector[*@data]\n        assert_equal(@original, second)\n      end\n      should \"[] returns same results as R-c()\" do\n        reference=[0,4,5,6,10].to_scale\n        assert_equal(reference, Statsample::Vector[0,4,5,6,10])\n        assert_equal(reference, Statsample::Vector[0,4..6,10])\n        assert_equal(reference, Statsample::Vector[[0],[4,5,6],[10]])\n        assert_equal(reference, Statsample::Vector[[0],[4,[5,[6]]],[10]])\n\n        assert_equal(reference, Statsample::Vector[[0],[4,5,6].to_vector,[10]])\n\n      end\n      should \"be the same usign #to_vector\" do\n        lazy1=@data.to_vector(:scale)\n        assert_equal(@original,lazy1)\n      end\n      should \"be the same using #to_scale\" do\n        lazy2=@data.to_scale\n        assert_equal(@original,lazy2)\n        assert_equal(:scale,lazy2.type)\n        assert_equal(@data.find_all{|v| !v.nil?},lazy2.valid_data)\n      end\n      should \"could use new_scale with size only\" do\n        v1=10.times.map {nil}.to_scale\n        v2=Statsample::Vector.new_scale(10)\n        assert_equal(v1,v2)\n\n      end\n      should \"could use new_scale with size and value\" do\n        a=rand\n        v1=10.times.map {a}.to_scale\n        v2=Statsample::Vector.new_scale(10,a)\n        assert_equal(v1,v2)\n      end\n      should \"could use new_scale with func\" do\n        v1=10.times.map {|i| i*2}.to_scale\n        v2=Statsample::Vector.new_scale(10) {|i| i*2}\n        assert_equal(v1,v2)\n      end\n\n    end\n\n    context \"#split_by_separator\" do\n\n      setup do\n        @a = Statsample::Vector.new([\"a\",\"a,b\",\"c,d\",\"a,d\",10,nil],:nominal)\n        @b=@a.split_by_separator(\",\")\n      end\n      should \"returns a Hash\" do\n        assert_kind_of(Hash, @b)\n      end\n      should \"return a Hash with keys with different values of @a\" do\n        expected=['a','b','c','d',10]\n        assert_equal(expected, @b.keys)\n      end\n\n      should \"returns a Hash, which values are Statsample::Vector\" do\n        @b.each_key {|k| assert_instance_of(Statsample::Vector, @b[k])}\n      end\n      should \"hash values are n times the tokens appears\" do\n        assert_counting_tokens(@b)\n      end\n      should \"#split_by_separator_freq returns the number of ocurrences of tokens\" do\n        assert_equal({'a'=>3,'b'=>1,'c'=>1,'d'=>2,10=>1}, @a.split_by_separator_freq())\n      end\n      should \"using a different separator give the same values\" do\n        a = Statsample::Vector.new([\"a\",\"a*b\",\"c*d\",\"a*d\",10,nil],:nominal)\n        b=a.split_by_separator(\"*\")\n        assert_counting_tokens(b)\n      end\n    end\n    should \"return correct median_absolute_deviation\" do\n      a=[1, 1, 2, 2, 4, 6, 9].to_scale\n      assert_equal(1, a.median_absolute_deviation)\n    end\n    should \"return correct histogram\" do\n      a=10.times.map {|v| v}.to_scale\n      hist=a.histogram(2)\n      assert_equal([5,5], hist.bin)\n      3.times do |i|\n        assert_in_delta(i*4.5, hist.get_range(i)[0], 1e-9)\n      end\n\n    end\n    should \"have a name\" do\n      @c.name==\"Test Vector\"\n    end\n    should \"without explicit name, returns vector with succesive numbers\" do\n      a=10.times.map{rand(100)}.to_scale\n      b=10.times.map{rand(100)}.to_scale\n      assert_match(/Vector \\d+/, a.name)\n      a.name=~/Vector (\\d+)/\n      next_number=$1.to_i+1\n      assert_equal(\"Vector #{next_number}\",b.name)\n    end\n    should \"save to a file and load the same Vector\" do\n      outfile=Tempfile.new(\"vector.vec\")\n      @c.save(outfile.path)\n      a=Statsample.load(outfile.path)\n      assert_equal(@c,a)\n    end\n    should \"#collect returns an array\" do\n      val=@c.collect {|v| v}\n      assert_equal(val,[5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99])\n    end\n\n    should \"#recode returns a recoded array\" do\n      a=@c.recode{|v| @c.is_valid?(v) ? 0 : 1 }\n      exp=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1].to_vector\n      assert_equal(exp,a)\n      exp.recode!{|v| v==0 ? 1:0}\n      exp2=(([1]*15)+([0]*3)).to_vector\n      assert_equal(exp2,exp)\n    end\n    should \"#product returns the * of all values\" do\n      a=[1,2,3,4,5].to_vector(:scale)\n      assert_equal(120,a.product)\n    end\n\n    should \"missing values\" do\n      @c.missing_values=[10]\n      assert_equal([-99,-99,1,2,3,4,5,5,5,5,5,6,6,7,8,9], @c.valid_data.sort)\n      assert_equal([5,5,5,5,5,6,6,7,8,9,nil,1,2,3,4,nil,-99,-99], @c.data_with_nils)\n      @c.missing_values=[-99]\n      assert_equal(@c.valid_data.sort,[1,2,3,4,5,5,5,5,5,6,6,7,8,9,10])\n      assert_equal(@c.data_with_nils,[5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,nil,nil])\n      @c.missing_values=[]\n      assert_equal(@c.valid_data.sort,[-99,-99,1,2,3,4,5,5,5,5,5,6,6,7,8,9,10])\n      assert_equal(@c.data_with_nils,[5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99])\n\n    end\n    should \"correct has_missing_data? with missing data\" do\n      a=[1,2,3,nil].to_vector\n      assert(a.has_missing_data?)\n    end\n    should \"correct has_missing_data? without missing data\" do\n      a=[1,2,3,4,10].to_vector\n      assert(!a.has_missing_data?)\n    end\n    should \"with explicit missing_values, should respond has_missing_data?\" do\n      a=[1,2,3,4,10].to_vector\n      a.missing_values=[10]\n      assert(a.has_missing_data?)\n    end\n    should \"label correctly fields\" do\n      @c.labels={5=>'FIVE'}\n      assert_equal([\"FIVE\",\"FIVE\",\"FIVE\",\"FIVE\",\"FIVE\",6,6,7,8,9,10,1,2,3,4,nil,-99, -99],@c.vector_labeled.to_a)\n    end\n    should \"verify\" do\n      h=@c.verify{|d| !d.nil? and d>0}\n      e={15=>nil,16=>-99,17=>-99}\n      assert_equal(e,h)\n    end\n    should \"have a summary with name on it\" do\n      assert_match(/#{@c.name}/, @c.summary)\n    end\n\n    should \"GSL::Vector based should push correcty\" do\n      if Statsample.has_gsl?\n        v=GSL::Vector[1,2,3,4,5].to_scale\n        v.push(nil)\n        assert_equal([1,2,3,4,5,nil], v.to_a)\n        assert(v.flawed?)\n      else\n        skip(\"Requires GSL\")\n      end\n    end\n\n\n    should \"split correctly\" do\n      a = Statsample::Vector.new([\"a\",\"a,b\",\"c,d\",\"a,d\",\"d\",10,nil],:nominal)\n      assert_equal([%w{a},%w{a b},%w{c d},%w{a d},%w{d},[10],nil], a.splitted)\n    end\n    should \"multiply correct for scalar\" do\n      a = [1,2,3].to_scale\n      assert_equal([5,10,15].to_scale, a*5)\n    end\n    should \"multiply correct with other vector\" do\n      a = [1,2,3].to_scale\n      b = [2,4,6].to_scale\n\n      assert_equal([2,8,18].to_scale, a*b)\n    end\n    should \"sum correct for scalar\" do\n      a = [1,2,3].to_scale\n      assert_equal([11,12,13].to_scale, a+10)\n    end\n\n    should \"raise NoMethodError when method requires ordinal and vector is nominal\" do\n      @c.type=:nominal\n      assert_raise(::NoMethodError) { @c.median }\n    end\n\n    should \"raise NoMethodError when method requires scalar and vector is ordinal\" do\n      @c.type=:ordinal\n      assert_raise(::NoMethodError) { @c.mean }\n    end\n    should \"jacknife correctly with named method\" do\n      # First example\n      a=[1,2,3,4].to_scale\n      ds=a.jacknife(:mean)\n      assert_equal(a.mean, ds[:mean].mean)\n      ds=a.jacknife([:mean,:sd])\n      assert_equal(a.mean, ds[:mean].mean)\n      assert_equal(a.sd, ds[:mean].sd)\n    end\n    should \"jacknife correctly with custom method\" do\n      # Second example\n      a=[17.23, 18.71,13.93,18.81,15.78,11.29,14.91,13.39, 18.21, 11.57, 14.28, 10.94, 18.83, 15.52,13.45,15.25].to_scale\n      ds=a.jacknife(:log_s2=>lambda {|v|  Math.log(v.variance) })\n      exp=[1.605, 2.972, 1.151, 3.097, 0.998, 3.308, 0.942, 1.393, 2.416, 2.951, 1.043, 3.806, 3.122, 0.958, 1.362, 0.937].to_scale\n\n      assert_similar_vector(exp, ds[:log_s2], 0.001)\n      assert_in_delta(2.00389, ds[:log_s2].mean, 0.00001)\n      assert_in_delta(1.091, ds[:log_s2].variance, 0.001)\n    end\n    should \"jacknife correctly with k>1\" do\n      a=rnorm(6)\n      ds=a.jacknife(:mean,2)\n      mean=a.mean\n      exp=[3*mean-2*(a[2]+a[3]+a[4]+a[5]) / 4, 3*mean-2*(a[0]+a[1]+a[4]+a[5]) / 4, 3*mean-2*(a[0]+a[1]+a[2]+a[3]) / 4].to_scale\n      assert_similar_vector(exp, ds[:mean], 1e-13)\n    end\n    should \"bootstrap should return a vector with mean=mu and sd=se\" do\n      a=rnorm(100)\n      ds=a.bootstrap([:mean,:sd],200)\n      se=1/Math.sqrt(a.size)\n      assert_in_delta(0, ds[:mean].mean, 0.3)\n      assert_in_delta(se, ds[:mean].sd, 0.02)\n    end\n\n\n  end\n\n\n\n  def test_nominal\n    assert_equal(@c[1],5)\n    assert_equal({ 1=>1,2=>1,3=>1,4=>1,5=>5,6=>2,7=>1,8=>1, 9=>1,10=>1},@c.frequencies)\n    assert_equal({ 1=>1,2=>1,3=>1,4=>1,5=>5,6=>2,7=>1,8=>1, 9=>1,10=>1},@c._frequencies)\n    assert_equal({ 1 => 1.quo(15) ,2=>1.quo(15), 3=>1.quo(15),4=>1.quo(15),5=>5.quo(15),6=>2.quo(15),7=>1.quo(15), 8=>1.quo(15), 9=>1.quo(15),10=>1.quo(15)}, @c.proportions)\n    assert_equal(@c.proportion, 1.quo(15))\n    assert_equal(@c.proportion(2), 1.quo(15))\n    assert_equal([1,2,3,4,5,6,7,8,9,10], @c.factors.sort)\n    assert_equal(@c.mode,5)\n    assert_equal(@c.n_valid,15)\n  end\n  def test_equality\n    v1=[1,2,3].to_vector\n    v2=[1,2,3].to_vector\n    assert_equal(v1,v2)\n    v1=[1,2,3].to_vector(:nominal)\n    v2=[1,2,3].to_vector(:ordinal)\n    assert_not_equal(v1,v2)\n    v2=[1,2,3]\n    assert_not_equal(v1,v2)\n    v1=[1,2,3].to_vector()\n    v2=[1,2,3].to_vector()\n    assert_equal(v1,v2)\n    assert_equal(false, v1 == Object.new)\n  end\n  def test_vector_percentil\n    a=[1,2,2,3,4,5,5,5,6,10].to_scale\n    expected=[10,25,25,40,50,70,70,70,90,100].to_scale\n    assert_equal(expected, a.vector_percentil)\n    a=[1,nil,nil,2,2,3,4,nil,nil,5,5,5,6,10].to_scale\n    expected=[10,nil,nil,25,25,40,50,nil,nil,70,70,70,90,100].to_scale\n    assert_equal(expected, a.vector_percentil)\n  end\n  def test_ordinal\n    @c.type=:ordinal\n    assert_equal(5,@c.median)\n    assert_equal(4,@c.percentil(25))\n    assert_equal(7,@c.percentil(75))\n\n    v=[200000, 200000, 210000, 220000, 230000, 250000, 250000, 250000, 270000, 300000, 450000, 130000, 140000, 140000, 140000, 145000, 148000, 165000, 170000, 180000, 180000, 180000, 180000, 180000, 180000 ].to_scale\n    assert_equal(180000,v.median)\n    a=[7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 9.0, 9.0, 10.0, 10.0, 10.0, 10.0, 10.0, 12.0, 12.0, 13.0, 14.0, 14.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0].to_scale\n    assert_equal(4.5, a.percentil(25))\n    assert_equal(6.5, a.percentil(50))\n    assert_equal(9.5, a.percentil(75))\n    assert_equal(3.0, a.percentil(10))\n  end\n  def test_linear_percentil_strategy\n    values = [102, 104, 105, 107, 108, 109, 110, 112, 115, 116].shuffle.to_scale\n    assert_equal 102, values.percentil(0, :linear)\n    assert_equal 104.75, values.percentil(25, :linear)\n    assert_equal 108.5, values.percentil(50, :linear)\n    assert_equal 112.75, values.percentil(75, :linear)\n    assert_equal 116, values.percentil(100, :linear)\n\n    values = [102, 104, 105, 107, 108, 109, 110, 112, 115, 116, 118].shuffle.to_scale\n    assert_equal 102, values.percentil(0, :linear)\n    assert_equal 105, values.percentil(25, :linear)\n    assert_equal 109, values.percentil(50, :linear)\n    assert_equal 115, values.percentil(75, :linear)\n    assert_equal 118, values.percentil(100, :linear)\n  end\n  def test_ranked\n    v1=[0.8,1.2,1.2,2.3,18].to_vector(:ordinal)\n    expected=[1,2.5,2.5,4,5].to_vector(:ordinal)\n    assert_equal(expected,v1.ranked)\n    v1=[nil,0.8,1.2,1.2,2.3,18,nil].to_vector(:ordinal)\n    expected=[nil,1,2.5,2.5,4,5,nil].to_vector(:ordinal)\n    assert_equal(expected,v1.ranked)\n  end\n  def test_scale\n    a=Statsample::Vector.new([1,2,3,4,\"STRING\"], :scale)\n    assert_equal(10, a.sum)\n    i=0\n    factors=a.factors.sort\n    [0,1,2,3,4].each{|v|\n      assert(v==factors[i])\n      assert(v.class==factors[i].class,\"#{v} - #{v.class} != #{factors[i]} - #{factors[i].class}\")\n      i+=1\n    }\n  end\n  def test_vector_centered\n    mean=rand()\n    samples=11\n    centered=samples.times.map {|i| i-((samples/2).floor).to_i}.to_scale\n    not_centered=centered.recode {|v| v+mean}\n    obs=not_centered.centered\n    centered.each_with_index do |v,i|\n      assert_in_delta(v,obs[i],0.0001)\n    end\n  end\n  def test_vector_standarized\n    v1=[1,2,3,4,nil].to_vector(:scale)\n    sds=v1.sds\n    expected=[((1-2.5).quo(sds)),((2-2.5).quo(sds)),((3-2.5).quo(sds)),((4-2.5).quo(sds)), nil].to_vector(:scale)\n    vs=v1.vector_standarized\n    assert_equal(expected, vs)\n    assert_equal(0,vs.mean)\n    assert_equal(1,vs.sds)\n  end\n\n  def test_vector_standarized_with_zero_variance\n    v1=100.times.map {|i| 1}.to_scale\n    exp=100.times.map {nil}.to_scale\n    assert_equal(exp,v1.standarized)\n  end\n\n    def test_check_type\n    v=Statsample::Vector.new\n    v.type=:nominal\n    assert_raise(NoMethodError) { v.check_type(:scale)}\n    assert_raise(NoMethodError) { v.check_type(:ordinal)}\n    assert(v.check_type(:nominal).nil?)\n\n    v.type=:ordinal\n\n    assert_raise(NoMethodError) { v.check_type(:scale)}\n\n    assert(v.check_type(:ordinal).nil?)\n    assert(v.check_type(:nominal).nil?)\n\n\n    v.type=:scale\n    assert(v.check_type(:scale).nil?)\n    assert(v.check_type(:ordinal).nil?)\n    assert(v.check_type(:nominal).nil?)\n\n    v.type=:date\n    assert_raise(NoMethodError) { v.check_type(:scale)}\n    assert_raise(NoMethodError) { v.check_type(:ordinal)}\n    assert_raise(NoMethodError) { v.check_type(:nominal)}\n  end\n\n  def test_add\n    a=Statsample::Vector.new([1,2,3,4,5], :scale)\n    b=Statsample::Vector.new([11,12,13,14,15], :scale)\n    assert_equal([3,4,5,6,7], (a+2).to_a)\n    assert_equal([12,14,16,18,20], (a+b).to_a)\n    assert_raise  ArgumentError do\n      a + @c\n    end\n    assert_raise  TypeError do\n      a+\"string\"\n    end\n    a=Statsample::Vector.new([nil,1, 2  ,3 ,4 ,5], :scale)\n    b=Statsample::Vector.new([11, 12,nil,13,14,15], :scale)\n    assert_equal([nil,13,nil,16,18,20], (a+b).to_a)\n    assert_equal([nil,13,nil,16,18,20], (a+b.to_a).to_a)\n  end\n  def test_minus\n    a=Statsample::Vector.new([1,2,3,4,5], :scale)\n    b=Statsample::Vector.new([11,12,13,14,15], :scale)\n    assert_equal([-1,0,1,2,3], (a-2).to_a)\n    assert_equal([10,10,10,10,10], (b-a).to_a)\n    assert_raise  ArgumentError do\n      a-@c\n    end\n    assert_raise  TypeError do\n      a-\"string\"\n    end\n    a=Statsample::Vector.new([nil,1, 2  ,3 ,4 ,5], :scale)\n    b=Statsample::Vector.new([11, 12,nil,13,14,15], :scale)\n    assert_equal([nil,11,nil,10,10,10], (b-a).to_a)\n    assert_equal([nil,11,nil,10,10,10], (b-a.to_a).to_a)\n  end\n  def test_sum_of_squares\n    a=[1,2,3,4,5,6].to_vector(:scale)\n    assert_equal(17.5, a.sum_of_squared_deviation)\n  end\n  def test_average_deviation\n    a=[1,2,3,4,5,6,7,8,9].to_scale\n    assert_equal(20.quo(9), a.average_deviation_population)\n  end\n  def test_samples\n    srand(1)\n    assert_equal(100,@c.sample_with_replacement(100).size)\n    assert_equal(@c.valid_data.to_a.sort, @c.sample_without_replacement(15).sort)\n    assert_raise  ArgumentError do\n      @c.sample_without_replacement(20)\n    end\n    @c.type=:scale\n    srand(1)\n    assert_equal(100, @c.sample_with_replacement(100).size)\n    assert_equal(@c.valid_data.to_a.sort, @c.sample_without_replacement(15).sort)\n\n  end\n  def test_valid_data\n    a=Statsample::Vector.new([1,2,3,4,\"STRING\"])\n    a.missing_values=[-99]\n    a.add(1,false)\n    a.add(2,false)\n    a.add(-99,false)\n    a.set_valid_data\n    exp_valid_data=[1,2,3,4,\"STRING\",1,2]\n    assert_equal(exp_valid_data,a.valid_data)\n    a.add(20,false)\n    a.add(30,false)\n    assert_equal(exp_valid_data,a.valid_data)\n    a.set_valid_data\n    exp_valid_data_2=[1,2,3,4,\"STRING\",1,2,20,30]\n    assert_equal(exp_valid_data_2,a.valid_data)\n  end\n  def test_set_value\n    @c[2]=10\n    expected=[5,5,10,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99].to_vector\n    assert_equal(expected.data,@c.data)\n  end\n  def test_gsl\n    if Statsample.has_gsl?\n      a=Statsample::Vector.new([1,2,3,4,\"STRING\"], :scale)\n\n      assert_equal(2,a.mean)\n      assert_equal(a.variance_sample_ruby,a.variance_sample)\n      assert_equal(a.standard_deviation_sample_ruby,a.sds)\n      assert_equal(a.variance_population_ruby,a.variance_population)\n      assert_equal(a.standard_deviation_population_ruby,a.standard_deviation_population)\n      assert_nothing_raised do\n        a=[].to_vector(:scale)\n      end\n      a.add(1,false)\n      a.add(2,false)\n      a.set_valid_data\n      assert_equal(3,a.sum)\n      b=[1,2,nil,3,4,5,nil,6].to_vector(:scale)\n      assert_equal(21, b.sum)\n      assert_equal(3.5, b.mean)\n      assert_equal(6,b.gsl.size)\n      c=[10,20,30,40,50,100,1000,2000,5000].to_scale\n      assert_in_delta(c.skew,     c.skew_ruby     ,0.0001)\n      assert_in_delta(c.kurtosis, c.kurtosis_ruby ,0.0001)\n    end\n  end\n  def test_vector_matrix\n    v1=%w{a a a b b b c c}.to_vector\n    v2=%w{1 3 4 5 6 4 3 2}.to_vector\n    v3=%w{1 0 0 0 1 1 1 0}.to_vector\n    ex=Matrix.rows([[\"a\", \"1\", \"1\"], [\"a\", \"3\", \"0\"], [\"a\", \"4\", \"0\"], [\"b\", \"5\", \"0\"], [\"b\", \"6\", \"1\"], [\"b\", \"4\", \"1\"], [\"c\", \"3\", \"1\"], [\"c\", \"2\", \"0\"]])\n    assert_equal(ex,Statsample.vector_cols_matrix(v1,v2,v3))\n  end\n  def test_marshalling\n    v1=(0..100).to_a.collect{|n| rand(100)}.to_vector(:scale)\n    v2=Marshal.load(Marshal.dump(v1))\n    assert_equal(v1,v2)\n  end\n  def test_dup\n    v1=%w{a a a b b b c c}.to_vector\n    v2=v1.dup\n    assert_equal(v1.data,v2.data)\n    assert_not_same(v1.data,v2.data)\n    assert_equal(v1.type,v2.type)\n\n    v1.type=:ordinal\n    assert_not_equal(v1.type,v2.type)\n    assert_equal(v1.missing_values,v2.missing_values)\n    assert_not_same(v1.missing_values,v2.missing_values)\n    assert_equal(v1.labels,v2.labels)\n    assert_not_same(v1.labels,v2.labels)\n\n    v3=v1.dup_empty\n    assert_equal([],v3.data)\n    assert_not_equal(v1.data,v3.data)\n    assert_not_same(v1.data,v3.data)\n    assert_equal(v1.type,v3.type)\n    v1.type=:ordinal\n    v3.type=:nominal\n    assert_not_equal(v1.type,v3.type)\n    assert_equal(v1.missing_values,v3.missing_values)\n    assert_not_same(v1.missing_values,v3.missing_values)\n    assert_equal(v1.labels,v3.labels)\n    assert_not_same(v1.labels,v3.labels)\n  end\n  def test_paired_ties\n    a=[0,0,0,1,1,2,3,3,4,4,4].to_vector(:ordinal)\n    expected=[2,2,2,4.5,4.5,6,7.5,7.5,10,10,10].to_vector(:ordinal)\n    assert_equal(expected,a.ranked)\n  end\n  def test_dichotomize\n    a=  [0,0,0,1,2,3,nil].to_vector\n    exp=[0,0,0,1,1,1,nil].to_scale\n    assert_equal(exp,a.dichotomize)\n    a=  [1,1,1,2,2,2,3].to_vector\n    exp=[0,0,0,1,1,1,1].to_scale\n    assert_equal(exp,a.dichotomize)\n    a=  [0,0,0,1,2,3,nil].to_vector\n    exp=[0,0,0,0,1,1,nil].to_scale\n    assert_equal(exp,a.dichotomize(1))\n    a= %w{a a a b c d}.to_vector\n    exp=[0,0,0,1,1,1].to_scale\n    assert_equal(exp, a.dichotomize)\n  end\n  def test_can_be_methods\n    a=  [0,0,0,1,2,3,nil].to_vector\n    assert(a.can_be_scale?)\n    a=[0,\"s\",0,1,2,3,nil].to_vector\n    assert(!a.can_be_scale?)\n    a.missing_values=[\"s\"]\n    assert(a.can_be_scale?)\n\n    a=[Date.new(2009,10,10), Date.today(), \"2009-10-10\", \"2009-1-1\", nil, \"NOW\"].to_vector\n    assert(a.can_be_date?)\n    a=[Date.new(2009,10,10), Date.today(),nil,\"sss\"].to_vector\n    assert(!a.can_be_date?)\n  end\n  def test_date_vector\n    a=[Date.new(2009,10,10), :NOW, \"2009-10-10\", \"2009-1-1\", nil, \"NOW\",\"MISSING\"].to_vector(:date, :missing_values=>[\"MISSING\"])\n\n    assert(a.type==:date)\n    expected=[Date.new(2009,10,10), Date.today(), Date.new(2009,10,10), Date.new(2009,1,1), nil, Date.today(), nil ]\n    assert_equal(expected, a.date_data_with_nils)\n  end\nend\n"
  },
  {
    "path": "test/test_wilcoxonsignedrank.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\n\nclass StatsampleUMannWhitneyTestCase < MiniTest::Unit::TestCase\n  include Statsample::Test\n  context Statsample::Test::WilcoxonSignedRank do\n\tcontext \"Example 1\" do\n\t\tsetup do\n\t\t  @v1=[110,122,125,120,140,124,123,137,135,145].to_scale\n\t\t  @v2=[125,115,130,140,140,115,140,125,140,135].to_scale\n\t\t  @u=Statsample::Test::WilcoxonSignedRank.new(@v1,@v2)\n\t\tend\n\t\tshould \"have same result using class or Test#u_mannwhitney\" do \n\t\t  assert_equal(Statsample::Test.wilcoxon_signed_rank(@v1,@v2).w, @u.w) \n\t\tend\n\t\tshould \"have correct W values\" do\n\t\t  assert_equal(9,@u.w)\n\t\tend\n\t\tshould \"have correct nr values\" do\n\t\t\tassert_equal(9,@u.nr)\n\t\tend\n\t\tshould \"have correct value for z\" do\n\t\t  assert_in_delta(0.503,@u.z,0.001)\n\t\tend\n\t\tshould \"have correct value for probability_z\" do\n\t\t  assert_in_delta(0.614,@u.probability_z,0.001)\n\t\tend\n\t\tshould \"have correct value for probability_exact\" do\n\t\t  assert_in_delta(0.652,@u.probability_exact,0.001)\n\t\tend    \n\t\tshould \"have summary\" do\n\t\t  assert(@u.summary!=\"\")\n\t\tend \n\t  end\n\t  \n\t  context \"Example 2\" do\n\t\tsetup do\n\t\t  @v2=[78,24,64,45,64,52,30,50,64,50,78,22,84,40,90,72].to_scale\n\t\t  @v1=[78,24,62,48,68,56,25,44,56,40,68,36,68,20,58,32].to_scale\n\t\t  @u=Statsample::Test::WilcoxonSignedRank.new(@v1,@v2)\n\t\tend\n\t\tshould \"have same result using class or Test#u_mannwhitney\" do \n\t\t  assert_equal(Statsample::Test.wilcoxon_signed_rank(@v1,@v2).w, @u.w) \n\t\tend\n\t\tshould \"have correct W values\" do\n\t\t  assert_equal(67,@u.w)\n\t\tend\n\t\tshould \"have correct nr values\" do\n\t\t\tassert_equal(14,@u.nr)\n\t\tend\n\t\tshould \"have correct value for z\" do\n\t\t  assert_in_delta(2.087,@u.z,0.001)\n\t\tend\n\t\tshould \"have correct value for probability_z\" do\n\t\t  assert_in_delta(0.036,@u.probability_z,0.001)\n\t\tend\n\t\tshould \"have correct value for probability_exact\" do\n\t\t  assert_in_delta(0.036,@u.probability_exact,0.001)\n\t\tend    \n\t\tshould \"have summary\" do\n\t\t  assert(@u.summary!=\"\")\n\t\tend \n\t  end\n\t\n\t\n\tend\n\t  \nend\n"
  },
  {
    "path": "test/test_xls.rb",
    "content": "require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))\nclass StatsampleExcelTestCase < MiniTest::Unit::TestCase\n  context \"Excel reader\" do\n    setup do \n      @ds=Statsample::Excel.read(File.dirname(__FILE__)+\"/fixtures/test_xls.xls\")\n    end\n    should \"set the number of cases\" do\n      assert_equal(6,@ds.cases)\n    end\n    should \"set correct field names\" do \n      assert_equal(%w{id name age city a1},@ds.fields)\n    end\n    should \"set a dataset equal to expected\" do \n      id=[1,2,3,4,5,6].to_vector(:scale)\n      name=[\"Alex\",\"Claude\",\"Peter\",\"Franz\",\"George\",\"Fernand\"].to_vector(:nominal)\n      age=[20,23,25,nil,5.5,nil].to_vector(:scale)\n      city=[\"New York\",\"London\",\"London\",\"Paris\",\"Tome\",nil].to_vector(:nominal)\n      a1=[\"a,b\",\"b,c\",\"a\",nil,\"a,b,c\",nil].to_vector(:nominal)\n      ds_exp=Statsample::Dataset.new({'id'=>id,'name'=>name,'age'=>age,'city'=>city,'a1'=>a1}, %w{id name age city a1})\n      ds_exp.fields.each{|f|\n        assert_equal(ds_exp[f],@ds[f])\n      }\n      assert_equal(ds_exp,@ds)\n    end\n    should \"set to nil empty cells\" do \n      assert_equal(nil,@ds['age'][5])\n    end\n  end\n  context \"Excel writer\" do\n    setup do \n      a=100.times.map{rand(100)}.to_scale\n      b=([\"b\"]*100).to_vector\n      @ds={'b'=>b, 'a'=>a}.to_dataset(%w{b a})\n      tempfile=Tempfile.new(\"test_write.xls\")\n      Statsample::Excel.write(@ds,tempfile.path)\n      @ds2=Statsample::Excel.read(tempfile.path)\n    end\n    should \"return same fields as original\" do\n      assert_equal(@ds.fields ,@ds2.fields)\n    end\n    should \"return same number of cases as original\" do\n      assert_equal(@ds.cases, @ds2.cases)\n    end\n    should \"return same cases as original\" do\n      i=0\n      @ds2.each_array do |row|\n        assert_equal(@ds.case_as_array(i),row)\n        i+=1\n      end    \n    end\n  end\nend\n"
  },
  {
    "path": "web/Rakefile",
    "content": "# -*- ruby -*-\nrequire 'rake'\nrequire 'fileutils'\ndirectory \"examples\"\n\ndef get_base(f)\n  f.sub(File.dirname(__FILE__)+\"/../examples/\",\"\").gsub(\"/\",\"_\").gsub(\".rb\",\"\")\nend\n\n\nEXAMPLES=Dir.glob(File.dirname(__FILE__)+\"/../examples/**/*.rb\").map {|v|     [v, get_base(v)]\n}.find_all{|v| !v[0].include?\"_data\"}\n\nEXAMPLES_BASE=EXAMPLES.map {|v| v[1]}\n\n\ndesc \"Build all html, rtf and pdf files\"\ntask :build_site do\n  ruby \"build_site.rb\"\nend\n\n\ntask :clean do\n  Dir.glob(File.dirname(__FILE__)+\"/examples/*.pdf\").each do |t|\n    FileUtils.rm t\n  end\n  Dir.glob(File.dirname(__FILE__)+\"/examples/*.html\").each do |t|\n    FileUtils.rm t\n  end\n  Dir.glob(File.dirname(__FILE__)+\"/examples/*.rtf\").each do |t|\n    FileUtils.rm t\n  end\n  Dir.glob(File.dirname(__FILE__)+\"/examples/images/*.*\").each do |t|\n    FileUtils.rm t\n  end\nend\n\n\nload 'upload_task.rb' if File.exists? \"upload_task.rb\"\n"
  }
]