1 function resu = df_func(func, A, B, itercol=true, whole=logical([0 0]));
3 %# function resu = df_func(func, A, B, whole)
4 %# Implements an iterator to apply some func when at
5 %# least one argument is a dataframe. The output is a dataframe with
6 %# the same metadata, types may be altered, like f.i. double=>logical.
7 %# When itercol is 'true', the default, LHS is iterated by columns,
8 %# otherwise by rows. 'Whole' is a two-elements logical vector with
9 %# the meaning that LHS and or RHS must be iterated at once or not
11 %% Copyright (C) 2009-2012 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
13 %% This file is part of Octave.
15 %% Octave is free software; you can redistribute it and/or
16 %% modify it under the terms of the GNU General Public
17 %% License as published by the Free Software Foundation;
18 %% either version 2, or (at your option) any later version.
20 %% Octave is distributed in the hope that it will be useful,
21 %% but WITHOUT ANY WARRANTY; without even the implied
22 %% warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
23 %% PURPOSE. See the GNU General Public License for more
26 %% You should have received a copy of the GNU General Public
27 %% License along with Octave; see the file COPYING. If not,
28 %% write to the Free Software Foundation, 51 Franklin Street -
29 %% Fifth Floor, Boston, MA 02110-1301, USA.
32 %# $Id: df_func.m 9585 2012-02-05 15:32:46Z cdemills $
35 [A, B, resu] = df_basecomp(A, B, itercol, func);
36 itercol = itercol(1); %# drop second value
38 if (isa(B, 'dataframe'))
39 if (!isa(A, 'dataframe')),
41 for indi = resu._cnt(2):-1:1,
42 switch resu._type{indi}
44 resu._data{indi} = feval(func, A, char(B._data{indi}));
46 resu._data{indi} = feval(func, A, B._data{indi});
51 if (whole(1) && !whole(2)),
52 for indi = resu._cnt(2):-1:1,
53 switch resu._type{indi}
55 resu._data{indi} = feval(func, A, \
56 char(B._data{indi}(:, B._rep{indi})));
58 resu._data{indi} = feval(func, A, \
59 B._data{indi}(:, B._rep{indi}));
61 resu._rep{indi} = 1:size(resu._data{indi}, 2);
63 elseif (itercol && !whole(2)),
64 for indi = resu._cnt(2):-1:1,
65 switch resu._type{indi}
67 resu._data{indi} = feval(func, squeeze(A(:, indi, :)), \
68 char(B._data{indi}(:, B._rep{indi})));
70 resu._data{indi} = feval(func, squeeze(A(:, indi, :)), \
71 B._data{indi}(:, B._rep{indi}));
73 resu._rep{indi} = 1:size(resu._data{indi}, 2);
77 for indi = resu._cnt(2):-1:1,
78 switch resu._type{indi}
80 resu._data{indi} = feval(func, A(indi, :), char(B._data{indi}));
82 resu._data{indi} = feval(func, A(indi, :), B._data{indi});
86 dummy = feval(func, A, df_whole(B));
87 for indi = resu._cnt(2):-1:1, %# store column-wise
88 resu._data{indi} = squeeze(dummy(:, indi, :));
89 resu._rep{indi} = 1:size(resu._data{indi}, 2);
90 resu._type{indi} = class(dummy);
96 for indi = resu._cnt(2):-1:1,
97 switch resu._type{indi}
99 resu._data{indi} = feval\
100 (func, char(A._data{indi}(:, A._rep{indi})), \
101 char(B._data{indi}(B._rep{indi})));
103 resu._data{indi} = feval\
104 (func, A._data{indi}(:, A._rep{indi}), \
105 B._data{indi}(:, B._rep{indi}));
107 resu._rep{indi} = 1:size(resu._data{indi}, 2);
109 else %# itercol is false
112 for indi = resu._cnt(2):-1:1,
113 switch resu._type{indi}
115 resu._data{indi} = feval(func, dummy, \
116 char(B._data{indi}(:, B._rep{indi})));
118 resu._data{indi} = feval(func, dummy, \
119 B._data{indi}(:, B._rep{indi}));
121 resu._rep{indi} = 1:size(resu._data{indi}, 2);
124 for indi = resu._cnt(2):-1:1,
125 switch resu._type{indi}
127 resu._data{indi} = squeeze\
128 (feval(func, dummy(indi, :, :),\
129 char(B._data{indi}(:, B._rep{indi}))));
131 resu._data{indi} = squeeze\
132 (feval(func, dummy(indi, :, :), \
133 B._data{indi}(:, B._rep{indi})));
135 resu._rep{indi} = 1:size(resu._data{indi}, 2);
138 dummy = feval(func, dummy, df_whole(B));
139 for indi = resu._cnt(2):-1:1, %# store column-wise
140 resu._data{indi} = squeeze(dummy(:, indi, :));
141 resu._rep{indi} = 1:size(resu._data{indi}, 2);
142 resu._type{indi} = class(dummy);
147 else %# B is not a dataframe
149 for indi = resu._cnt(2):-1:1,
150 switch resu._type{indi}
152 resu._data{indi} = feval(func, char(A._data{indi}), B);
154 resu._data{indi} = feval(func, A._data{indi}, B);
161 for indi = resu._cnt(2):-1:1,
162 switch resu._type{indi}
164 unfolded = char(A._data{indi}(:, A._rep{indi}));
166 unfolded = A._data{indi}(:, A._rep{indi});
168 resu._data{indi} = squeeze(feval(func, unfolded, B));
169 resu._rep{indi} = 1:size(resu._data{indi}, 2);
172 for indi = resu._cnt(2):-1:1,
173 switch resu._type{indi}
175 unfolded = char(A._data{indi}(:, A._rep{indi}));
177 unfolded = A._data{indi}(:, A._rep{indi});
179 resu._data{indi} = feval(func, unfolded, \
180 squeeze(B(:, indi, :)));
181 resu._rep{indi} = 1:size(resu._data{indi}, 2);
187 for indi = columns(B):-1:1,
188 resu._data{indi} = squeeze(feval(func, dummy, B(:, indi, :)));
189 resu._rep{indi} = 1:size(resu._data{indi}, 2);
193 for indi = resu._cnt(1):-1:1,
194 resu._data{indi} = squeeze(feval(func, dummy(indi, :, :), \
196 resu._rep{indi} = 1:size(resu._data{indi}, 2);
199 for indi = resu._cnt(1):-1:1, %# in place computation
200 dummy(indi, :, :) = feval(func, dummy(indi, :, :), B);
202 for indi = resu._cnt(2):-1:1, %# store column-wise
203 resu._data{indi} = squeeze(dummy(:, indi, :));
204 resu._rep{indi} = 1:size(resu._data{indi}, 2);
208 %# verify that sizes match, this is required for "\"
209 resu._cnt(2) = length(resu._data);
210 resu._cnt(1) = max(cellfun('size', resu._data, 1));
211 if (length(resu._ridx) < resu._cnt(1)),
212 if (1 == length(resu._ridx)),
213 resu._ridx(end+1:resu._cnt(1), 1) = resu._ridx(1);
215 resu._ridx(end+1:resu._cnt(1), 1) = NA;
218 if (length(resu._name{2}) < resu._cnt(2)),
219 if (1 == length(resu._name{2})),
220 resu._name{2}(end+1:resu._cnt(2), 1) = resu._name{2};
221 resu._over{2}(end+1:resu._cnt(2), 1) = resu._over{2};
223 resu._name{2}(end+1:resu._cnt(2), 1) = '_';
224 resu._over{2}(end+1:resu._cnt(2), 1) = true;
231 resu._type = cellfun(@class, resu._data, "UniformOutput", false);
233 resu = df_thirddim(resu);