ERROR while calculating Euclidean distances to multiple tables in cell array
40 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
採用された回答
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
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 件のコメント
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 件)
参考
カテゴリ
Help Center および File Exchange で Dictionaries についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!