1%# -*- mode: Octave -*- 2 3%% Copyright (C) 2009-2017 Pascal Dupuis <cdemills@gmail.com> 4 %% 5 %% This file is part of the dataframe package for Octave. 6 %% 7 %% This package is free software; you can redistribute it and/or 8 %% modify it under the terms of the GNU General Public 9 %% License as published by the Free Software Foundation; 10 %% either version 3, or (at your option) any later version. 11 %% 12 %% This package is distributed in the hope that it will be useful, 13 %% but WITHOUT ANY WARRANTY; without even the implied 14 %% warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 %% PURPOSE. See the GNU General Public License for more 16 %% details. 17 %% 18 %% You should have received a copy of the GNU General Public 19 %% License along with this package; see the file COPYING. If not, 20 %% see <http://www.gnu.org/licenses/>. 21 22%# this file is mostly identical to 'dataframe', except that fragments 23%# can be easily extracted and run in interactive mode. 24 25x = dataframe(randn(3, 3), 'rownames', (7:-1:5).'); 26x(1:3, 1) = 3; 27x(1:3, 1) = (4:6).'; 28assert(x.array(2, 1), 5) 29x(1, 1:3) = 3; 30x(1, 1:3) = (4:6).'; 31assert(x.array(1, 2), 5) 32assert(isempty(x.rowidx), false) 33x.types(2) ='single'; 34assert(class(x.array(1, 2)), 'single') 35x=dataframe('data_test.csv'); 36assert(isna(x.array(9, 4))) 37# remove rownames 38x.rownames = []; 39assert(size(x.rownames), [0 0]) 40# remove a column through '.' access 41y = x; y.DataName = []; 42if (strcmp (genvarname ('_A'), 'x_A')) 43 assert(size(y(:, 'x_IBIAS_')), [10 1]) 44else 45 assert(size(y(:, '_IBIAS_')), [10 1]) 46end 47assert(size(y), [10 6]) 48y = repmat([false true], 10, 1); 49y(4) = true; 50z = x(:, ["VBIAS"; "Freq"])==[-5.4 300e3]; 51assert(z.array(:, :), y) 52assert(find(all(z, 2)), 4) 53assert(sum(x(:, 'VBIAS')).array(), -51) 54assert(cumsum(x(:, 'VBIAS')).array(), cumsum(x.array(:, 'VBIAS'))) 55assert(sum(x(:, 5:6), 2).array(), sum(x.array(:, 5:6), 2)) 56assert(cumsum(x(:, 5:6), 2).array(), cumsum(x.array(:, 5:6), 2)) 57assert(nth_element(x.array(:, 4:6), 2:3), nth_element(x(:, 4:6), 2:3).array) 58y = x{}; 59assert(size(y), [10 7]) 60y = x{[2 5], [2 7]}; 61assert(y, {-5.8, "E"; -5.2, "C"}) 62y = x{}([2 5], [2 7]); 63assert(y, {-5.8, "E"; -5.2, "C"}) 64y = x{1:2, 1:2}(4); 65assert(y, {-5.8}) 66# remove a column through (:, name) access 67y = x; y(:, "DataName") = []; 68assert(size(y), [10 6]) 69# create an empty dataframe 70y = dataframe([]); 71assert(isempty(y), true) 72y = x.df(:, 2:6); 73Y = 2*pi*double(y.Freq).*y.C+y.GOUT; 74z = dataframe(y,{{'Y'; Y}}); 75assert(size(z), [10 6]) 76assert(abs(z(1, "Y") - Y(1)).array, 0) 77# direct matrix setting through struct access 78y.Freq=[(1:10).' (10:-1:1).']; 79# verify the "end" operator on the third dim 80assert(y.array(2, 2, end), 9) 81# direct setting through 3D matrix 82y(:, ["C"; "G"], 1:2) = repmat(y(:, ["C"; "G"]), [1 1 2]); 83y(4:5, 4:5) = NaN; 84# test 85if any(size(x) != [10 7]), 86 error('x: wrong input size') 87endif 88if any(size(y) != [10 5 2]), 89 error('y: wrong input size') 90endif 91# THIS MAY NOT CHANGE! numel is called by subsasgn and interfere 92# if not returning 1 93assert(numel(x), 1) 94assert(numel(x, ':'), 70) 95assert(numel(x, ':', 'Freq'), 10) 96assert(numel(x, ':', [1 3 5]), 30) 97assert(numel(x, ':', [1 3 5]), 30) 98assert(numel(x, x(:, "OK_") == 'A', ["C"; "G*"]), 4) 99# test simple slices 100assert(x.VBIAS(1:6), (-6:.2:-5).') 101assert(x.array(6:10, 2), (-5:.2:-4.2).') 102assert(x.array(6, "OK_"), 'B') 103assert(x.array(2, logical([0 0 1 1])), x.array(2, 3:4)) 104assert(size(y.array(:, :, :)), [10 5 2]) 105assert(size(y.array(:, :)), [10 10]) 106assert(size(y.array(:, 2, 2)), [10 1]) 107assert(size(y.array(:, 2)), [10 1]) 108assert(y.C(4:5), [NaN NaN]) 109 110myerr = false; errmsg = 'Line 90: Accessing dataframe past limits'; 111try 112 x(1, 8) 113 myerr = true; 114catch 115 end 116 if (myerr) error (errmsg); end 117 errmsg = 'Line 97: Accessing dataframe past limits'; 118 try 119 x(11, 1) 120 myerr = true; 121catch 122 end 123 if (myerr) error (errmsg); end 124 errmsg = 'Line 104: Accessing dataframe past limits'; 125 try 126 x(1, logical(ones(1, 8))) 127 myerr = true; 128 catch 129end 130if (myerr) error (errmsg); end 131errmsg = 'Line 111: Accessing dataframe with unknown column name'; 132 try 133 x.types{"FReq*"} 134 myerr = true; 135catch 136end 137if (myerr) error (errmsg); end 138 139# test 140#!! removed -- output format may only be specified before selection 141# select one column 142# assert(x(1:3, 1).cell(:), x.cell(1:3)(:)) 143# assert(x(33:35).cell.', x(33:35).cell(:)) 144# select two columns 145assert(x.cell(1:10, 2:3)(:), x.cell(11:30)(:)) 146errmsg = 'Line 126: Concatenating column of incompatible types'; 147 try 148 x(:); 149 myerr = true; 150catch 151end 152if (myerr) error (errmsg); end 153errmsg = 'Line 133: Concatenating column of incompatible types'; 154 try 155 x.dataframe(:); 156 myerr = true; 157catch 158end 159if (myerr) error (errmsg); end 160errmsg = 'Line 140: Illegal access'; 161 try 162 x.dataframe.cell 163 myerr = true; 164catch 165end 166if (myerr) error (errmsg); end 167# test 168# test modifying column type 169x.types("Freq") = 'uint32'; x.types(2) = 'single'; 170# downclassing must occur ! 171assert(class(x.array(1, ["Freq"; "C"])), 'uint32') 172# upclassing must occur ! 173assert(class(x.as.double(1, ["Freq"; "C"])), 'double') 174errmsg = 'Line 154: Incorrect internal field sub-referencing'; 175 try 176 x.types{"Freq"} 177 myerr = true; 178catch 179end 180if (myerr) error (errmsg); end 181# error errmsg='line :mixing different types") 182# removed: this now works, but downclassing to int 183# x([12:18 22:28 32:38]); 184errmsg = 'Line 164: non-square access'; 185try 186 x.dataframe([22:28 32:37]); 187 myerr = true; 188catch 189end 190if (myerr) error (errmsg); end 191errmsg = 'Line 171: non-square access'; 192try 193 x.cell([1:19]); 194 myerr = true; 195catch 196end 197if (myerr) error (errmsg); end 198errmsg = 'Line 176: single-dimension name access'; 199try 200 x('Freq'); 201 myerr = true; 202catch 203end 204if (myerr) error (errmsg); end 205# test 206# complex access 207x(x(:, "OK_") == '?', ["C"; "G*"]) = NaN; 208assert(x.array(4, 5:6), [NaN NaN]) 209# extract values 210y = x.dataframe(x(:, "OK_") =='A', {"Freq", "VB*", "C", "G"}); 211# comparison using cell output class, because assert use (:) 212assert(y.cell(:, 2:3), x.cell([1 7], ["VB*"; "C"])) 213assert(x.array((33:35).'), x.array(3:5, 4)) 214# test further dereferencing 215assert(x.array(:, "C")(2:4), x.array(2:4, "C")) 216# complex modifications through cell access 217z = dataframe(x, {"VB*", {"Polarity" ,"Sense"; ones(12,2), zeros(10,2)}}); 218assert(size(z), [12 9 2]) 219assert(z.Sense(11:12, :), NA*ones(2, 2)) 220assert(size(struct(z).x_over{2}, 2) - size(struct(x).x_over{2}, 2), 2) 221x = dataframe(randn(3, 3)); y = x.array; 222xl = x > 0; yl = y > 0; 223a = zeros(size(yl)); b = a; 224a(xl) = 1; b(yl) = 1; 225assert(a, b) 226[a, b] = sort(y(:)); y = reshape(b, 3, 3); x = dataframe(y); 227a = zeros(size(yl)); b = a; 228a(x) = 10:-1:2; b(y) = 10:-1:2; 229assert(a, b) 230x = dataframe(randn(3, 3)); y = randn(3, 3); z = dataframe(y); 231assert((x+y(1)).array, x.array+y(1)) 232assert((y(1)+x).array, y(1)+x.array) 233assert((x+y).array, x.array+y) 234assert((y+x).array, y+x.array) 235assert((x+z).array, x.array+z.array) 236assert((bsxfun(@plus, x, z(1,:))).array, bsxfun(@plus, x.array, z.array(1,:))) 237assert((bsxfun(@plus, x, z(:,1))).array, bsxfun(@plus, x.array, z.array(:,1))) 238assert((bsxfun(@minus,z(1,:),x)).array, bsxfun(@minus,z.array(1,:),x.array)) 239assert((bsxfun(@minus,z(:,1),x)).array, bsxfun(@minus,z.array(:,1),x.array)) 240assert((x > 0).array, x.array > 0) 241assert((0 > x).array, 0 > x.array) 242assert((x > y).array, x.array > y); 243assert((y > x).array, y > x.array); 244assert((x > z).array, x.array > z.array) 245assert((x*y(1)).array, x.array*y(1)) 246assert((y(1)*x).array, y(1)*x.array) 247assert((x.*y).array, x.array.*y) 248assert((y.*x).array, y.*x.array) 249assert((z.*x).array, z.array.*x.array) 250assert((x*y).array, x.array*y) 251assert((y*x).array, y*x.array) 252assert((x*z).array, x.array*z.array) 253assert((x/y(1)).array, x.array/y(1)) 254assert((x./y).array, x.array./y) 255assert((y./x).array, y./x.array) 256assert((z./x).array, z.array./x.array) 257assert((x/y).array, x.array/y) 258assert((y/x).array, y/x.array) 259assert((x/z).array, x.array/z.array) 260# left division is a bit more complicated 261assert((x(1, 1)\y).array, x.array(1, 1)\y, sqrt(eps)) 262assert((x(:, 1)\y).array, x.array(:, 1)\y, sqrt(eps)) 263assert((x(:, 1:2)\y).array, x.array(:, 1:2)\y, sqrt(eps)) 264assert((x\y).array, x.array\y, sqrt(eps)) 265assert((y\x).array, y\x.array, sqrt(eps)) 266assert((x\z).array, x.array\z.array, sqrt(eps)) 267x=dataframe(randn(4, 3, 2)); y=randn(4, 3, 2); z=dataframe(y); 268assert((abs(sum(center(x)) < sqrt(eps)).array)) 269assert((x+y).array, x.array+y) 270assert((y+x).array, y+x.array) 271assert((x+z).array, x.array+z.array) 272assert((bsxfun(@plus,x,z(1,:,:))).array, bsxfun(@plus,x.array,z.array(1,:,:))) 273assert((bsxfun(@plus,x,z(:,1,:))).array, bsxfun(@plus,x.array,z.array(:,1,:))) 274assert((bsxfun(@plus,z(1,:,:),x)).array, bsxfun(@plus,z.array(1,:,:),x.array)) 275assert((bsxfun(@plus,z(:,1,:),x)).array, bsxfun(@plus,z.array(:,1,:),x.array)) 276[a, b] = sort(x(:)); b = b(b <= 9); 277x = dataframe(reshape((1:9)(b), [3 3])); 278y = reshape((1:9)(b), [3 3]); z = dataframe(y); 279assert(x(x(:)), y(x(:))) 280assert(x(y(:)), y(y(:))) 281z= x(x); 282assert(z.array, y(x)) 283z = x(y); 284assert(z.array, y(y)) 285disp('All tests passed'); 286