ERROR while calculating Euclidean distances to multiple tables in cell array

40 ビュー (過去 30 日間)
lil brain
lil brain 2025 年 2 月 19 日 19:47
コメント済み: Voss 2025 年 2 月 20 日 18:32
I have this as my ost recent code:
%% Check for outliers in each table in each cell of C_all_steps and C_all_steps_no_break
% Load the saved C_all_steps files
load('C_all_steps.mat', 'C_all_steps', 'participant_ids');
load('C_all_steps_no_break.mat', 'C_all_steps_no_break', 'participant_ids_no_break');
% Initialize cell arrays to store cleaned data and outliers for both datasets
C_all_steps_cleaned = cell(size(C_all_steps)); % For cleaned data (filtered dataset)
C_all_steps_outliers = cell(size(C_all_steps)); % For removed outliers (filtered dataset)
C_all_steps_no_break_cleaned = cell(size(C_all_steps_no_break)); % For cleaned data (non-break dataset)
C_all_steps_no_break_outliers = cell(size(C_all_steps_no_break)); % For removed outliers (non-break dataset)
% Loop through each participant in the filtered dataset
for i = 1:size(C_all_steps, 1)
% Get participant ID (from filtered dataset)
participant_id = participant_ids(i);
% Loop through each step segment for the current participant
for j = 1:length(C_all_steps{i})
currentTable = C_all_steps{i}{j}; % Get the current step segment
% Check if the segment has any data
if isempty(currentTable)
C_all_steps_cleaned{i, j} = {}; % Store empty cell
C_all_steps_outliers{i, j} = {}; % Store empty cell
continue;
end
% Initialize logical array to track rows with outliers
outlierMask = false(height(currentTable), 1);
% Columns to check for outliers (15 to 35)
columnsToCheck = 15:35;
% Process each column for outliers
for col = columnsToCheck
if col <= width(currentTable)
% Extract column data
columnData = currentTable{:, col};
% Compute mean and standard deviation
meanValue = mean(columnData, 'omitnan');
stdDev = std(columnData, 'omitnan');
% Define the thresholds for outliers
thresholdHigh = meanValue + 3 * stdDev;
thresholdLow = meanValue - 3 * stdDev;
% Identify outliers in this column
isOutlier = columnData > thresholdHigh | columnData < thresholdLow;
% Update the overall outlier mask
outlierMask = outlierMask | isOutlier;
end
end
% Separate outliers from non-outliers
outliersInTable = currentTable(outlierMask, :);
cleanedInTable = currentTable(~outlierMask, :);
% Store results for this subsegment
C_all_steps_cleaned{i, j} = cleanedInTable;
C_all_steps_outliers{i, j} = outliersInTable;
end
end
% Loop through each participant in the non-break dataset
for i = 1:size(C_all_steps_no_break, 1)
% Get participant ID (from non-break dataset)
participant_id_no_break = participant_ids_no_break(i);
% Loop through each step segment for the current participant (non-break dataset)
for j = 1:length(C_all_steps_no_break{i})
currentTable = C_all_steps_no_break{i}{j}; % Get the current step segment
% Check if the segment has any data
if isempty(currentTable)
C_all_steps_no_break_cleaned{i, j} = {}; % Store empty cell
C_all_steps_no_break_outliers{i, j} = {}; % Store empty cell
continue;
end
% Initialize logical array to track rows with outliers
outlierMask = false(height(currentTable), 1);
% Columns to check for outliers (15 to 35)
columnsToCheck = 15:35;
% Process each column for outliers
for col = columnsToCheck
if col <= width(currentTable)
% Extract column data
columnData = currentTable{:, col};
% Compute mean and standard deviation
meanValue = mean(columnData, 'omitnan');
stdDev = std(columnData, 'omitnan');
% Define the thresholds for outliers
thresholdHigh = meanValue + 3 * stdDev;
thresholdLow = meanValue - 3 * stdDev;
% Identify outliers in this column
isOutlier = columnData > thresholdHigh | columnData < thresholdLow;
% Update the overall outlier mask
outlierMask = outlierMask | isOutlier;
end
end
% Separate outliers from non-outliers
outliersInTable = currentTable(outlierMask, :);
cleanedInTable = currentTable(~outlierMask, :);
% Store results for this subsegment (non-break dataset)
C_all_steps_no_break_cleaned{i, j} = cleanedInTable;
C_all_steps_no_break_outliers{i, j} = outliersInTable;
end
end
% Save cleaned and outlier data into .mat files for both datasets
save('C_all_steps_cleaned.mat', 'C_all_steps_cleaned', 'C_all_steps_outliers', 'participant_ids');
save('C_all_steps_no_break_cleaned.mat', 'C_all_steps_no_break_cleaned', 'C_all_steps_no_break_outliers', 'participant_ids_no_break');
I wanted to change this Euclidean distance code that I already have and apply it to both C_all_steps_cleaned and C_all_steps_no_break_cleaned.
%% Calculate distances for C_all_steps_no_break_cleaned
for i = 1:size(C_all_steps_no_break_cleaned, 1)
for j = 1:length(C_all_steps_no_break_cleaned{i})
current_segment = C_all_steps_no_break_cleaned{i,j};
C_distances_no_break_cleaned{i,j} = calculate_segment_distances(current_segment);
end
end
% Save the results to .mat files
save('C_distances_cleaned.mat', 'C_distances_cleaned', 'participant_ids');
save('C_distances_no_break_cleaned.mat', 'C_distances_no_break_cleaned', 'participant_ids_no_break');
function distances_table = calculate_segment_distances(T)
% Calculates distances for a single segment (cell array of tables)
% Input: T - A cell array of tables (a segment from C_all_steps_cleaned or C_all_steps_no_break_cleaned)
% Output: distances_table - A cell array of distance tables corresponding to each table in T
distances_table = cell(size(T)); % Initialize output cell array
for k = 1:length(T) % Loop through the tables in the current segment
currentTable_cleaned = T{k};
if isempty(currentTable_cleaned)
distances_table{k} = []; % Store empty array if table is empty
continue;
end
X1 = currentTable_cleaned{:, 15};
Y1 = currentTable_cleaned{:, 16};
Z1 = currentTable_cleaned{:, 17};
X2 = currentTable_cleaned{:, 22};
Y2 = currentTable_cleaned{:, 23};
Z2 = currentTable_cleaned{:, 24};
X3 = currentTable_cleaned{:, 29};
Y3 = currentTable_cleaned{:, 30};
Z3 = currentTable_cleaned{:, 31};
if height(currentTable_cleaned) > 1
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table{k} = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
else
distances_table{k} = table();
end
end
end
But I always get the following error:
Error using tabular/length
Undefined function 'LENGTH' for input arguments of type 'table'. Use the height, width, or size functions instead.
Error in Copy_task_19022025 (line 302)
for j = 1:length(C_all_steps_no_break_cleaned{i})
Any idea how to solve this?

採用された回答

Voss
Voss 2025 年 2 月 19 日 21:40
C_all_steps_no_break_cleaned = load('C_all_steps_no_break_cleaned.mat').C_all_steps_no_break_cleaned
C_all_steps_no_break_cleaned = 3x8 cell array
{ 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} {1987x36 table } {488x36 table } {1945x36 table } {1749x36 table } {1493x36 table } {1315x36 table } {1456x36 table } {28x36 table } { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double}
The important point understanding and resolving the error is that C_all_steps_no_break_cleaned is a 2d cell array, so to iterate over each element of it you can iterate over rows (i) and columns (j) and index with (i,j) (or {i,j} as the case may be).
Example, using the original calculate_segment_distances function:
%% Calculate distances for C_all_steps_no_break_cleaned
[M,N] = size(C_all_steps_no_break_cleaned);
C_distances_no_break_cleaned = cell(M,N);
for i = 1:M
for j = 1:N
current_segment = C_all_steps_no_break_cleaned(i,j);
C_distances_no_break_cleaned{i,j} = calculate_segment_distances(current_segment);
end
end
C_distances_no_break_cleaned
C_distances_no_break_cleaned = 3x8 cell array
{1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell}
Another example, using an adjusted function calculate_segment_distances_new, which takes a table (rather than a cell array of tables) as input and returns a table (rather than a cell array of tables) as output, which might make more sense in this case, since only a scalar cell array of tables is ever passed in/out:
%% Calculate distances for C_all_steps_no_break_cleaned
[M,N] = size(C_all_steps_no_break_cleaned);
C_distances_no_break_cleaned = cell(M,N);
for i = 1:M
for j = 1:N
current_segment = C_all_steps_no_break_cleaned{i,j};
C_distances_no_break_cleaned{i,j} = calculate_segment_distances_new(current_segment);
end
end
C_distances_no_break_cleaned
C_distances_no_break_cleaned = 3x8 cell array
{ 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} {1986x2 table } {487x2 table } {1944x2 table } {1748x2 table } {1492x2 table } {1314x2 table } {1455x2 table } {27x2 table } { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double}
Of course, you don't have to have two loops, one for rows and one for columns; you can iterate over each element using linear indexing, e.g.:
%% Calculate distances for C_all_steps_no_break_cleaned
siz = size(C_all_steps_no_break_cleaned);
C_distances_no_break_cleaned = cell(siz);
for i = 1:prod(siz)
current_segment = C_all_steps_no_break_cleaned{i};
C_distances_no_break_cleaned{i} = calculate_segment_distances_new(current_segment);
end
C_distances_no_break_cleaned
C_distances_no_break_cleaned = 3x8 cell array
{ 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} {1986x2 table } {487x2 table } {1944x2 table } {1748x2 table } {1492x2 table } {1314x2 table } {1455x2 table } {27x2 table } { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double} { 0x0 double}
function distances_table = calculate_segment_distances(T)
% Calculates distances for a single segment (cell array of tables)
% Input: T - A cell array of tables (a segment from C_all_steps_cleaned or C_all_steps_no_break_cleaned)
% Output: distances_table - A cell array of distance tables corresponding to each table in T
distances_table = cell(size(T)); % Initialize output cell array
for k = 1:length(T) % Loop through the tables in the current segment
currentTable_cleaned = T{k};
if isempty(currentTable_cleaned)
distances_table{k} = []; % Store empty array if table is empty
continue;
end
X1 = currentTable_cleaned{:, 15};
Y1 = currentTable_cleaned{:, 16};
Z1 = currentTable_cleaned{:, 17};
X2 = currentTable_cleaned{:, 22};
Y2 = currentTable_cleaned{:, 23};
Z2 = currentTable_cleaned{:, 24};
X3 = currentTable_cleaned{:, 29};
Y3 = currentTable_cleaned{:, 30};
Z3 = currentTable_cleaned{:, 31};
if height(currentTable_cleaned) > 1
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table{k} = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
else
distances_table{k} = table();
end
end
end
function distances_table = calculate_segment_distances_new(T)
% Calculates distances for a single segment (table T)
% Input: T - A table (a segment from C_all_steps_cleaned or C_all_steps_no_break_cleaned)
% Output: distances_table - A table corresponding to T
if isempty(T)
distances_table = [];
return
elseif height(T) <= 1
distances_table = table();
return
end
X1 = T{:, 15};
Y1 = T{:, 16};
Z1 = T{:, 17};
X2 = T{:, 22};
Y2 = T{:, 23};
Z2 = T{:, 24};
X3 = T{:, 29};
Y3 = T{:, 30};
Z3 = T{:, 31};
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
end
  3 件のコメント
lil brain
lil brain 2025 年 2 月 20 日 13:25
Oh I think I got it by just combining the two like so:
%% Calculate distances for C_all_steps_no_break_cleaned
siz = size(C_all_steps_no_break_cleaned);
C_distances_no_break_cleaned = cell(siz);
for i = 1:prod(siz)
current_segment = C_all_steps_no_break_cleaned{i};
C_distances_no_break_cleaned{i} = calculate_segment_distances_new(current_segment);
end
C_distances_no_break_cleaned
%% Calculate distances for C_all_steps_cleaned
siz = size(C_all_steps_cleaned);
C_distances_cleaned = cell(siz);
for i = 1:prod(siz)
current_segment = C_all_steps_cleaned{i};
C_distances_cleaned{i} = calculate_segment_distances_new(current_segment);
end
C_distances_cleaned
%% Function Definitions (Must be at the end of the script)
function distances_table = calculate_segment_distances(T)
% Calculates distances for a single segment (cell array of tables)
% Input: T - A cell array of tables
% Output: distances_table - A cell array of distance tables
distances_table = cell(size(T)); % Initialize output cell array
for k = 1:length(T) % Loop through tables
currentTable_cleaned = T{k};
if isempty(currentTable_cleaned)
distances_table{k} = []; % Store empty array if table is empty
continue;
end
X1 = currentTable_cleaned{:, 15};
Y1 = currentTable_cleaned{:, 16};
Z1 = currentTable_cleaned{:, 17};
X2 = currentTable_cleaned{:, 22};
Y2 = currentTable_cleaned{:, 23};
Z2 = currentTable_cleaned{:, 24};
X3 = currentTable_cleaned{:, 29};
Y3 = currentTable_cleaned{:, 30};
Z3 = currentTable_cleaned{:, 31};
if height(currentTable_cleaned) > 1
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table{k} = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
else
distances_table{k} = table();
end
end
end
function distances_table = calculate_segment_distances_new(T)
% Calculates distances for a single segment (table T)
% Input: T - A table
% Output: distances_table - A table corresponding to T
if isempty(T)
distances_table = [];
return
elseif height(T) <= 1
distances_table = table();
return
end
X1 = T{:, 15};
Y1 = T{:, 16};
Z1 = T{:, 17};
X2 = T{:, 22};
Y2 = T{:, 23};
Z2 = T{:, 24};
X3 = T{:, 29};
Y3 = T{:, 30};
Z3 = T{:, 31};
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
end
Voss
Voss 2025 年 2 月 20 日 18:32
Yes, in your version of MATLAB, all function definitions in a script must be at the end.
Note that calculate_segment_distances is not called in the script in your most recent comment, so you could remove it if calculate_segment_distances_new does what you want. I wrote the new one because I wasn't sure if the old one was working as you intended.

サインインしてコメントする。

その他の回答 (1 件)

Walter Roberson
Walter Roberson 2025 年 2 月 19 日 20:01
Use
for j = 1:width(C_all_steps_no_break{i})
  1 件のコメント
lil brain
lil brain 2025 年 2 月 19 日 20:05
編集済み: lil brain 2025 年 2 月 19 日 20:12
This doesnt work for me. I now get this error:
Error using {}
Subscripting into a table using one subscript (as in t(i)) is not supported. Specify a row subscript and a variable subscript, as in t(rows,vars). To select variables, use
t(:,i) or for one variable t.(i). To select rows, use t(i,:).
Error in Copy_task_19022025>calculate_segment_distances (line 323)
currentTable_cleaned = T{k};
Error in Copy_task_19022025 (line 304)
C_distances_no_break_cleaned{i,j} = calculate_segment_distances(current_segment);
When using the adjusted code like you suggested:
%% Calculate distances for C_all_steps_no_break_cleaned
for i = 1:size(C_all_steps_no_break_cleaned, 1)
for j = 1:width(C_all_steps_no_break_cleaned{i})
current_segment = C_all_steps_no_break_cleaned{i,j};
C_distances_no_break_cleaned{i,j} = calculate_segment_distances(current_segment);
end
end
% Save the results to .mat files
save('C_distances_cleaned.mat', 'C_distances_cleaned', 'participant_ids');
save('C_distances_no_break_cleaned.mat', 'C_distances_no_break_cleaned', 'participant_ids_no_break');
function distances_table = calculate_segment_distances(T)
% Calculates distances for a single segment (cell array of tables)
% Input: T - A cell array of tables (a segment from C_all_steps_cleaned or C_all_steps_no_break_cleaned)
% Output: distances_table - A cell array of distance tables corresponding to each table in T
distances_table = cell(size(T)); % Initialize output cell array
for k = 1:width(T) % Loop through the tables in the current segment
currentTable_cleaned = T{k};
if isempty(currentTable_cleaned)
distances_table{k} = []; % Store empty array if table is empty
continue;
end
X1 = currentTable_cleaned{:, 15};
Y1 = currentTable_cleaned{:, 16};
Z1 = currentTable_cleaned{:, 17};
X2 = currentTable_cleaned{:, 22};
Y2 = currentTable_cleaned{:, 23};
Z2 = currentTable_cleaned{:, 24};
X3 = currentTable_cleaned{:, 29};
Y3 = currentTable_cleaned{:, 30};
Z3 = currentTable_cleaned{:, 31};
if height(currentTable_cleaned) > 1
distances_X1_X2 = sqrt((X2(2:end) - X1(1:end-1)).^2 + (Y2(2:end) - Y1(1:end-1)).^2 + (Z2(2:end) - Z1(1:end-1)).^2);
distances_X1_X3 = sqrt((X3(2:end) - X1(1:end-1)).^2 + (Y3(2:end) - Y1(1:end-1)).^2 + (Z3(2:end) - Z1(1:end-1)).^2);
distances_table{k} = table(distances_X1_X2, distances_X1_X3, 'VariableNames', {'X1_X2_Distance', 'X1_X3_Distance'});
else
distances_table{k} = table();
end
end
end

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeDictionaries についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by