이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
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!오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 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 (한국어)