Skip to content

Commit

Permalink
Fix #1248: add renamevars and removevars functions (#1266)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nelson-numerical-software authored Oct 25, 2024
1 parent 8fe7645 commit 81b2c42
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `end` magic keyword can be overloaded for classes (applied to `table` class).
- [#1250](http://github.com/nelson-lang/nelson/issues/1250) `head`, `tail` functions for table and array.
- [#1248](http://github.com/nelson-lang/nelson/issues/1248) `removevars`, `renamevars` functions for table.

### Changed

Expand Down
20 changes: 14 additions & 6 deletions modules/table/functions/@table/subsasgn.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,19 @@
if ~isequal(size(before.RowNames), size(value.RowNames))
error(_('Value assignment must be same size as existing value.'));
end
if isstring(value.VariableNames)
value.VariableNames = cellstr(value.VariableNames);
end
if isstring(value.RowNames)
value.RowNames = cellstr(value.RowNames);
ce = {};
if isstring(value.VariableNames) || iscellstr(value.VariableNames)
if iscellstr(value.VariableNames)
ce = value.VariableNames;
else
ce = cellstr(value.VariableNames);
end
R = renamevars(T, before.VariableNames, ce);
return
else
if isstring(value.RowNames)
value.RowNames = cellstr(value.RowNames);
end
end
st.Properties = value;
R = class(st, 'table');
Expand Down Expand Up @@ -205,7 +213,7 @@
end
else
% Delete specific columns
if ~isequal(idxRow, 1:width(T)) || isempty(idxCol)
if ~isequal(idxRow, 1:height(T)) || isempty(idxCol)
error(_('At least one subscript must be '':'' when you delete rows or variables by assigning [].'));
end
for j = idxCol
Expand Down
6 changes: 6 additions & 0 deletions modules/table/functions/@table/subsref.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
% Keep as is
elseif ischar(rowIdx) || iscellstr(rowIdx) || isstring(rowIdx)
% Handle row names
if ischar(rowIdx)
rowIdx = {rowIdx};
end
rowIdx = find(ismember(st.Properties.RowNames, rowIdx));
if isempty(rowIdx)
error(_('Row name not found.'));
Expand All @@ -147,6 +150,8 @@
% Handle column indexing
if ischar(colIdx) && strcmp(colIdx, ':')
colIdx = 1:width(T);
elseif ischar(colIdx) && isrow(colIdx)
colIdx = find(ismember(st.Properties.VariableNames, {colIdx}));
elseif islogical(colIdx)
colIdx = find(colIdx);
elseif isnumeric(colIdx)
Expand All @@ -156,6 +161,7 @@
else
error(_('Invalid column indexing.'));
end

selectedVarNames = st.Properties.VariableNames(colIdx);
tableData = cell(1, length(selectedVarNames));
for i = 1:length(selectedVarNames)
Expand Down
23 changes: 23 additions & 0 deletions modules/table/functions/removevars.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
%=============================================================================
% Copyright (c) 2016-present Allan CORNET (Nelson)
%=============================================================================
% This file is part of the Nelson.
%=============================================================================
% LICENCE_BLOCK_BEGIN
% SPDX-License-Identifier: LGPL-3.0-or-later
% LICENCE_BLOCK_END
%=============================================================================
function varargout = removevars(varargin)
nargoutchk(0, 1);
narginchk(1, 2);
T = varargin{1};
mustBeA(T, 'table', 1);
if (nargin < 2)
vars = [];
else
vars = varargin{2};
end
T(:, vars) = [];
varargout{1} = T;
end
%=============================================================================
88 changes: 88 additions & 0 deletions modules/table/functions/renamevars.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
%=============================================================================
% Copyright (c) 2016-present Allan CORNET (Nelson)
%=============================================================================
% This file is part of the Nelson.
%=============================================================================
% LICENCE_BLOCK_BEGIN
% SPDX-License-Identifier: LGPL-3.0-or-later
% LICENCE_BLOCK_END
%=============================================================================
function varargout = renamevars(varargin)
narginchk(3, 3); % Check that there are exactly 3 input arguments
nargoutchk(0, 1); % Check that there is at most 1 output argument

% Unpack input arguments
T = varargin{1};
oldNames = varargin{2};
newNames = varargin{3};

% Ensure the types are correct
mustBeA(T, 'table', 1); % Check if T is a table
mustBeText(oldNames, 2); % Check if oldNames are text
mustBeText(newNames, 3); % Check if newNames are text

% Convert oldNames and newNames to cell arrays of strings
oldNames = cellstr(oldNames);
newNames = cellstr(newNames);

% Ensure oldNames and newNames are the same length
if (length(oldNames) ~= length(newNames))
error(_('oldNames and newNames must have the same length.'));
end

% Check for duplicates in oldNames
if (length(unique(oldNames)) ~= length(oldNames))
error('Duplicate names in oldNames are not allowed.');
end

% Check for duplicates in newNames
if (length(unique(newNames)) ~= length(newNames))
error('Duplicate names in newNames are not allowed.');
end

% Convert table to struct
st = struct(T);

% Get current fieldnames from st.data
currentFields = fieldnames(st.data);

% Check if all oldNames exist in the current fieldnames
for i = 1:length(oldNames)
if ~any(strcmp(oldNames{i}, currentFields))
error(sprintf(_('Name "%s" not found in the table.'), oldNames{i}));
end
end

% Create new struct for renamed fields
newData = struct();

% Copy and rename fields
for i = 1:length(currentFields)
currentField = currentFields{i};
idx = find(strcmp(currentField, oldNames));

if ~isempty(idx)
% If field should be renamed, use new name
newData.(newNames{idx}) = st.data.(currentField);
else
% If field is not in oldNames, keep original name
newData.(currentField) = st.data.(currentField);
end
end

% Replace old data struct with new one
st.data = newData;

% Update VariableNames in Properties
oldVarNames = st.Properties.VariableNames;
newVarNames = oldVarNames;
for i = 1:length(oldNames)
idx = strcmp(oldNames{i}, oldVarNames);
if any(idx)
newVarNames{idx} = newNames{i};
end
end
st.Properties.VariableNames = newVarNames;

varargout{1} = class(st, 'table');
end
82 changes: 82 additions & 0 deletions modules/table/help/en_US/xml/removevars.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xmldoc>
<copyright>SAME AS NELSON SOFTWARE</copyright>

<language>en_US</language>
<keyword>removevars</keyword>
<short_description>Delete variables from table.</short_description>

<syntax>
<syntax_item>TB = removevars(TA, varsNames)</syntax_item>
</syntax>

<param_input>

<param_input_item>
<param_name>TA</param_name>
<param_description>Input table.</param_description>
</param_input_item>
<param_input_item>
<param_name>varsNames</param_name>
<param_description
>Variable names in input table to remove: character vector, string array or cell array of character vectors.</param_description>
</param_input_item>

</param_input>

<param_output>
<param_output_item>
<param_name>TB</param_name>
<param_description>Table object modified.</param_description>
</param_output_item>
</param_output>

<description>
<p><b>TB = removevars(TA, varsNames)</b> removes the variables specified by <b
>varsNames</b> from the table <b
>TA</b> and stores the remaining variables in <b>T2</b>.</p>
<p
>You can specify the variables by name, position, or using logical indices.</p>
<p>You can also remove variables from a table using <b
>T(:, varsNames) = []</b>.</p>
</description>
<used_function />
<bibliography />

<examples>

<example_item>
<example_item_type>nelson</example_item_type>
<example_item_description />
<example_item_data
><![CDATA[C = {'John', 28, true; 'Alice', 35, false; 'Bob', 42, true};
% Convert the cell array to a table
T1 = cell2table(C)
T2 = removevars(T1, 'C2')
]]>
</example_item_data>
</example_item>

</examples>

<see_also>
<see_also_item>
<link linkend="${table}table">table</link>
</see_also_item>
<see_also_item>
<link linkend="${table}renamevars">renamevars</link>
</see_also_item>

</see_also>

<history>
<history_item>
<history_version>1.9.0</history_version>
<history_description>initial version</history_description>
</history_item>
</history>

<authors>
<author_item>Allan CORNET</author_item>
</authors>
</xmldoc>
94 changes: 94 additions & 0 deletions modules/table/help/en_US/xml/renamevars.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xmldoc>
<copyright>SAME AS NELSON SOFTWARE</copyright>

<language>en_US</language>
<keyword>renamevars</keyword>
<short_description>Rename variables in table.</short_description>

<syntax>
<syntax_item>TB = renamevars(TA, varsNames, newNames)</syntax_item>
</syntax>

<param_input>

<param_input_item>
<param_name>TA</param_name>
<param_description>Input table.</param_description>
</param_input_item>
<param_input_item>
<param_name>varsNames</param_name>
<param_description
>Variable names in input table: character vector, string array or cell array of character vectors.</param_description>
</param_input_item>
<param_input_item>
<param_name>newNames</param_name>
<param_description
>New names for variables: character vector, string array or cell array of character vectors.</param_description>
</param_input_item>

</param_input>

<param_output>
<param_output_item>
<param_name>TB</param_name>
<param_description
>Table object with variable names modified.</param_description>
</param_output_item>
</param_output>

<description>
<p><b
>TB = renamevars(TA, varsNames, newNames)</b> renames the variables in the table <b
>TA</b> as specified by <b
>varsNames</b> and assigns them the new names provided in <b
>newNames</b>.</p>
<p
>You can also rename all the variables in a table by assigning new names to its <b
>VariableNames</b> property using <b
>T.Properties.VariableNames = newNames</b>.</p>
<p>In this case, <b
>newNames</b> must be a string array or a cell array of character vectors.</p>
</description>
<used_function />
<bibliography />

<examples>

<example_item>
<example_item_type>nelson</example_item_type>
<example_item_description />
<example_item_data
><![CDATA[C = {'John', 28, true; 'Alice', 35, false; 'Bob', 42, true};
% Convert the cell array to a table
T1 = cell2table(C);
T2 = renamevars(T1, {'C1', 'C2'}, {'Name', 'Age'})
T3 = cell2table(C);
T3.Properties.VariableNames = {'Name', 'Age', 'Married'};
T3]]>
</example_item_data>
</example_item>

</examples>

<see_also>
<see_also_item>
<link linkend="${table}table">table</link>
</see_also_item>
<see_also_item>
<link linkend="${table}removevars">removevars</link>
</see_also_item>

</see_also>

<history>
<history_item>
<history_version>1.9.0</history_version>
<history_description>initial version</history_description>
</history_item>
</history>

<authors>
<author_item>Allan CORNET</author_item>
</authors>
</xmldoc>
27 changes: 27 additions & 0 deletions modules/table/tests/test_removars.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
%=============================================================================
% Copyright (c) 2016-present Allan CORNET (Nelson)
%=============================================================================
% This file is part of the Nelson.
%=============================================================================
% LICENCE_BLOCK_BEGIN
% SPDX-License-Identifier: LGPL-3.0-or-later
% LICENCE_BLOCK_END
%=============================================================================
LastName = {'Sanchez';'Johnson';'Li';'Diaz';'Brown'};
Age = [38;43;38;40;49];
Smoker = logical([1;0;1;0;1]);
Height = [71;69;64;67;64];
Weight = [176;163;131;133;119];
BloodPressure = [124 93; 109 77; 125 83; 117 75; 122 80];
T = table(LastName, Age, Smoker, Height, Weight, BloodPressure);
R = removevars(T, 'Age');
REF = table(LastName, Smoker, Height, Weight, BloodPressure);
assert_isequal(R, REF);
R2 = removevars(R, 1);
REF = table(Smoker, Height, Weight, BloodPressure);
assert_isequal(R2, REF);
%=============================================================================
R = removevars(T,{'Smoker','Weight'});
REF = table(LastName, Age, Height, BloodPressure);
assert_isequal(R, REF);
%=============================================================================
Loading

0 comments on commit 81b2c42

Please sign in to comment.