module Statsample # Class to create crosstab of data # With this, you can create reports and do chi square test # The first vector will be at rows and the second will the the columns # class Crosstab include GetText bindtextdomain("statsample") attr_reader :v_rows, :v_cols attr_accessor :row_label, :column_label, :name, :percentage_row, :percentage_column, :percentage_total def initialize(v1, v2, opts=Hash.new) raise ArgumentError, "Both arguments should be Vectors" unless v1.is_a? Statsample::Vector and v2.is_a? Statsample::Vector raise ArgumentError, "Vectors should be the same size" unless v1.size==v2.size @v_rows, @v_cols=Statsample.only_valid(v1,v2) @cases=@v_rows.size @row_label=nil @column_label=nil @name=nil @percentage_row=@percentage_column=@percentage_total=false opts.each{|k,v| self.send("#{k}=",v) if self.respond_to? k } if(@name.nil?) if (!@row_label.nil? and !@column_label.nil?) @name=_("Crosstab %s - %s") % [@row_label, @column_label] else @name=_("Crosstab") end end end def rows_names @v_rows.factors.sort end def cols_names @v_cols.factors.sort end def rows_total @v_rows.frequencies end def cols_total @v_cols.frequencies end def frequencies base=rows_names.inject([]){|s,row| s+=cols_names.collect{|col| [row,col]} }.inject({}) {|s,par| s[par]=0 s } base.update(Statsample::vector_cols_matrix(@v_rows,@v_cols).to_a.to_vector.frequencies) end def to_matrix f=frequencies rn=rows_names cn=cols_names Matrix.rows(rn.collect{|row| cn.collect{|col| f[[row,col]]} }) end def frequencies_by_row f=frequencies rows_names.inject({}){|sr,row| sr[row]=cols_names.inject({}) {|sc,col| sc[col]=f[[row,col]]; sc} sr } end def frequencies_by_col f=frequencies cols_names.inject({}){|sc,col| sc[col]=rows_names.inject({}) {|sr,row| sr[row]=f[[row,col]]; sr} sc } end # Chi square, based on expected and real matrix def chi_square require 'statsample/test' Statsample::Test.chi_square(self.to_matrix, matrix_expected) end # Useful to obtain chi square def matrix_expected rn=rows_names cn=cols_names rt=rows_total ct=cols_total t=@v_rows.size m=rn.collect{|row| cn.collect{|col| (rt[row]*ct[col]).quo(t) } } Matrix.rows(m) end def cols_empty_hash cols_names.inject({}) {|a,x| a[x]=0;a} end def to_reportbuilder(generator) anchor=generator.add_toc_entry(_("Crosstab: ")+name) generator.add_html "