1function df = df_pad(df, dim, n, coltype) 2 %# function resu = df_pad(df, dim, n, coltype = []) 3 %# given a dataframe, insert n rows or columns, and adjust everything 4 %# accordingly. Coltype is a supplemental argument: 5 %# dim = 1 => not used 6 %# dim = 2 => type of the added column(s) 7 %# dim = 3 => index of columns receiving a new sheet (default: all) 8 9 %% Copyright (C) 2009-2017 Pascal Dupuis <cdemills@gmail.com> 10 %% 11 %% This file is part of the dataframe package for Octave. 12 %% 13 %% This package is free software; you can redistribute it and/or 14 %% modify it under the terms of the GNU General Public 15 %% License as published by the Free Software Foundation; 16 %% either version 2, or (at your option) any later version. 17 %% 18 %% This package is distributed in the hope that it will be useful, 19 %% but WITHOUT ANY WARRANTY; without even the implied 20 %% warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 21 %% PURPOSE. See the GNU General Public License for more 22 %% details. 23 %% 24 %% You should have received a copy of the GNU General Public 25 %% License along with this package; see the file COPYING. If not, 26 %% see <http://www.gnu.org/licenses/>. 27 28 if (nargin < 4), coltype = []; end 29 try 30 NA = NA; 31 catch 32 NA = NaN; 33 end 34 35 switch dim 36 case 1 37 if (~isempty (df.x_name{1})), 38 if (length (df.x_name{1}) < df.x_cnt(1)+n) 39 %# generate a name for the new row(s) 40 df.x_name{1}(df.x_cnt(1)+(1:n), 1) = {'_'}; 41 df.x_over{1}(1, df.x_cnt(1)+(1:n), 1) = true; 42 end 43 end 44 %# complete row indexes: by default, row number. 45 if (isempty (df.x_ridx)) 46 (1:n); 47 dummy = ans(:); 48 else 49 dummy = vertcat (df.x_ridx, repmat (size (df.x_ridx, 1)+(1:n).', ... 50 1, size (df.x_ridx, 2))); 51 end 52 df.x_ridx = dummy; 53 %# pad every line 54 for indi = (1:min (size (df.x_data, 2), df.x_cnt(2))) 55 neff = n + df.x_cnt(1) - size (df.x_data{indi}, 1); 56 if (neff > 0) 57 m = max(1, size (df.x_data{indi}, 2)); 58 switch df.x_type{indi} 59 case {'char'} 60 %# there is no 'string NA' 61 dummy = {}; dummy(1:neff, 1:m) = 'NA'; 62 dummy = vertcat (df.x_data{indi}, dummy); 63 case { 'double'} 64 dummy = vertcat (df.x_data{indi}, repmat (NA, neff, m)); 65 %# there is no 'NA' with logical values, avoid casting error 66 case {'logical'} 67 dummy = vertcat (df.x_data{indi}, repmat (false, neff, m)); 68 otherwise 69 dummy = cast (vertcat (df.x_data{indi}, repmat (NA, neff, m)), ... 70 df.x_type{indi}); 71 end 72 df.x_data{indi} = dummy; 73 if (isempty (df.x_rep{indi})) 74 df.x_rep{indi} = 1; 75 end 76 end 77 end 78 df.x_cnt(1) = df.x_cnt(1) + n; 79 80 case 2 81 %# create new columns 82 if (isempty (coltype)) 83 error ('df_pad: dim equals 2, and coltype undefined'); 84 end 85 if (length (n) > 1) %#second value is an offset 86 indc = n(2); n = n(1); 87 if (indc < df.x_cnt(2)), 88 %# shift to the right 89 df.x_name{2}(n + (indc+1:end)) = df.x_name{2}(indc+1:end); 90 df.x_over{2}(n + (indc+1:end)) = df.x_over{2}(indc+1:end); 91 dummy = cstrcat (repmat ('_', n, 1), ... 92 strjust (num2str(indc + (1:n).'), 'left')); 93 df.x_name{2}(indc + (1:n)) = cellstr (dummy); 94 df.x_over{2}(indc + (1:n)) = true; 95 df.x_type(n+(indc+1:end)) = df.x_type(indc+1:end); 96 df.x_type(indc + (1:n)) = NA; 97 df.x_data(n + (indc+1:end)) = df.x_data(indc+1:end); 98 df.x_rep(n + (indc+1:end)) = df.x_rep(indc+1:end); 99 df.x_data(indc + (1:n)) = NA; 100 df.x_rep(indc + (1:n)) = 1; 101 end 102 else 103 %# add new values after the last column 104 indc = min (size (df.x_data, 2), df.x_cnt(2)); 105 end 106 if (~isa (coltype, 'cell')) coltype = {coltype}; end 107 if (isscalar (coltype) && n > 1) 108 coltype = repmat (coltype, 1, n); 109 end 110 for indi = (1:n) 111 switch coltype{indi} 112 case {'char'} 113 dummy = {repmat(NA, df.x_cnt(1), 1) }; 114 dummy(:, 1) = '_'; 115 case { 'double'} 116 dummy = repmat (NA, df.x_cnt(1), 1); 117 case {'logical'} %# there is no NA in logical type 118 dummy = repmat (false, df.x_cnt(1), 1); 119 otherwise 120 try 121 dummy = cast (repmat (NA, df.x_cnt(1), 1), coltype{indi}); 122 catch 123 %# There was an issue -- transfer coltype to data 124 if (indc+indi > df.x_cnt(2)) 125 dummy = {coltype{indi}}; coltype{indi} = 'char'; 126 if (df.x_cnt(1) < 1) 127 %# nothing defined yet -- pad with one line 128 df.x_type{indc+indi} = coltype{indi}; 129 df = df_pad (df, 1, 1); 130 end 131 else 132 dummy = sprintf ('Trying to change type of column %d, which was %s, to %s', ... 133 indc+indi, df.x_type{indi}, coltype{indi}); 134 error (dummy); 135 end 136 end 137 end 138 df.x_data{indc+indi} = dummy; 139 df.x_rep{indc+indi} = 1; 140 df.x_type{indc+indi} = coltype{indi}; 141 end 142 143 if (size (df.x_data, 2) > df.x_cnt(2)), 144 df.x_cnt(2) = size (df.x_data, 2); 145 end 146 if (length (df.x_name{2}) < df.x_cnt(2)), 147 %# generate a name for the new column(s) 148 dummy = cstrcat (repmat ('_', n, 1), ... 149 strjust (num2str (indc + (1:n).'), 'left')); 150 df.x_name{2}(indc + (1:n)) = cellstr (dummy); 151 df.x_over{2}(1, indc + (1:n)) = true; 152 end 153 154 case 3 155 if (n <= 0) return; end 156 if (isempty (coltype)), 157 coltype = 1:df.x_cnt(2); 158 end 159 dummy = max (n+cellfun (@length, df.x_rep(coltype))); 160 if (size (df.x_ridx, 2) < dummy), 161 df.x_ridx(:, end+1:dummy) = NA; 162 end 163 for indi = (coltype) 164 switch df.x_type{indi} 165 case {'char'} 166 if (isa (df.x_data{indi}, 'char')) %# pure char 167 dummy = horzcat (df.x_data{indi}(:, df.x_rep{indi}), ... 168 repmat({NA}, df.x_cnt(1), 1)); 169 keyboard 170 else 171 dummy = horzcat (df.x_data{indi}(:, df.x_rep{indi}), ... 172 repmat({NA}, df.x_cnt(1), 1)); 173 end 174 case {'double'} 175 dummy = horzcat (df.x_data{indi}(:, df.x_rep{indi}), ... 176 repmat (NA, df.x_cnt(1), 1)); 177 case {'logical'} 178 %# there is no logical 'NA' -- fill empty elems with false 179 dummy = horzcat (df.x_data{indi}(:, df.x_rep{indi}), ... 180 repmat (false, df.x_cnt(1), 1)); 181 otherwise 182 dummy = cast (horzcat (df.x_data{indi}(:, df.x_rep{indi}), ... 183 repmat (NA, df.x_cnt(1), 1)), ... 184 df.x_type{indi}); 185 end 186 df.x_data{indi} = dummy; 187 df.x_rep{indi} = [df.x_rep{indi} length(df.x_rep{indi})+ones(1, n)]; 188 try 189 assert (size(df.x_data{indi}, 2), max(df.x_rep{indi})) 190 catch 191 keyboard 192 end 193 end 194 df = df_thirddim (df); 195 otherwise 196 error ('Invalid dimension in df_pad'); 197 end 198 199end 200