現在この質問をフォロー中です
- フォローしているコンテンツ フィードに更新が表示されます。
- コミュニケーション基本設定に応じて電子メールを受け取ることができます。
How to split into different tables a multi-level cell?
3 ビュー (過去 30 日間)
古いコメントを表示
My final goal is to have a 428x11 table from an image analysis that I ran which final outcome is 'data'. Object 'data' is a 428x1 cell, and that one column is a 1x11 cell that looks like ['name', v1, v2, v3, v4, v5, 6, v7, v8, V9, v10], and again, 428 times.
I have tried using data_table=regexp(data(:), '\s+', 'split'); but get an error using regexp 'All cells must be char row vectors.', and tried with 'cellstr' but didn't work. I have also tried with loops -although I am not proficient with iterations- but I can't index with multi-level cells, and something like data2=data{2:end,1}{1,1}; or data2=data{:,1}{:,1}; hasn't worked. I have seen similar questions in but MATLAB Answers haven't worked for me so far.
I really appreciate any help!
採用された回答
per isakson
2017 年 12 月 2 日
編集済み: per isakson
2017 年 12 月 2 日
"final goal is to have a 428x11 table"
Study this
data = {
{'name1',1,2,3,4,5,6,7,8,9,0}
{'name2',1,2,3,4,5,6,7,8,9,0}
{'name3',1,2,3,4,5,6,7,8,9,0}
};
cac = cat( 1, data{:} );
mytable = cell2table( cac )
it displays in the command window
mytable =
cac1 cac2 cac3 cac4 cac5 cac6 cac7 cac8 cac9 cac10 cac11
_______ ____ ____ ____ ____ ____ ____ ____ ____ _____ _____
'name1' 1 2 3 4 5 6 7 8 9 0
'name2' 1 2 3 4 5 6 7 8 9 0
'name3' 1 2 3 4 5 6 7 8 9 0
12 件のコメント
JoanManBar
2017 年 12 月 2 日
Thank you so much for your answer. It actually worked with YOUR sample matrix but not with my data. However it's getting close since it creates a 242x11 table. So I wonder what I am doing wrong. I am sharing my cell in case you want to take a closer look. Thank you once again!
per isakson
2017 年 12 月 3 日
編集済み: per isakson
2017 年 12 月 3 日
- "it creates a 242x11 table" thus the two lines of code do what they are supposed to do
- "what I am doing wrong" I cannot see any requirement besides "242x11 table" and that is fulfilled. What do you further require? What do you want to achieve? You don't say.
>> load('matlab.mat')
>> cac = cat( 1, data{:} );
mytable = cell2table( cac )
mytable =
cac1 cac2 cac3 cac4 cac5 cac6 cac7 cac8 cac9 cac10 cac11
_______________ ____ ______ ______ ______ ____ ______ ______ ______ ______ ______
'sample006.tif' 71 172.31 138.36 112.3 2570 130.46 25.35 172.31 138.36 112.3
'sample026.tif' 116 168.1 134.01 106.86 952 68.517 17.91 168.1 134.01 106.86
'sample223.tif' 96 163.64 137.07 115.81 1293 83.787 20.473 163.64 137.07 115.81
'sample231.tif' 107 178.36 150.75 127.69 2283 115.56 25.323 178.36 150.75 127.69
'sample006.tif' 71 172.31 138.36 112.3 2570 130.46 25.35 172.31 138.36 112.3
'sample223.tif' 96 163.64 137.07 115.81 1293 83.787 20.473 163.64 137.07 115.81
'sample006.tif' 71 172.31 138.36 112.3 2570 130.46 25.35 172.31 138.36 112.3
'sample231.tif' 107 178.36 150.75 127.69 2283 115.56 25.323 178.36 150.75 127.69
'sample223.tif' 96 163.64 137.07 115.81 1293 83.787 20.473 163.64 137.07 115.81
'sample026.tif' 116 168.1 134.01 106.86 952 68.517 17.91 168.1 134.01 106.86
...
Speculations: The cell array data isn't what you think it is. There are only four unique row headers, i.e. file names in data
>> col1 = cac(:,1);
>> length(col1)
ans =
242
>> [ col1_unique, ixa, ixc ] = unique( col1 );
>> col1_unique
col1_unique =
'sample006.tif'
'sample026.tif'
'sample223.tif'
'sample231.tif'
>>
Actually, there are only four unique rows
>> [ cac_unique_rows, ixa, ixc ] = unique_rows( cac, [1:size(cac,2)] );
>> cac_unique_rows
cac_unique_rows =
'sample006.tif' [ 71] [172.3078] [138.3623] [112.3047] [2570] [130.4569] [25.3503] [172.3078] [138.3623] [112.3047]
'sample026.tif' [116] [168.1040] [134.0053] [106.8592] [ 952] [ 68.5168] [17.9097] [168.1040] [134.0053] [106.8592]
'sample223.tif' [ 96] [163.6419] [137.0719] [115.8105] [1293] [ 83.7872] [20.4729] [163.6419] [137.0719] [115.8105]
'sample231.tif' [107] [178.3574] [150.7464] [127.6881] [2283] [115.5610] [25.3232] [178.3574] [150.7464] [127.6881]
JoanManBar
2017 年 12 月 3 日
編集済み: per isakson
2017 年 12 月 5 日
More than just an answer, this was a meaningful lesson! You are right, my data cell was completely wrong, and although I still don't accomplish my objective (sheet with RGB and size of my seeds), you answered wisely the question I asked. I am still struggling really bad to learn the basics of Matlab.
I know I have already asked a lot, but if you would still like to help me, all that I want is my files' names in each corresponding row, i.e. 'sample..' instead of numbers from 1 to number of files -I know that's a different question.
I am attaching my code and files anyways.
.
.
Two copies removed
.
close all; clear all; clc;
imagefiles = dir('*.tif');
filenames = {imagefiles.name};
nfiles = length(imagefiles);
for i=1:nfiles
currentfilename = imagefiles(i).name;
currentimage = imread(currentfilename);
images = currentimage;
images = imcrop(images, [0 0 1557 1844]);
Red_ch = images(:,:,1);
Green_ch = images(:,:,2);
Blue_ch = images(:,:,3);
binary = Red_ch > 90;
binary = bwareafilt(binary, [100, inf]);
se = strel('disk',7,0);
binary = imerode(binary, se);
[labeledI, numSeeds] = bwlabel(binary);
props = regionprops(labeledI, 'Area', 'MajorAxisLength',
'MinorAxisLength');
for k = 1:numSeeds
Areas(k) = props(k).Area;
Length(k) = props(k).MajorAxisLength;
Width(k) = props(k).MinorAxisLength;
end
propsR = regionprops(labeledI, Red_ch, 'MeanIntensity',
'PixelValues');
propsG = regionprops(labeledI, Green_ch, 'MeanIntensity',
'PixelValues');
propsB = regionprops(labeledI, Blue_ch, 'MeanIntensity',
'PixelValues');
MeansR = [propsR.MeanIntensity];
MeansG = [propsG.MeanIntensity];
MeansB = [propsB.MeanIntensity];
for j = 1:numSeeds
PixMeansR(j) = mean(propsR(j).PixelValues);
PixMeansR = PixMeansR';
PixMeansG(j) = mean(propsG(j).PixelValues);
PixMeansG = PixMeansG';
PixMeansB(j) = mean(propsB(j).PixelValues);
PixMeansB = PixMeansB';
end
if exist('data','var')~=1
data = [repmat(i,1,numSeeds)', (1:numSeeds)', MeansR', MeansG',
MeansB', Areas', Length', Width', filenames];
else
data = vertcat(data,[repmat(i,1,numSeeds)', (1:numSeeds)',
MeansR', MeansG', MeansB', Areas', Length', Width']);
end
end
THANK YOU SO MUCH!
per isakson
2017 年 12 月 4 日
編集済み: per isakson
2017 年 12 月 4 日
I assume your question is about
if exist('data','var')~=1
data = [repmat(i,1,numSeeds)', (1:numSeeds)', MeansR', MeansG', ...
MeansB', Areas', Length', Width', filenames];
else
data = vertcat(data,[repmat(i,1,numSeeds)', (1:numSeeds)', ...
MeansR', MeansG', MeansB', Areas', Length', Width']);
end
In the second iteration of the loop, when the else-clause is executed for the first time, I get the error
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in cssm (line 57)
data = vertcat(data,[repmat(i,1,numSeeds)', (1:numSeeds)', ...
which shouldn't surprise.
Comments on this if-else-end construct
- it attempts to create a cell array, data, which differs from data that you uploaded in the mat-file. E.g. MeanR ... in the uploaded data are scalars, here they are vectors with one element per seed.
- In the uploaded data the format of the first row didn't differ from the rest. It might be a good idea to show column headers in the first row, e.g. ...,'MeansR','MeansG','MeansB','Areas','Length','Width',...
- this construct is inefficient and hard to read. The numbers of files is known, thus pre-allocating the cell array, data = cell( nfiles, 12 );, and use assignments to fill it with data.
I'm lost. Show with an example what data shall look like.
JoanManBar
2017 年 12 月 4 日
I am so sorry, I feel like I'm wasting your time and that's because I haven't been clear at all. The previous code was a little different that the second one since I realized -thank to you- that the array was not what I thought it was. Additionally, the second I uploaded was had mistakes as well. I honestly don't know what to do!
Dear Per Isakson, I want to have a spread sheet that shows these columns and their corresponding values:
Image_Name, Seed, Mean_Red, Mean_Green, Mean_Blue, Area, Length, Width
Where:
Image_Name: Name of each photo
Seed: Number of seeds per photo
Mean_Red: Mean red value of each seed
Mean_Green: Mean green value of each seed
Mean_Blue: Mean blue value of each seed
Area: Area of each seed
Length: Length of each seed
Width: Width of each seed
I'd like to have other variables, but that would be more than enough. How can I do that?
Thank you once again, I really appreciate all the time and help you have provided.
per isakson
2017 年 12 月 4 日
編集済み: per isakson
2017 年 12 月 4 日
There is a serious problem with this loop and a couple of minor.
for k = 1:numSeeds
Areas(k) = props(k).Area;
Length(k) = props(k).MajorAxisLength;
Width(k) = props(k).MinorAxisLength;
end
- When the outer loop encounters a picture with fewer seeds than the previous the values at the end of Areas etc. will not be overwritten. The length of Areas etc. will increase down the table. Pictures with few seeds will give entries in the table with data on seeds of previous pictures.
- pre-allocation of memory is a good habit.
- The generic names, e.g. Length, make me nervous. There is a risk, they are in conflict with names used by Matlab.
per isakson
2017 年 12 月 4 日
編集済み: per isakson
2017 年 12 月 4 日
First I downloaded the picture and made an extra copy of sample006.tif, which I called sample.306.tif. (I was surprised that three pictures contained exactly 112 seeds. Ok, it's copies of the same picture.)
Then I modified your code.
Now the question is whether the result is what you expected.
>> data = cssm()
data =
'Image_Name' 'Seed' 'Mean_Red' 'Mean_Green' 'Mean_Blue' 'Area' 'Length' 'Width'
'sample006.tif' [ 69] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double]
'sample026.tif' [ 112] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample223.tif' [ 112] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample231.tif' [ 112] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample306.tif' [ 69] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double]
where
function data = cssm()
%#ok<*AGROW>
%#ok<*NASGU>
%#ok<*ASGLU>
imagefiles = dir('sample*.tif');
filenames = {imagefiles.name};
nfiles = length(imagefiles);
%
data = cell( nfiles+1, 8 );
data(1,:) = { 'Image_Name','Seed','Mean_Red','Mean_Green' ...
, 'Mean_Blue' ,'Area','Length' ,'Width' };
%
for i=1:nfiles
currentimage = imread( imagefiles(i).name );
%
Red_ch = currentimage(:,:,1);
Green_ch = currentimage(:,:,2);
Blue_ch = currentimage(:,:,3);
%
binary = Red_ch > 90;
binary = bwareafilt(binary, [100, inf]);
se = strel('disk',7,0);
binary = imerode(binary, se);
%
[labeledI, numSeeds] = bwlabel(binary);
%
props = regionprops(labeledI,'Area','MajorAxisLength','MinorAxisLength');
%
Areas = reshape([props.Area] , [], 1 );
Length = reshape([props.MajorAxisLength], [], 1 );
Width = reshape([props.MinorAxisLength], [], 1 );
%
propsR = regionprops(labeledI, Red_ch, 'MeanIntensity', 'PixelValues');
propsG = regionprops(labeledI, Green_ch, 'MeanIntensity', 'PixelValues');
propsB = regionprops(labeledI, Blue_ch, 'MeanIntensity', 'PixelValues');
%
MeansR = reshape([propsR.MeanIntensity], [], 1 );
MeansG = reshape([propsG.MeanIntensity], [], 1 );
MeansB = reshape([propsB.MeanIntensity], [], 1 );
%
data(i+1,:) = { imagefiles(i).name, numSeeds ...
, MeansR, MeansG, MeansB ...
, Length, Areas, Width };
end
end
Comments:
- I have problems with the blip as a shortcut for transpose. I prefer reshape, because the name is good and reshape outputs the desired shape regardless of whether the input is row or column.
- I removed some help-variables, which I didn't think added any value.
- I vectorized the loops over numSeeds.
- I removed the crop-command to simplify testing.
per isakson
2017 年 12 月 4 日
And finally
>> mytable = cell2table( data(2:end,:), 'VariableNames', data(1,:) )
mytable =
Image_Name Seed Mean_Red Mean_Green Mean_Blue Area Length Width
_______________ ____ ______________ ______________ ______________ ______________ ______________ ______________
'sample006.tif' 69 [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double]
'sample026.tif' 112 [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample223.tif' 112 [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample231.tif' 112 [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double] [112x1 double]
'sample306.tif' 69 [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double] [ 69x1 double]
JoanManBar
2017 年 12 月 4 日
Today is one of the best days of my life thanks to you! I can't believe it finally works! And I can't tell with words how grateful I feel with you!
I realized that I uploaded the wrong images and that's why three of them have the same results. I apologize!
Would you mind doing one last thing for me? Could you please tell me how the first column (Image_Name) can have the sample name repeated in rows as many times as there is seeds?
If there is anything I can do for you, please let me know!
THANKS A LOT!
per isakson
2017 年 12 月 5 日
Here is a function, which takes the cell array data from above and returns the table you want (I think). In this table there is one row per seed. There are no row names.
I find it most rewarding to learn that I really helped you.
My functions lack both comments and error checking. I encourage you to try to understand the code and add some.
>> out_tbl = cssm2( data )
out_tbl =
Image_Name Seed Mean_Red Mean_Green Mean_Blue Area Length Width
_______________ ____ ________ __________ _________ ______ ______ ______
'sample006.tif' 1 171.83 137.49 111.47 122.38 2117 22.299
'sample006.tif' 2 170.82 134.89 109.36 117.08 1800 20.107
'sample006.tif' 3 178.06 145.43 115.19 129.65 5976 82.874
'sample006.tif' 4 153.78 118.21 89.604 128.57 3121 31.13
'sample006.tif' 5 171.72 141.22 116.84 124.48 1920 20.122
...
...
>> whos out_tbl data
Name Size Bytes Class Attributes
data 6x8 28410 cell
out_tbl 474x8 95114 table
where
function out_tbl = cssm2( data )
%
colhead = data( 1, : );
out_tbl = one_batch_of_seeds_to_table( data(2,:), colhead );
%
for jj = 3 : size( data, 1 )
tbl = one_batch_of_seeds_to_table( data(jj,:), colhead );
out_tbl = vertcat( out_tbl, tbl ); %#ok<AGROW>
end
end
and where
function tbl = one_batch_of_seeds_to_table( body, colhead )
%
len = length( body{3} );
pic = repmat( body(1), len, 1 );
sno = reshape( (1:len), [], 1 );
tbl = table( pic, sno, body{3:end}, 'VariableNames', colhead );
end
JoanManBar
2017 年 12 月 6 日
Once again, thank you very much! I'm having some trouble with that last part since 'body' is not defined but I think it's time for me to stop bothering you and do the work myself.
I have learned more from your answers than from my experience reading the MATLAB documentation and I really appreciate that.
その他の回答 (0 件)
参考
カテゴリ
Help Center および File Exchange で Matrix Indexing についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!エラーが発生しました
ページに変更が加えられたため、アクションを完了できません。ページを再度読み込み、更新された状態を確認してください。
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
アジア太平洋地域
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)