# class Statsample::Factor::Rotation

Base class for component matrix rotation.

## Reference:¶ ↑

Use subclasses Varimax, Equimax or Quartimax for desired type of rotation

```Use:
a = Matrix[ [ 0.4320,  0.8129,  0.3872]
, [ 0.7950, -0.5416,  0.2565]
, [ 0.5944,  0.7234, -0.3441]
, [ 0.8945, -0.3921, -0.1863] ]
rotation = Statsample::Factor::Varimax(a)
rotation.iterate
p rotation.rotated
p rotation.component_transformation_matrix```

Base class for component matrix rotation.

## Reference:¶ ↑

Use subclasses Varimax, Equimax or Quartimax for desired type of rotation

```Use:
a = Matrix[ [ 0.4320,  0.8129,  0.3872]
, [ 0.7950, -0.5416,  0.2565]
, [ 0.5944,  0.7234, -0.3441]
, [ 0.8945, -0.3921, -0.1863] ]
rotation = Statsample::Factor::Varimax(a)
rotation.iterate
p rotation.rotated
p rotation.component_transformation_matrix```

EPSILON
MAX_ITERATIONS

### Attributes

communalities[R]
component_transformation_matrix[R]
epsilon[RW]

Maximum precision

h2[R]
iterations[R]
max_iterations[RW]

Maximum number of iterations

rotated[R]
rotated_component_matrix[R]
use_gsl[RW]

### Public Class Methods

new(matrix, opts=Hash.new) click to toggle source
```# File lib/statsample/factor/rotation.rb, line 34
def initialize(matrix, opts=Hash.new)
@name=_("%s rotation") % rotation_name
@matrix=matrix
@n=@matrix.row_size # Variables, p on original
@m=@matrix.column_size # Factors, r on original
@component_transformation_matrix=nil
@max_iterations=MAX_ITERATIONS
@epsilon=EPSILON
@rotated=nil
@h2=(@matrix.collect {|c| c**2} * Matrix.column_vector([1]*@m)).column(0).to_a
@use_gsl=Statsample.has_gsl?
opts.each{|k,v|
self.send("#{k}=",v) if self.respond_to? k
}
end```

### Public Instance Methods

compute() click to toggle source
```# File lib/statsample/factor/rotation.rb, line 57
def compute
iterate
end```
iterate() click to toggle source

Start iteration

```# File lib/statsample/factor/rotation.rb, line 61
def iterate
k_matrix=@use_gsl ? GSL::Matrix : ::Matrix
t=k_matrix.identity(@m)
b=(@use_gsl ? @matrix.to_gsl : @matrix.dup)
h=k_matrix.diagonal(*@h2).collect {|c| Math::sqrt(c)}
h_inverse=h.collect {|c| c!=0 ? 1/c : 0 }
bh=h_inverse * b
@not_converged=true
@iterations=0
while @not_converged
break if @iterations>@max_iterations
@iterations+=1
#puts "Iteration #{iterations}"
num_pairs=@m*(@m-1).quo(2)
(0..(@m-2)).each do |i| #+ go through factor index 0:r-1-1 (begin)
((i+1)..(@m-1)).each do |j| #+ pair i to "rest" of factors (begin)

xx = bh.column(i)
yy = bh.column(j)
tx = t.column(i)
ty = t.column(j)

uu = @n.times.collect {|var_i| xx[var_i]**2-yy[var_i]**2}
vv = @n.times.collect {|var_i| 2*xx[var_i]*yy[var_i]}

a  = @n.times.inject(0) {|ac,var_i| ac+ uu[var_i] }
b  = @n.times.inject(0) {|ac,var_i| ac+ vv[var_i] }
c  = @n.times.inject(0) {|ac,var_i| ac+ (uu[var_i]**2 - vv[var_i]**2) }
d  = @n.times.inject(0) {|ac,var_i| ac+ (2*uu[var_i]*vv[var_i]) }
num=x(a,b,c,d)
den=y(a,b,c,d)
phi=Math::atan2(num,den) / 4.0
# puts "#{i}-#{j}: #{phi}"

if(Math::sin(phi.abs) >= @epsilon)
xx_rot=( Math::cos(phi)*xx)+(Math::sin(phi)*yy)
yy_rot=((-Math::sin(phi))*xx)+(Math::cos(phi)*yy)

tx_rot=( Math::cos(phi)*tx)+(Math::sin(phi)*ty)
ty_rot=((-Math::sin(phi))*tx)+(Math::cos(phi)*ty)

bh=bh.to_a

@n.times {|row_i|
bh[row_i][i] = xx_rot[row_i]
bh[row_i][j] = yy_rot[row_i]
}
t=t.to_a
@m.times {|row_i|
t[row_i][i]=tx_rot[row_i]
t[row_i][j]=ty_rot[row_i]
}
#if @use_gsl
bh=k_matrix.[](*bh)
t=k_matrix.[](*t)
#else
#  bh=Matrix.rows(bh)
#  t=Matrix.rows(t)

#end
else
num_pairs=num_pairs-1
@not_converged=false if num_pairs==0
end # if
end #j
end #i
end # while
@rotated=h*bh
@rotated.extend CovariateMatrix
@rotated.name=_("Rotated Component matrix")

if @matrix.respond_to? :fields_x
@rotated.fields_x = @matrix.fields_x
else
@rotated.fields_x = @n.times.map {|i| "var_#{i+1}"}
end
if @matrix.respond_to? :fields_y
@rotated.fields_y = @matrix.fields_y
else
@rotated.fields_y = @m.times.map {|i| "var_#{i+1}"}
end

@component_transformation_matrix=t
@component_transformation_matrix.extend CovariateMatrix
@component_transformation_matrix.name=_("Component transformation matrix")

if @matrix.respond_to? :fields_y
@component_transformation_matrix.fields = @matrix.fields_y

else
@component_transformation_matrix.fields = @m.times.map {|i| "var_#{i+1}"}
end

@rotated
end```
report_building(g) click to toggle source
```# File lib/statsample/factor/rotation.rb, line 49
def report_building(g)
g.section(:name=>@name) do |s|
s.parse_element(rotated)
s.parse_element(component_transformation_matrix)
end
end```