Logical indexing: Find row in table by text in column

a = {'hi', 'bye'; 'don', 'tcry' };
t = array2table(a);
u = t(t.a1 == 'don', :); % error: Undefined operator '==' for cell
How do I do a logical search for the row where a1 is 'bye'?
If it was numbers, it would be easy:
b = [1,2 ; 3,4];
q = array2table(b);
r = q(b1 == 3, :); # works perfectly
OK I found one way: Use string().
g = t(string(t.a1)=="don", :); % works! ;-)
Are there other ways, better ways, nicer ways?

댓글 수: 1

Stephen23
Stephen23 2018년 2월 6일
편집: Stephen23 2018년 2월 6일
"Are there other ways, better ways, nicer ways?"
Yes: use strcmp, strcmpi, etc. Do not use == for testing for string/character array equivalence.

댓글을 달려면 로그인하십시오.

 채택된 답변

Star Strider
Star Strider 2018년 2월 6일
To compare strings use the strcmp (link) or strcmpi function:
u = t(strcmp(t.a1, 'don'), :);
u =
1×2 table
a1 a2
_____ ______
'don' 'tcry'

댓글 수: 2

Just another way to use Star Strider's solution. If you want the index to the row containing your desired value,
iRow = find(strcmp(t.a1, 'don')==1);
Note that beginners tend to use find more than they should, you typically see:
indices = find(somearray == somevalue);
result = somerarray(indices);
where find wasn't needed at all and was just a waste of time:
isfound = somearray == somevalue;
result = somearray(isfound);
It's actually rare that you do need the indices.

댓글을 달려면 로그인하십시오.

추가 답변 (4개)

Guillaume
Guillaume 2018년 2월 6일
편집: Guillaume 2018년 2월 6일
Comparison of char arrays is always done with strcmp, never with ==. Thus:
u = t(strcmp(t.a1, 'don'), :)
The string class introduced in r2016b overloads == so that it can be used for comparison , so converting the char arrays to strings is indeed another solution.
Kristupas Karcemarskas
Kristupas Karcemarskas 2022년 4월 17일

1 개 추천

I found that it is really easy to use categorise() function
for example:
u=categorise(u);
Peter Perkins
Peter Perkins 2018년 2월 7일

0 개 추천

Two other things worth considering:
1) if {'hi', 'bye'; 'don', 'tcry'} are always unique, consider making them row names. Then t('don', :) is what you would use.
2) If {'hi', 'bye'; 'don', 'tcry'} could be a large list of repeated values, consider making them a categorical vector. Then u = t(t.a1 == 'don', :) is what you would use.
But even if those are not an option, if you are using R2016b or later, consider using a string array instead of a cellstr, as Guillaume says.

댓글 수: 2

1) Could you edit your answer and show how to make them row names?
2) Could you edit your answer and show how to make 'hi' and 'don' a categorical vector?
And in case 2 - two questions:
2a. Will I not get the same as I had with my original question? Reminder
u = t(t.a1 == 'don', :); % error: Undefined operator '==' for cell
2b. Will it be correct to use t.a1 == 'don' or should I use strcmp here too?
3. Just a last remark: Guillaume confirmed what I said and explained when and why it was made to work, but did not suggest it.
To make them row names, it's just
r.Properties.RowNames = t.a1;
t.a1 = []; % delete the original variable
but if the data are coming from a file you may well be able to read them in as row names. See the doc for readtable.
To make a categorical, it's just
t.a1 = categorical(t.a1)
but you will probably want to look over the documentation for categorical arrays. Once t.a1 is categorical, you can use ==. It's not the main reason for using categoricals, but it's a convenience (one that string also provides).

댓글을 달려면 로그인하십시오.

Gabor
Gabor 2021년 3월 3일

0 개 추천

b = [1,2 ; 3,4];
q = array2table(b);
r = q(b1 == 3, :);
Unrecognized function or variable 'b1'.

댓글 수: 1

b = [1,2 ; 3,4];
q = array2table(b);
r = q(q.b1 == 3, :);
This is how it works

댓글을 달려면 로그인하십시오.

카테고리

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by