lib/statsample/reliability/skillscaleanalysis.rb
module Statsample
module Reliability
# Analysis of a Skill Scale
# Given a dataset with results and a correct answers hash,
# generates a ScaleAnalysis
# == Usage
# x1 = Daru::Vector.new(%{a b b c})
# x2 = Daru::Vector.new(%{b a b c})
# x3 = Daru::Vector.new(%{a c b a})
# ds = Daru::DataFrame.new({:x1 => @x1, :x2 => @x2, :x3 => @x3})
# key={ :x1 => 'a',:x2 => 'b', :x3 => 'a'}
# ssa=Statsample::Reliability::SkillScaleAnalysis.new(ds,key)
# puts ssa.summary
class SkillScaleAnalysis
include Summarizable
attr_accessor :name
attr_accessor :summary_minimal_item_correlation
attr_accessor :summary_show_problematic_items
def initialize(ds,key,opts=Hash.new)
opts_default={
:name=>_("Skill Scale Reliability Analysis (%s)") % ds.name,
:summary_minimal_item_correlation=>0.10,
:summary_show_problematic_items=>true
}
@ds=ds
@key=key
@opts=opts_default.merge(opts)
@opts.each{|k,v| self.send("#{k}=",v) if self.respond_to? k }
@cds=nil
end
# Dataset only corrected vectors
def corrected_dataset_minimal
cds = corrected_dataset
dsm = Daru::DataFrame.new(
@key.keys.inject({}) do |ac,v|
ac[v] = cds[v]
ac
end
)
dsm.rename _("Corrected dataset from %s") % @ds.name
dsm
end
def vector_sum
corrected_dataset_minimal.vector_sum
end
def vector_mean
corrected_dataset_minimal.vector_mean
end
def scale_analysis
sa = ScaleAnalysis.new(corrected_dataset_minimal)
sa.name=_("%s (Scale Analysis)") % @name
sa
end
def corrected_dataset
if @cds.nil?
@cds = Daru::DataFrame.new({}, order: @ds.vectors, name: @ds.name)
@ds.each_row do |row|
out = {}
row.each_with_index do |v, k|
if @key.has_key? k
if @ds[k].reject_values(*Daru::MISSING_VALUES).include_values? v
out[k]= @key[k] == v ? 1 : 0
else
out[k] = nil
end
else
out[k] = v
end
end
@cds.add_row(Daru::Vector.new(out))
end
@cds.update
end
@cds
end
def report_building(builder)
builder.section(:name=>@name) do |s|
sa = scale_analysis
s.parse_element(sa)
if summary_show_problematic_items
s.section(:name=>_("Problematic Items")) do |spi|
count=0
sa.item_total_correlation.each do |k,v|
if v < summary_minimal_item_correlation
count+=1
spi.section(:name=>_("Item: %s") % @ds[k].name) do |spii|
spii.text _("Correct answer: %s") % @key[k]
spii.text _("p: %0.3f") % corrected_dataset[k].mean
props=@ds[k].proportions.inject({}) {|ac,v| ac[v[0]] = v[1].to_f;ac}
spi.table(:name=>"Proportions",:header=>[_("Value"), _("%")]) do |table|
props.each do |k1,v|
table.row [ @ds[k].index_of(k1), "%0.3f" % v]
end
end
end
end
end
spi.text _("No problematic items") if count==0
end
end
end
end
end
end
end