dm = readtable('iris_subset.csv');

target = "Species";
varnames = dm.Properties.VariableNames;
features = varnames (~strcmp(varnames, target));

X = dm{:, features};
y = dm{:, target};

% find and remove rows where target is missing
missing_target = ismissing(y);
X(missing_target,:) = [];
y(missing_target) = [];

% convert target to integers 1, 2, 3, etc. 
[labels, ~, y] = unique(y);

% compute column means of feature values
mu = mean(X, 1, 'omitmissing')
miss = ismissing(X);        % logical matrix with 1 
                            % for missing values

[~, col_miss] = find(miss); % find column/feature  
                            % for missing data
X(miss) = mu(col_miss);     % replace with corresponding 
                            % column / feature means

% compute upper gates (ug) 
mu = mean (X);              % recalculate the mean
sd = std (X, 1);

% clip values higher than upper gate (ug) 

%upper gate for each feature based on feature mean
ug = mu + 2*sd;	    
        
% a constant lower gate  of 0.1 for all features
lg = repmat(0.1, 1, size(X,2)); 


ug_clip = (X > ug);         % logical matrix: upper outliers
[~, col_ug] = find(ug_clip);
X(ug_clip) = ug(col_ug);    % replace with upper gate values

 
lg_clip = (X < lg);         % logical matrix: lower outliers
[~, col_lg] = find(lg_clip);
X(lg_clip) = lg(col_lg);    % replace with lower gate values
