module Statsample
module Reliability
class << self
# Calculate Chonbach's alpha for a given dataset.
# only uses tuples without missing data
def cronbach_alpha(ods)
ds=ods.dup_only_valid
n_items=ds.fields.size
s2_items=ds.vectors.inject(0) {|ac,v|
ac+v[1].variance }
total=ds.vector_sum
(n_items.quo(n_items-1)) * (1-(s2_items.quo(total.variance)))
end
# Calculate Chonbach's alpha for a given dataset
# using standarized values for every vector.
# Only uses tuples without missing data
def cronbach_alpha_standarized(ods)
ds=ods.dup_only_valid.fields.inject({}){|a,f|
a[f]=ods[f].standarized; a
}.to_dataset
cronbach_alpha(ds)
end
def cronbach_alpha_from_n_s2_cov(n,s2,cov)
(n.quo(n-1)) * (1-(s2.quo(s2+(n-1)*cov)))
end
# Returns n necessary to obtain specific alpha
# given variance and covariance mean of items
def n_for_desired_alpha(alpha,s2,cov)
# Start with a regular test : 50 items
min=2
max=1000
n=50
prev_n=0
epsilon=0.0001
dif=1000
c_a=cronbach_alpha_from_n_s2_cov(n,s2,cov)
dif=c_a - alpha
while(dif.abs>epsilon and n!=prev_n)
prev_n=n
if dif<0
min=n
n=(n+(max-min).quo(2)).to_i
else
max=n
n=(n-(max-min).quo(2)).to_i
end
c_a=cronbach_alpha_from_n_s2_cov(n,s2,cov)
dif=c_a - alpha
#puts "#{n} , #{c_a}"
end
n
end
# First derivative for alfa
# Parameters
# n: Number of items
# sx: mean of variances
# sxy: mean of covariances
def alpha_first_derivative(n,sx,sxy)
(sxy*(sx-sxy)).quo(((sxy*(n-1))+sx)**2)
end
# Second derivative for alfa
# Parameters
# n: Number of items
# sx: mean of variances
# sxy: mean of covariances
def alfa_second_derivative(n,sx,sxy)
(2*(sxy**2)*(sxy-sx)).quo(((sxy*(n-1))+sx)**3)
end
end
class ItemCharacteristicCurve
attr_reader :totals, :counts, :vector_total
def initialize (ds, vector_total=nil)
vector_total||=ds.vector_sum
raise ArgumentError, "Total size != Dataset size" if vector_total.size!=ds.cases
@vector_total=vector_total
@ds=ds
@totals={}
@counts=@ds.fields.inject({}) {|a,v| a[v]={};a}
process
end
def process
i=0
@ds.each do |row|
tot=@vector_total[i]
@totals[tot]||=0
@totals[tot]+=1
@ds.fields.each do |f|
item=row[f].to_s
@counts[f][tot]||={}
@counts[f][tot][item]||=0
@counts[f][tot][item] += 1
end
i+=1
end
end
# Return a hash with p for each different value on a vector
def curve_field(field, item)
out={}
item=item.to_s
@totals.each do |value,n|
count_value= @counts[field][value][item].nil? ? 0 : @counts[field][value][item]
out[value]=count_value.quo(n)
end
out
end # def
end # self
end # Reliability
end # Statsample
require 'statsample/reliability/scaleanalysis.rb'
require 'statsample/reliability/multiscaleanalysis.rb'