-
Notifications
You must be signed in to change notification settings - Fork 8
/
padcat.m
157 lines (141 loc) · 5.47 KB
/
padcat.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
function [M, TF] = padcat(varargin)
% PADCAT - concatenate vectors with different lengths by padding with NaN
%
% M = PADCAT(V1, V2, V3, ..., VN) concatenates the vectors V1 through VN
% into one large matrix. All vectors should have the same orientation,
% that is, they are all row or column vectors. The vectors do not need to
% have the same lengths, and shorter vectors are padded with NaNs.
% The size of M is determined by the length of the longest vector. For
% row vectors, M will be a N-by-MaxL matrix and for column vectors, M
% will be a MaxL-by-N matrix, where MaxL is the length of the longest
% vector.
%
% Examples:
% a = 1:5 ; b = 1:3 ; c = [] ; d = 1:4 ;
% padcat(a,b,c,d) % row vectors
% % -> 1 2 3 4 5
% % 1 2 3 NaN NaN
% % NaN NaN NaN NaN NaN
% % 1 2 3 4 NaN
% CC = {d.' a.' c.' b.' d.'} ;
% padcat(CC{:}) % column vectors
% % 1 1 NaN 1 1
% % 2 2 NaN 2 2
% % 3 3 NaN 3 3
% % 4 4 NaN NaN 4
% % NaN 5 NaN NaN NaN
%
% [M, TF] = PADCAT(..) will also return a logical matrix TF with the same
% size as R having true values for those positions that originate from an
% input vector. This may be useful if any of the vectors contain NaNs.
%
% Example:
% a = 1:3 ; b = [] ; c = [1 NaN] ;
% [M,tf] = padcat(a,b,c)
% % find the original NaN
% [Vev,Pos] = find(tf & isnan(M))
% % -> Vec = 3 , Pos = 2
%
% This second output can also be used to change the padding value into
% something else than NaN.
%
% [M, tf] = padcat(1:3,1,1:4)
% M(~tf) = 99 % change the padding value into 99
%
% Scalars will be concatenated into a single column vector.
%
% See also CAT, RESHAPE, STRVCAT, CHAR, HORZCAT, VERTCAT, ISEMPTY
% NONES, GROUP2CELL (Matlab File Exchange)
% for Matlab 2008 and up (tested in R2011a)
% version 1.2 (oct 2011)
% (c) Jos van der Geest
% email: [email protected]
% History
% 1.0 (feb 2009) created
% 1.1 (feb 2011) improved comments
% 1.2 (oct 2011) added help on changing the padding value into something
% else than NaN
% Acknowledgements:
% Inspired by padadd.m (feb 2000) Fex ID 209 by Dave Johnson
error(nargchk(1,Inf,nargin)) ;
% check the inputs
SZ = cellfun(@size,varargin,'UniformOutput',false) ; % sizes
Ndim = cellfun(@ndims,varargin) ; %
if ~all(Ndim==2)
error([mfilename ':WrongInputDimension'], ...
'Input should be vectors.') ;
end
TF = [] ; % default second output so we do not have to check all the time
% for 2D matrices (including vectors) the size is a 1-by-2 vector
SZ = cat(1,SZ{:}) ;
maxSZ = max(SZ) ; % probable size of the longest vector
% maxSZ equals :
% - [1 1] for all scalars input
% - [X 1] for column vectors
% - [1 X] for all row vectors
% - [X Y] otherwise (so padcat will not work!)
if ~any(maxSZ == 1), % hmm, not all elements are 1-by-N or N-by-1
% 2 options ...
if any(maxSZ==0),
% 1) all inputs are empty
M = [] ;
return
else
% 2) wrong input
% Either not all vectors have the same orientation (row and column
% vectors are being mixed) or an input is a matrix.
error([mfilename ':WrongInputSize'], ...
'Inputs should be all row vectors or all column vectors.') ;
end
end
if nargin == 1,
% single input, nothing to concatenate ..
M = varargin{1} ;
else
% Concatenate row vectors in a row, and column vectors in a column.
dim = (maxSZ(1)==1) + 1 ; % Find out the dimension to work on
X = cat(dim, varargin{:}) ; % make one big list
% we will use linear indexing, which operates along columns. We apply a
% transpose at the end if the input were row vectors.
if maxSZ(dim) == 1,
% if all inputs are scalars, ...
M = X ; % copy the list
elseif all(SZ(:,dim)==SZ(1,dim)),
% all vectors have the same length
M = reshape(X,SZ(1,dim),[]) ;% copy the list and reshape
else
% We do have vectors of different lengths.
% Pre-allocate the final output array as a column oriented array. We
% make it one larger to accommodate the largest vector as well.
M = zeros([maxSZ(dim)+1 nargin]) ;
% where do the fillers begin in each column
M(sub2ind(size(M), SZ(:,dim).'+1, 1:nargin)) = 1 ;
% Fillers should be put in after that position as well, so applying
% cumsum on the columns
% Note that we remove the last row; the largest vector will fill an
% entire column.
M = cumsum(M(1:end-1,:),1) ; % remove last row
% If we need to return position of the non-fillers we will get them
% now. We cannot do it afterwards, since NaNs may be present in the
% inputs.
if nargout>1,
TF = ~M ;
% and make use of this logical array
M(~TF) = NaN ; % put the fillers in
M(TF) = X ; % put the values in
else
M(M==1) = NaN ; % put the fillers in
M(M==0) = X ; % put the values in
end
end
if dim == 2,
% the inputs were row vectors, so transpose
M = M.' ;
TF = TF.' ; % was initialized as empty if not requested
end
end % nargin == 1
if nargout > 1 && isempty(TF),
% in this case, the inputs were all empty, all scalars, or all had the
% same size.
TF = true(size(M)) ;
end