saving mat file changes my structures!

Hello -
I have a function that compiles data into a structure which consists of field: num which is a 1x24 cell. Thus, D.num = {1x24 cell} My function does this correctly, and allows me to interface with an existing function. However, when my function saves the structure, D, as a mat file, the mat file adds a field. I end up with: D.D.num = {1x24 cell]
I have probed the function and there is only one field when it runs. But the saving is what is changing it. I use the command: save('fname.mat','D') to save the matfile. When I do this from my workspace (and not within the program) it works fine. When the program (function) saves the file, it adds and extra field that is redundant. This is making further programming hard, and I don't see many other options to save this variable.
Thanks - Brad

댓글 수: 1

Cedric
Cedric 2015년 7월 21일
편집: Cedric 2015년 7월 21일
This is because SAVE offers the possibility to save multiple variables at once defined by their names (passed as strings):
>> a = 8 ; b = 9 ;
>> save( 'test.mat', 'a', 'b' ) ;
When we LOAD test.mat, in an ideal world where people would remember/know what was saved in their MAT-Files, MATLAB could assume that we would know that there were two variables, and build an output that we could use this way:
>> [a, b] = load( 'test.mat' ) ; % Wrong.
Yet, my guess is that MATLAB devs had to account for the fact that we usually don't know what we did, especially when someone else did it, so they preferred outputting a struct that contains the variables that were saved as fields:
>> data = load( 'test.mat' )
data =
a: 8
b: 9
What tricked you is that you named the output of LOAD D, so you thought that the struct had been kind of expanded like in Inception. If you name it differently though, like data, you'll see that it will contain D and the whole thing will make sense!
>> data = load( ... )
data =
D: [1x1 struct]
>> D = data.D % Extract field D which is the former variable D.
D =
num: {...}
Signed: someone who didn't understand why he got data.data after loading some MAT-File years ago.

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

답변 (2개)

Muthu Annamalai
Muthu Annamalai 2015년 7월 21일

0 개 추천

Your problem maybe that you are loading wrong, whereas your save code seems OK.
Try this code for your load function,
function D = foo()
D = [];
load('fname.mat'); %this will load D in the local workspace.
return
end
which should overwrite the local copy D and return it to the caller.
Image Analyst
Image Analyst 2015년 7월 21일

0 개 추천

You're probably doing
D = load('fname.mat');
Doing it this way will create a structure called D with all the variables you saved as fields off of that structure. So that's how you got a D.D. If you had also saved a myVar variable, you would get a D.myVar field.
Either read into a structure and pick off your variable from the structure:
storedStruct = load('fname.mat');
D = storedStructure.D;
or "poof" the variables into existence:
load('fname.mat');
I think the first method is the preferred one since people usually don't like to poof variables into workspaces.

댓글 수: 9

Brad Rosenheim
Brad Rosenheim 2015년 7월 21일
Thank you. I am trying to read the output into another function, so it doesn't really have to do with the workspace. In other words, I don't mind poofing. However, the .mat file name is stored as a number (e.g. 493.mat) for interfacing with some other software. Therefore, in the program, I have to give that file a name and I can't poof it into existence.
Is there a way to sift through the layers of a structure until one finds .num? In other words, an if loop that sorts through the various layers until the condition of field=num is met?
Brad
Cedric
Cedric 2015년 7월 21일
편집: Cedric 2015년 7월 21일
You can generate a the string '493.mat' from the numeric content of a variable fNumber=493 using SPRINTF:
fName = sprintf( '%d.mat', fNumber ) ;
The name of the file doesn't become a field name when you load it though. If you then do:
data = load( fName ) ;
you will always have data.D if D was saved in the MAT-File. Unless D was built with a field name based on the aforementioned number, there is no reason to iterate through its fields (you'll always have data.D.num or D.num if you extracted D with D = data.D).
Brad Rosenheim
Brad Rosenheim 2015년 7월 22일
편집: Image Analyst 2015년 7월 22일
The issue here is that I cannot programmatically extract what I'm looking for from a nested structure because there is no good way to sort through the different layers of a nested structure array. I've tried getfield, isfield and other similar functions, but the answer seems to be on how we make structures:
Create a nested structure. a is a structure with a field which contains another structure.
a.b = struct('c',{},'d',{})
a =
b: [0x0 struct]
View the names of the fields of a.b.
fieldnames(a.b)
ans =
'c'
'd'
Here, Mathworks acknowledges that the only way to get into a specific layer of a structure is to know what comprises the struct. One cannot make a variable hold the name of a field, for instance.
So, that leads to the question of how the save function or the load function creates another layer and how can I avoid it? It is very frustrating because it represents something that the programming environment is doing that you didn't ask for - and that makes it very hard to program.
Brad
Image Analyst
Image Analyst 2015년 7월 22일
Brad, I'm not really sure what you're looking for. A structure can have another structure as a field. It can also have strings as fields. You can also have dynamic field names (Google it) where the field names are variable and these names are created/given "on the fly". But I don't really know what you are after. it's not clear. All the code you gave behaves exactly as I would have predicted, so I don't really know what you want.
What is unclear to me is why you have unknown field names. Do you get structs made by other people who used various naming conventions?
There are ways to iterate through field names, as Image Analyst mentions, but the problem to me is why in the first place you are in this situation with unknown field names.
Here is an example where we iterate through field names:
>> S = struct( 'x', 7, 'y', 8, 'u', 9 )
S =
x: 7
y: 8
u: 9
The function FIELDNAMES can be used to get a list of field names given as a cell array of strings:
>> fNames = fieldnames( S )
fNames =
'x'
'y'
'u'
These strings can be used to index the original struct performing a dynamic field name type of indexing .('name') :
for fId = 1 : numel( fNames )
value = S.(fNames{fId}) ;
fprintf( '2 * %s = %d\n', fNames{fId}, 2 * value ) ;
end
Running this outputs:
2 * x = 14
2 * y = 16
2 * u = 18
MSani
MSani 2019년 6월 28일
After removing the empty fields and saving the file, it changes the structure of the arrays and as I am working with the file in python, I am no longer able to process the file in python with the changed structure. How can the file be properly saved after modifying it without changing the structure?
Guillaume
Guillaume 2019년 6월 28일
@Msani, that's two old questions that you've revived and highjacked to ask your own. Please start your own question so it can be properly answered and give as many details as possible (in particular, the code you're using and an example starting structure).
MSani
MSani 2019년 6월 28일
I started my own question for my first issue and was asked to add it to an existing question. That is why I am doing the same now or else I would have started a new thread instead.

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

카테고리

도움말 센터File Exchange에서 Workspace Variables and MAT Files에 대해 자세히 알아보기

질문:

2015년 7월 21일

편집:

2019년 6월 28일

Community Treasure Hunt

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

Start Hunting!

Translated by