In a cell how do I extract a specific range of values from a few columns that have a certain value in another column?
2 ビュー (過去 30 日間)
古いコメントを表示
I'm quite new to MATLAB so apologies if my question is a bit confusing.
I have a cell with subject names in the first column, time points in the second column and experiment values in the third column:
Bob 1 100
Bob 3 200
Bob 4 500
Bill 1 200
Bill 2 300
Bill 5 600
I want to create a struct with 2 fields using this cell; the first with the subjects name and the second field with a matrix that has the time and experiment values for that subject. For example, for the above cell I want it to make a 1x2 struct with 2 fields with the first entry being:
Name: 'Bob'
Values: [1,100 ; 3,200 ; 4,500]
And the seecond entry in the struct being:
Name: 'Bill'
Values: [1,200 ; 2,300 ; 5,600]
0 件のコメント
採用された回答
Stephen23
2016 年 8 月 5 日
編集済み: Stephen23
2016 年 8 月 5 日
This method will correctly preserve the order of the input data:
C = {...
'Bob',1,100;
'Bob',3,200;
'Bob',4,500;
'Bill',1,200;
'Bill',2,300;
'Bill',5,600;
'Bob',8,1000;
'Anna',2,900;
'Anna',9,000;
};
[uni,idx,idy] = unique(C(:,1),'stable');
mat = cell2mat(C(:,2:3));
[idy,idz] = sort(idy);
tmp = accumarray(idy,idz,[],@(r){mat(r,:)});
S = struct('name',uni,'values',tmp)
And checking:
for k = 1:numel(S) S(k).name S(k).values end
prints:
ans =
Bob
ans =
1 100
3 200
4 500
8 1000
ans =
Bill
ans =
1 200
2 300
5 600
ans =
Anna
ans =
2 900
9 0
その他の回答 (3 件)
Guillaume
2016 年 8 月 5 日
編集済み: Guillaume
2016 年 8 月 5 日
If I understood correctly:
c ={'Bob', 1, 100; 'Bob', 3, 200; 'Bob', 4, 500; 'Bill', 1, 200; 'Bill', 2, 300; 'Bill', 5 , 600};
[names, ~, rows] = unique(c(:, 1));
allvalues = cell2mat(c(:, 2:end));
%%option 1: group using splitapply, R2015b or later
values = splitapply(@(row) {row}, allvalues, rows);
%%option 2: group using accumarray, any version
values = accumarray(rows, (1:size(c, 1))', [], @(row) {allvalues(row, :)});
s = struct('Names', names, 'Values', values)
The splitapply (requires R2015b or later) syntax is simpler as you need to subvert accumarray to make it work on several columns at once. On the other hand accumarray is probably faster as it's a compiled function whereas splitapply is a just a plain m file.
3 件のコメント
Guillaume
2016 年 8 月 5 日
編集済み: Guillaume
2016 年 8 月 5 日
Yes, accumarray does not preserve the order. In my limited testing, splitapply appears to, but it's not guaranteed by the function.
However, I assumed that the order of the entries did not matter (why should they?). If an ordering does matter, why should it be the order of the original cell array instead of a time ordering? The latter can be simply achieved with:
%...
values = splitapply(@(row) {row}, allvalues, rows); %or using accumarray
values = cellfun(@sortrows, values, 'UniformOutput', false);
%... construct struct as normal
Thorsten
2016 年 8 月 5 日
You can also achieve this without accumarray or splitat, using a for-loop.
c ={'Bob', 1, 100; 'Bob', 3, 200; 'Bob', 4, 500; 'Bill', 1, 200; 'Bill', 2, 300; 'Bill', 5 , 600};
[names, ~, rows] = unique(c(:, 1));
allvalues = cell2mat(c(:, 2:end));
for i = 1:numel(names)
S(i).name = names{i};
S(i).values = allvalues(strcmp(c(:,1), names{i}), :);
end
Bekay.Kang
2016 年 8 月 5 日
編集済み: Guillaume
2016 年 8 月 5 日
hello mdon.
hope this will be helpful for you !
struct_you_want=struct('Name',cell_data(:,1),'Value',cell2mat(cell_data(:,2:3)));
:)
2 件のコメント
Guillaume
2016 年 8 月 5 日
I believe mdon wants all entries with the same name to be regrouped. The above won't do that.
参考
カテゴリ
Help Center および File Exchange で Structures についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!