spec/vector_spec.rb in daru-0.0.5 vs spec/vector_spec.rb in daru-0.1.0

- old
+ new

@@ -1,12 +1,16 @@ require 'spec_helper.rb' describe Daru::Vector do - ALL_DTYPES = [:array, :nmatrix] - ALL_DTYPES.each do |dtype| - describe dtype do + describe dtype.to_s do + before do + @common_all_dtypes = Daru::Vector.new( + [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99], + dtype: dtype, name: :common_all_dtypes) + end + context "#initialize" do before do @tuples = [ [:a, :one, :foo], [:a, :two, :bar], @@ -62,21 +66,55 @@ expect(dv.index).to eq(Daru::Index.new [0,1,2,3,4]) end it "inserts nils for extra indices" do - dv = Daru::Vector.new [1,2,3], name: :yoga, index: [0,1,2,3,4], dtype: :array + dv = Daru::Vector.new [1,2,3], name: :yoga, index: [0,1,2,3,4], dtype: dtype - expect(dv).to eq([1,2,3,nil,nil].dv(:yoga,nil, Array)) + expect(dv).to eq([1,2,3,nil,nil].dv(:yoga,nil, :array)) end it "inserts nils for extra indices (MultiIndex)" do dv = Daru::Vector.new [1,2], name: :mi, index: @multi_index, dtype: :array expect(dv).to eq(Daru::Vector.new([1,2,nil,nil], name: :mi, index: @multi_index, dtype: :array)) end end + context ".new_with_size" do + it "creates new vector from only size" do + v1 = Daru::Vector.new 10.times.map { nil }, dtype: dtype + v2 = Daru::Vector.new_with_size 10, dtype: dtype + expect(v2).to eq(v1) + end if [:array, :nmatrix].include?(dtype) + + it "creates new vector from only size and value" do + a = rand + v1 = Daru::Vector.new 10.times.map { a }, dtype: dtype + v2 = Daru::Vector.new_with_size(10, value: a, dtype: dtype) + expect(v2).to eq(v1) + end + + it "accepts block" do + v1 = Daru::Vector.new 10.times.map {|i| i * 2 } + v2 = Daru::Vector.new_with_size(10, dtype: dtype) { |i| i * 2 } + expect(v2).to eq(v1) + end + end + + context ".[]" do + it "returns same results as R-c()" do + reference = Daru::Vector.new([0, 4, 5, 6, 10]) + expect(Daru::Vector[0, 4, 5, 6, 10]) .to eq(reference) + expect(Daru::Vector[0, 4..6, 10]) .to eq(reference) + expect(Daru::Vector[[0], [4, 5, 6], [10]]) .to eq(reference) + expect(Daru::Vector[[0], [4, [5, [6]]], [10]]).to eq(reference) + + expect(Daru::Vector[[0], Daru::Vector.new([4, 5, 6]), [10]]) + .to eq(reference) + end + end + context "#[]" do context Daru::Index do before :each do @dv = Daru::Vector.new [1,2,3,4,5], name: :yoga, index: [:yoda, :anakin, :obi, :padme, :r2d2], dtype: dtype @@ -105,11 +143,11 @@ index: [:yoda, :anakin], name: :yoga, dtype: dtype)) end it "returns a vector when specified numeric Range" do expect(@dv[3..4]).to eq(Daru::Vector.new([4,5], name: :yoga, - index: [:padme, :r2d2], name: :yoga, dtype: dtype)) + index: [:padme, :r2d2], dtype: dtype)) end end context Daru::MultiIndex do before do @@ -300,26 +338,37 @@ it "deletes element of specified index" do @dv.delete_at :one expect(@dv).to eq(Daru::Vector.new [2,3,4,5], name: :a, - index: [:two, :three, :four, :five]), dtype: dtype + index: [:two, :three, :four, :five], dtype: dtype) end it "deletes element of specified integer index" do @dv.delete_at 2 expect(@dv).to eq(Daru::Vector.new [1,2,4,5], name: :a, - index: [:one, :two, :four, :five]), dtype: dtype + index: [:one, :two, :four, :five], dtype: dtype) end end context Daru::MultiIndex do pending "Possibly next release" end end + context "#delete_if" do + it "deletes elements if block evaluates to true" do + v = Daru::Vector.new [1,22,33,45,65,32,524,656,123,99,77], dtype: dtype + ret = v.delete_if { |d| d % 11 != 0 } + expect(ret).to eq( + Daru::Vector.new([1,45,65,32,524,656,123], + index: [0,3,4,5,6,7,8], dtype: dtype)) + expect(ret.dtype).to eq(dtype) + end + end + context "#index_of" do context Daru::Index do it "returns index of specified value" do dv = Daru::Vector.new [1,2,3,4,5], name: :a, index: [:one, :two, :three, :four, :five], dtype: dtype @@ -492,14 +541,164 @@ context Daru::MultiIndex do pending end end + + context "#collect" do + it "returns an Array" do + a = @common_all_dtypes.collect { |v| v } + expect(a).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99]) + end + end + + context "#map" do + it "maps" do + a = @common_all_dtypes.map { |v| v } + expect(a).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99]) + end + end + + context "#map!" do + it "destructively maps" do + @common_all_dtypes.map! { |v| v + 1 } + expect(@common_all_dtypes).to eq(Daru::Vector.new( + [6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 2, 3, 4, 5, 12, -98, -98], + dtype: dtype)) + end + end + + context "#recode" do + it "maps and returns a vector of dtype of self by default" do + a = @common_all_dtypes.recode { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] + expect(a).to eq(exp) + expect(a.dtype).to eq(:array) + end + + it "maps and returns a vector of dtype gsl" do + a = @common_all_dtypes.recode(:gsl) { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], dtype: :gsl + expect(a).to eq(exp) + expect(a.dtype).to eq(:gsl) + end + + it "maps and returns a vector of dtype nmatrix" do + a = @common_all_dtypes.recode(:nmatrix) { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], dtype: :nmatrix + expect(a).to eq(exp) + expect(a.dtype).to eq(:nmatrix) + end + end + + context "#recode!" do + before :each do + @vector = Daru::Vector.new( + [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99], + dtype: dtype, name: :common_all_dtypes) + end + + it "destructively maps and returns a vector of dtype of self by default" do + @vector.recode! { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] + expect(@vector).to eq(exp) + expect(@vector.dtype).to eq(dtype) + end + + it "destructively maps and returns a vector of dtype gsl" do + @vector.recode!(:gsl) { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], dtype: :gsl + expect(@vector).to eq(exp) + expect(@vector.dtype).to eq(exp.dtype) + end + + it "destructively maps and returns a vector of dtype nmatrix" do + @vector.recode!(:nmatrix) { |v| v == -99 ? 1 : 0 } + exp = Daru::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], dtype: :nmatrix + expect(@vector).to eq(exp) + expect(@vector.dtype).to eq(exp.dtype) + end + end + + context "#verify" do + it "returns a hash of invalid data and index of data" do + v = Daru::Vector.new [1,2,3,4,5,6,-99,35,-100], dtype: dtype + h = v.verify { |d| d > 0 } + e = { 6 => -99, 8 => -100 } + expect(h).to eq(e) + end + end + + context "#summary" do + it "has name in the summary" do + expect(@common_all_dtypes.summary.match("#{@common_all_dtypes.name}")).to_not eq(nil) + end + end + + context "#bootstrap" do + it "returns a vector with mean=mu and sd=se" do + rng = Distribution::Normal.rng(0, 1) + vector =Daru::Vector.new_with_size(100, dtype: dtype) { rng.call} + + df = vector.bootstrap([:mean, :sd], 200) + se = 1 / Math.sqrt(vector.size) + expect(df[:mean].mean).to be_within(0.3).of(0) + expect(df[:mean].sd).to be_within(0.02).of(se) + end + end end - end # checking with ALL_DTYPES + end # describe ALL_DTYPES.each + # ----------------------------------------------------------------------- # works with arrays only + + context "#splitted" do + it "splits correctly" do + a = Daru::Vector.new ['a', 'a,b', 'c,d', 'a,d', 'd', 10, nil] + expect(a.splitted).to eq([%w(a), %w(a b), %w(c d), %w(a d), %w(d), [10], nil]) + end + end + + context "#missing_values" do + before do + @common = Daru::Vector.new([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99]) + end + + it "allows setting the value to be treated as missing" do + @common.missing_values = [10] + expect(@common.only_valid.to_a.sort).to eq( + [-99, -99, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 7, 8, 9] + ) + expect(@common.to_a).to eq( + [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99] + ) + + @common.missing_values = [-99] + expect(@common.only_valid.to_a.sort).to eq( + [1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10] + ) + expect(@common.to_a).to eq( + [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99] + ) + + @common.missing_values = [] + expect(@common.only_valid.to_a.sort).to eq( + [-99, -99, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10] + ) + expect(@common.to_a).to eq( + [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99] + ) + end + + it "responds to has_missing_data? with explicit missing_values" do + a = Daru::Vector.new [1,2,3,4,10] + a.missing_values = [10] + + expect(a.has_missing_data?).to eq(true) + end + end + context "#is_nil?" do before(:each) do @with_md = Daru::Vector.new([1,2,nil,3,4,nil]) @without_md = Daru::Vector.new([1,2,3,4,5,6]) end @@ -521,23 +720,23 @@ context Daru::MultiIndex do pending end end - context "#nil_positions" do + context "#missing_positions" do context Daru::Index do before(:each) do @with_md = Daru::Vector.new([1,2,nil,3,4,nil]) end it "returns the indexes of nils" do - expect(@with_md.nil_positions).to eq([2,5]) + expect(@with_md.missing_positions).to eq([2,5]) end it "updates after assingment" do @with_md[3] = nil - expect(@with_md.nil_positions).to eq([2,3,5]) + expect(@with_md.missing_positions).to eq([2,3,5]) end end context Daru::MultiIndex do pending @@ -613,8 +812,165 @@ expect(@vector.to_matrix).to eq(Matrix[[1,2,3,4,5,6]]) end it "converts Daru::Vector to a vertical Ruby Matrix" do expect(@vector.to_matrix(:vertical)).to eq(Matrix.columns([[1,2,3,4,5,6]])) + end + end + + context "#only_valid" do + it "returns a Vector of only non-nil data" do + vector = Daru::Vector.new [1,2,3,4,nil,3,nil], + index: [:a, :b, :c, :d, :e, :f, :g] + expect(vector.only_valid).to eq(Daru::Vector.new([1,2,3,4,3], + index: [:a, :b, :c, :d, :f])) + end + end + + context "#only_numerics" do + it "returns only numerical or missing data" do + v = Daru::Vector.new([1,2,nil,3,4,'s','a',nil]) + expect(v.only_numerics).to eq(Daru::Vector.new([1,2,nil,3,4,nil], + index: [0,1,2,3,4,7])) + end + end + + context "#to_gsl" do + it "returns a GSL::Vector of non-nil data" do + vector = Daru::Vector.new [1,2,3,4,nil,6,nil] + expect(vector.to_gsl).to eq(GSL::Vector.alloc(1,2,3,4,6)) + + gsl_vec = Daru::Vector.new [1,2,3,4,5], dtype: :gsl + expect(gsl_vec.to_gsl).to eq(GSL::Vector.alloc(1,2,3,4,5)) + end + end + + context "#split_by_separator" do + def expect_correct_tokens hash + expect(hash['a'].to_a).to eq([1, 1, 0, 1, 0, nil]) + expect(hash['b'].to_a).to eq([0, 1, 0, 0, 0, nil]) + expect(hash['c'].to_a).to eq([0, 0, 1, 0, 0, nil]) + expect(hash['d'].to_a).to eq([0, 0, 1, 1, 0, nil]) + expect(hash[10].to_a).to eq([0, 0, 0, 0, 1, nil]) + end + + before do + @a = Daru::Vector.new ['a', 'a,b', 'c,d', 'a,d', 10, nil] + @b = @a.split_by_separator(',') + end + + it "returns a Hash" do + expect(@b.class).to eq(Hash) + end + + it "returned Hash has keys with with different values of @a" do + expect(@b.keys).to eq(['a', 'b', 'c', 'd', 10]) + end + + it "returns a Hash, whose values are Daru::Vector" do + @b.each_key do |key| + expect(@b[key].class).to eq(Daru::Vector) + end + end + + it "ensures that hash values are n times the tokens appears" do + expect_correct_tokens @b + end + + it "gives the same values using a different separator" do + a = Daru::Vector.new ['a', 'a*b', 'c*d', 'a*d', 10, nil] + b = a.split_by_separator '*' + expect_correct_tokens b + end + end + + context "#split_by_separator_freq" do + it "returns the number of ocurrences of tokens" do + a = Daru::Vector.new ['a', 'a,b', 'c,d', 'a,d', 10, nil] + expect(a.split_by_separator_freq).to eq( + { 'a' => 3, 'b' => 1, 'c' => 1, 'd' => 2, 10 => 1 }) + end + end + + context "#n_valid" do + it "returns number of non-missing positions" do + v = Daru::Vector.new [1,2,3,4,nil,nil,3,5] + expect(v.n_valid).to eq(6) + end + end + + context "#reset_index!" do + it "resets any index to a numerical serialized index" do + v = Daru::Vector.new([1,2,3,4,5,nil,nil,4,nil]) + r = v.only_valid.reset_index! + expect(r).to eq(Daru::Vector.new([1,2,3,4,5,4])) + expect(r.index).to eq(Daru::Index.new([0,1,2,3,4,5])) + + indexed = Daru::Vector.new([1,2,3,4,5], index: [:a, :b, :c, :d, :e]) + expect(indexed.reset_index!.index).to eq(Daru::Index.new([0,1,2,3,4])) + end + end + + context "#rename" do + before :each do + @v = Daru::Vector.new [1,2,3,4,5,5], name: :this_vector + end + + it "assings name" do + @v.rename :that_vector + expect(@v.name).to eq(:that_vector) + end + + it "stores name as a symbol" do + @v.rename "This is a vector" + expect(@v.name).to eq(:"This is a vector") + end + end + + context "#any?" do + before do + @v = Daru::Vector.new([1,2,3,4,5]) + end + + it "returns true if block returns true for any one of the elements" do + expect(@v.any?{ |e| e == 1 }).to eq(true) + end + + it "returns false if block is false for all elements" do + expect(@v.any?{ |e| e > 10 }).to eq(false) + end + end + + context "#all?" do + before do + @v = Daru::Vector.new([1,2,3,4,5]) + end + + it "returns true if block is true for all elements" do + expect(@v.all? { |e| e < 6 }).to eq(true) + end + + it "returns false if block is false for any one element" do + expect(@v.all? { |e| e == 2 }).to eq(false) + end + end + + context "#only_missing" do + it "returns a vector (with proper index) of all the elements marked 'missing'" do + v = Daru::Vector.new([1,2,3,4,5,6,4,5,5,4,4,nil,nil,nil]) + v.missing_values = [nil, 5] + + expect(v.only_missing).to eq(Daru::Vector.new([5,5,5,nil,nil,nil], + index: [4,7,8,11,12,13])) + end + end + + context "#detach_index" do + it "creates a DataFrame with first Vector as index and second as values of the Vector" do + v = Daru::Vector.new([1,2,3,4,5,6], index: [:a, :b, :c, :d, :e, :f], name: :values) + expect(v.detach_index).to eq(Daru::DataFrame.new({ + index: ['a', 'b', 'c', 'd', 'e', 'f'], + vector: [1,2,3,4,5,6] + })) end end end if mri?