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