ERROR while calculating Euclidean distances to multiple tables in cell array
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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?
0 commentaires
Réponse acceptée
Voss
le 19 Fév 2025
C_all_steps_no_break_cleaned = load('C_all_steps_no_break_cleaned.mat').C_all_steps_no_break_cleaned
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
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
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
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 commentaires
Voss
le 20 Fév 2025
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.
Plus de réponses (1)
Voir également
Catégories
En savoir plus sur Dictionaries dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!