]> Creatis software - CreaPhase.git/blob - octave_packages/dataframe-0.9.1/@dataframe/cat.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / dataframe-0.9.1 / @dataframe / cat.m
1 function resu = cat(dim, A, varargin)
2   %# function resu = cat(dim, A, varargin)
3   %# This is the concatenation operator for a dataframe object. "Dim"
4   %# has the same meaning as ordinary cat. Next arguments may be
5   %# dataframe, vector/matrix, or two elements cells. First one is taken
6   %# as row/column name, second as data.
7
8   %% Copyright (C) 2009-2012 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
9   %%
10   %% This file is part of Octave.
11   %%
12   %% Octave is free software; you can redistribute it and/or
13   %% modify it under the terms of the GNU General Public
14   %% License as published by the Free Software Foundation;
15   %% either version 2, or (at your option) any later version.
16   %%
17   %% Octave is distributed in the hope that it will be useful,
18   %% but WITHOUT ANY WARRANTY; without even the implied
19   %% warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20   %% PURPOSE.  See the GNU General Public License for more
21   %% details.
22   %%
23   %% You should have received a copy of the GNU General Public
24   %% License along with Octave; see the file COPYING.  If not,
25   %% write to the Free Software Foundation, 51 Franklin Street -
26   %% Fifth Floor, Boston, MA 02110-1301, USA.
27   
28   %#
29   %# $Id: cat.m 9585 2012-02-05 15:32:46Z cdemills $
30   %#
31
32   if (!isa(A, 'dataframe')),
33     A = dataframe(A);
34   endif
35
36   switch dim
37     case 1
38       resu = A;
39           
40       for indi = 1:length(varargin),
41         B = varargin{indi};
42         if !isa(B, 'dataframe'),
43           if iscell(B) && 2 == length(B),
44             B = dataframe(B{2}, 'rownames', B{1});
45           else
46             B = dataframe(B, 'colnames', inputname(2+indi));
47           endif
48         endif
49         if resu._cnt(2) != B._cnt(2),
50           error('Different number of columns in dataframes');
51         endif
52         %# do not duplicate empty names
53         if !isempty(resu._name{1}) || !isempty(B._name{1}),
54           if length(resu._name{1}) < resu._cnt(1),
55             resu._name{1}(end+1:resu._cnt(1), 1) = {''};
56           endif
57           if length(B._name{1}) < B._cnt(1),
58             B._name{1}(end+1:B._cnt(1), 1) = {''};
59           endif
60           resu._name{1} = vertcat(resu._name{1}(:),  B._name{1}(:));
61           resu._over{1} = [resu._over{1} B._over{1}];
62         endif
63         resu._cnt(1) = resu._cnt(1) + B._cnt(1);
64         if size(resu._ridx, 2) < size(B._ridx, 2),
65           resu._ridx(:, end+1:size(B._ridx, 2)) = NA;
66         elseif size(resu._ridx, 2) > size(B._ridx, 2),
67           B._ridx(:, end+1:size(resu._ridx, 2)) = NA;
68         endif
69         resu._ridx = [resu._ridx; B._ridx];
70         %# find data with same column names
71         dummy = A._over{2} & B._over{2}; 
72         indA = true(1, resu._cnt(2));
73         indB = true(1, resu._cnt(2));
74         for indj = 1:resu._cnt(2),
75           if (dummy(indj)),
76             indk = strmatch(resu._name{2}(indj), B._name{2}, 'exact');
77             if (~isempty(indk)),
78               indk = indk(1);
79               if ~strcmp(resu._type{indj}, B._type{indk}),
80                 error("Trying to mix columns of different types");
81               endif
82             endif
83           else
84             indk = indj;
85           endif
86           resu._data{indj} = [resu._data{indj}; B._data{indk}];
87           indA(indj) = false; indB(indk) = false;
88         endfor
89         if any(indA) || any(indB)
90           error('Different number/names of columns in dataframe');
91         endif
92         
93       endfor
94       
95     case 2
96       resu = A;
97
98       for indi = 1:length(varargin),
99         B = varargin{indi};
100         if !isa(B, 'dataframe'),
101           if iscell(B) && 2 == length(B),
102             B = dataframe(B{2}, 'colnames', B{1});
103           else
104             B = dataframe(B, 'colnames', inputname(2+indi));
105           endif
106           B._ridx = resu._ridx; %# make them compatibles
107         endif
108         if resu._cnt(1) != B._cnt(1),
109           error('Different number of rows in dataframes');
110         endif
111         if any(resu._ridx(:) - B._ridx(:))
112           error('dataframes row indexes not matched');
113         endif
114         resu._name{2} = vertcat(resu._name{2}, B._name{2});
115         resu._over{2} = [resu._over{2} B._over{2}];
116         resu._data(resu._cnt(2)+(1:B._cnt(2))) = B._data;
117         resu._type(resu._cnt(2)+(1:B._cnt(2))) = B._type;
118         resu._cnt(2) = resu._cnt(2) + B._cnt(2);        
119       endfor
120       
121     case 3
122       resu = A;
123       
124       for indi = 1:length(varargin),
125         B = varargin{indi};
126         if (!isa(B, 'dataframe')),
127           if (iscell(B) && 2 == length(B)),
128             B = dataframe(B{2}, 'rownames', B{1});
129           else
130             B = dataframe(B, 'colnames', inputname(indi+2)); 
131           endif
132         endif
133         if (resu._cnt(1) != B._cnt(1)),
134           error('Different number of rows in dataframes');
135         endif
136         if (resu._cnt(2) != B._cnt(2)),
137           error('Different number of columns in dataframes');
138         endif
139         %# to be merged against 3rd dim, rownames must be equals, if
140         %# non-empty. Columns are merged based upon their name; columns
141         %# with identic content are kept.
142
143         if size(resu._ridx, 2) < size(B._ridx, 2),
144           resu._ridx(:, end+1:size(B._ridx, 2)) = NA;
145         elseif size(resu._ridx, 2) > size(B._ridx, 2),
146           B._ridx(:, end+1:size(resu._ridx, 2)) = NA;
147         endif
148         resu._ridx = cat(3, resu._ridx, B._ridx);
149         %# find data with same column names
150         indA = true(1, resu._cnt(2));
151         indB = true(1, resu._cnt(2));
152         dummy = A._over{2} & B._over{2}; 
153         for indj = 1:resu._cnt(2),
154           if (dummy(indj)),
155             indk = strmatch(resu._name{2}(indj), B._name{2}, 'exact');
156             if (~isempty(indk)),
157               indk = indk(1);
158               if (~strcmp(resu._type{indj}, B._type{indk})),
159                 error("Trying to mix columns of different types");
160               endif
161             endif
162           else
163             indk = indj;
164           endif
165           if (all([isnumeric(resu._data{indj}) isnumeric(B._data{indk})])),
166             %# iterate over the columns of resu and B
167             op1 = resu._data{indj}; op2 = B._data{indk};
168             for ind2=1:columns(op2),
169               indr = false;
170               for ind1=1:columns(op1),
171                 if (all(abs(op1(:, ind1) - op2(:, ind2)) <= eps)),
172                   resu._rep{indj} = [resu._rep{indj} ind1];
173                   indr = true;
174                   break;
175                 endif
176               endfor
177               if (!indr),
178                 %# pad in the second dim
179                 resu._data{indj} = [resu._data{indj}, B._data{indk}];
180                 resu._rep{indj} = [resu._rep{indj} 1+length(resu._rep{indj})];
181               endif
182             endfor
183           else
184             resu._data{indj} = [resu._data{indj} B._data{indk}];
185             resu._rep{indj} = [resu._rep{indj} 1+length(resu._rep({indj}))];
186           endif
187           indA(indj) = false; indB(indk) = false;
188         endfor
189         if (any(indA) || any(indB)),
190           error('Different number/names of columns in dataframe');
191         endif
192       endfor
193      
194       resu = df_thirddim(resu);
195       
196     otherwise
197       error('Incorrect call to cat');
198   endswitch
199   
200   %#  disp('End of cat'); keyboard
201 endfunction