readtable not reading logical values as expected
조회 수: 13 (최근 30일)
이전 댓글 표시
I am using version 9.9.0.1592791 (R2020b) Update 5.
I found this behavior while reading and writing tables via readtable() and writetable().
% First, I make a table and write it to file:
myint = 1;
mychar = {'1'};
mybool = true;
t = table();
t = addvars(t, myint);
t = addvars(t, mychar);
t = addvars(t, mybool)
writetable(t, 'mytable.csv');
% This gives the table t:
%{
t =
1×3 table
myint mychar mybool
_____ ______ ______
1 {'1'} true
%}
% and the .csv file:
%{
myint,mychar,mybool
1,1,1
%}
% Note that "true" is written as a "1" as is expected
% Now, I try to read the table, properly setting the options:
opts = detectImportOptions('mytable.csv');
opts = setvartype(opts,'myint','int8');
opts = setvartype(opts,'mychar','char');
opts = setvartype(opts,'mybool','logical');
t = readtable('mytable.csv',opts)
% Instead of the expected result of getting a table with values 1 (as an integer), "1" (as a char), and true (logical), I get:
%{
t =
1×3 table
myint mychar mybool
_____ ______ ______
1 {'1'} false
%}
% When I change my file to:
%{
myint,mychar,mybool
1,1,true
%}
% readtable() reads the data as expected, giving:
%{
t =
1×3 table
int char bool
___ _____ _____
1 {'1'} true
%}
Why is this happening? This is unexpected, especially considering that writetable writes logical values as '0' and '1'. Is this expected or is this a bug?
Note: When I use .xls instead of .csv, it behaves as expected.
댓글 수: 1
Adam Danz
2021년 8월 10일
편집: Adam Danz
2021년 8월 10일
Same behavior in R2021a. This is unexpected.
You should report this to tech support: Contact Us - MATLAB & Simulink
As a workaround, read in the logical column as double as then convert to logical.
opts = setvartype(opts,'mybool','double');
t = readtable('mytable.csv',opts);
t.mybool = logical(t.mybool);
채택된 답변
Jeremy Hughes
2021년 8월 10일
편집: Jeremy Hughes
2021년 8월 10일
The default results of detectImportOptions seeing "1" & "0" will be numeric, and the default logical reading expects "true","t" or "false","f" (case insensitive), but this is overridable.
T = array2table(randn(6,3)>0)
writetable(T,"mytable.csv","WriteVariableNames",false)
opts = delimitedTextImportOptions("NumVariables",3,...
"VariableNames",["myint","mychar","mybool"],...
"VariableTypes",["int8","char","logical"]);
getvaropts(opts,'mybool')
You can set what gets treated as true or false with the true and false symbols.
opts = setvaropts(opts,'mybool',...
"TrueSymbols",["t","true","1"],...
"FalseSymbols",["f","false","0"]);
t = readtable('mytable.csv',opts)
Note: This will only match literally 0 and 1, not "0.0" as false or "2" true, but should be good enough for most cases.
댓글 수: 11
Benoit Pasquier
2022년 6월 21일
Sorry for bumping this almost a year later, but this bug has not been fixed yet (MATLAB version 2022a update 2)
This bug just bit me recently and it took me a while to figure out what was wrong. This is a nasty bug because true entries are converted to false entirely silently. When I submitted a bug report I was directed here and given the same workarounds, which is fine, but to my surprise the case was quickly closed (in less than 24 hours).
This attitude is quite frustrating from a user's perspective. It is the second time that a bug report that I submit is getting "closed" despite only being given cheap workarounds. Why close a case if the reported bug is not fixed? And side question: Why is the "bug fix" suggestion here qualified as an "enhancement" rather than what it is, a "bug fix"?
(Apologies for the disgruntled tone.)
Jeremy Hughes
2022년 6월 21일
Hi, the reason for the quick closing of the case is that the report already exists in the system and it's not considered a bug. Your expectation and the design of this feature aren't in alignment, but it is working as designed as expected. This is, at least from a "policy" perspective, why it's an enhancement. Unfortunately, changing the default behavior would result in silent breaking-changes to existing uses which expect the current behavior. I realize that's not the most satisfying answer for your case.
Based on what you're expecting, instead of "logical" you'd be better off continuing to treat this as a number on import (uint8 perhaps), and convert it afterwards. There's not any performance ramifications for that, just a line:
t.mybool = logical(t.mybool)
That works as long as there aren't any "T" or "True" values as well. The paradigm of logical representation needs to be consistent in the file at the very least, or all hope is lost.
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Low-Level File I/O에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!