2010-11-24 15 views
16

Kann jemand hier, wie man eine Variable aus einer Matlab-Datei löschen? Ich weiß, dass Sie mit der Methode save -append Variablen zu einer vorhandenen Matlab-Datei hinzufügen können, aber es gibt keine Dokumentation darüber, wie Sie Variablen aus der Datei löschen können.Löschen von Variablen aus einer .mat-Datei

Bevor jemand sagt, "nur speichern", ist es, weil ich Zwischenverarbeitungsschritte auf die Festplatte speichern, um Speicherprobleme zu lindern, und am Ende wird es fast 10 GB Zwischendaten pro Analyse Routine. Vielen Dank!

Antwort

13

Interessanterweise können Sie die Option -append mit SAVE-effektiv Lösch Daten aus einer .mat-Datei verwenden. Notieren Sie sich diesen Auszug aus der Dokumentation (fett von mir hinzugefügt):

Für MAT-Dateien, fügt -append neue Variablen in die Datei oder ersetzt die gespeicherten Werte vorhandener Variablen mit Werten im Arbeitsbereich.

Mit anderen Worten, wenn eine Variable in Ihrer .mat Datei A aufgerufen wird, können Sie sparen über die Variable mit einer neuen Kopie A (die Sie auf [] festgelegt haben) mit den -append Möglichkeit. Es wird weiterhin eine Variable namens A in der .mat-Datei geben, aber sie wird leer sein und somit die gesamte Dateigröße reduzieren.

Hier ist ein Beispiel:

>> A = rand(1000);   %# Create a 1000-by-1000 matrix of random values 
>> save('savetest.mat','A'); %# Save A to a file 
>> whos -file savetest.mat %# Look at the .mat file contents 
    Name   Size    Bytes Class  Attributes 

    A   1000x1000   8000000 double 

Die Dateigröße ca. 7,21 MB sein. Jetzt tun Sie das:

>> A = [];        %# Set the variable A to empty 
>> save('savetest.mat','A','-append'); %# Overwrite A in the file 
>> whos -file savetest.mat    %# Look at the .mat file contents 
    Name  Size   Bytes Class  Attributes 

    A   0x0     0 double 

Und jetzt wird die Dateigröße um 169 Bytes sein. Die Variable ist immer noch da, aber sie ist leer.

+2

+1 für clevere Problemumgehung! – Jonas

1

Der einzige Weg, dies zu tun, den ich kenne, ist die Verwendung der MAT-Datei-API-Funktion matDeleteVariable. Es wäre, denke ich, ziemlich einfach, eine Fortran- oder C-Routine dafür zu schreiben, aber es scheint eine Menge Aufwand für etwas zu sein, das viel einfacher sein sollte.

+0

Wow, ich hoffe, das ist nicht der einzige Weg, es zu tun, obwohl danke, dass Sie darauf hingewiesen haben. Es ist schon eine Weile her, seit ich irgendetwas in c geschrieben habe ... Ich bin halb versucht, die Routine zu schreiben, die Sie nur für Tritte nennen. – eykanal

+0

@eykanal: Ich hoffe, es ist nicht der einzige Weg. Aber niemand hat uns von dem viel einfacheren Weg aus dem Befehlsfenster erzählt. –

+2

Möglicherweise wurde beabsichtigt, dies nicht bequemer zu machen. Das zusammenhängende Layout des MAT-Dateiformats bedeutet, dass Sie beim Löschen einer Variablen entweder "Müll" zurücklassen und Speicherplatz auf der Festplatte verschwenden oder möglicherweise einen Großteil der Datei neu schreiben müssen. So wie die O (n) Löschkosten für ein Element in einem Array, aber die Kosten für Festplatten-I/O. Das Freilegen einer Löschvariablenfunktion könnte eine Einladung für den einfachen Benutzer sein, versehentlich viele unnötige E/A auszuführen. –

0

Ich schlage vor, Sie laden die Variablen aus der .mat-Datei, die Sie behalten möchten, und speichern sie in einer neuen .mat-Datei. Bei Bedarf können Sie laden und speichern (mit '-append') in einer Schleife.

S = load(filename, '-mat', variablesYouWantToKeep); 
save(newFilename,'-struct',S,variablesYouWantToKeep); 
%# then you can delete the old file 
delete(filename) 
+0

Das ist, was ich mache, aber das ist ein kludgy Workaround. Ich bin wirklich überrascht, dass es keinen direkten Weg dafür zu geben scheint. – eykanal

+0

@eykanal: Es gibt anscheinend einfach nicht genug Leute, die jemals solch ein Feature brauchten. – Jonas

10

10 GB Daten? Das Aktualisieren von MAT-Dateien mit mehreren Variablen kann aufgrund des MAT-Format-Overheads teuer werden. Ziehen Sie in Betracht, die Daten aufzuteilen und jede Variable in einer anderen MAT-Datei zu speichern. Verwenden Sie bei Bedarf Verzeichnisse für die Organisation. Selbst wenn Sie eine praktische Funktion zum Löschen von Variablen aus einer MAT-Datei hätten, wäre dies ineffizient. Die Variablen in einer MAT-Datei sind zusammenhängend angeordnet, so dass das Ersetzen und Austauschen einer Variablen das Lesen und Schreiben eines Großteils des Rests erfordern kann. Wenn sie sich in separaten Dateien befinden, können Sie einfach die gesamte Datei löschen, was schnell geht.

Um dies in Aktion zu sehen, versuchen Sie diesen Code und durchlaufen Sie ihn im Debugger, während Sie etwas wie Process Explorer (unter Windows) verwenden, um seine E/A-Aktivität zu überwachen.

function replace_vars_in_matfile 

x = 1; 
% Random dummy data; zeros would compress really well and throw off results 
y = randi(intmax('uint8')-1, 100*(2^20), 1, 'uint8'); 

tic; save test.mat x y; toc; 
x = 2; 
tic; save -append test.mat x; toc; 
y = y + 1; 
tic; save -append test.mat y; toc; 

Auf meinem Computer sehen die Ergebnisse so aus.(Lesen und Schreiben sind kumulativ, Zeit pro Betrieb ist.)

    Read (MB)  Write (MB)  Time (sec) 
before any write: 25    0 
first write:  25    105    3.7 
append x:   235   315    3.6 
append y:   235   420    3.8 

Beachten Sie, dass die kleinen x variable Aktualisierung ist teurer als der großen y aktualisieren. Ein Großteil dieser E/A-Aktivität ist "redundante" Haushaltsarbeit, um das MAT-Dateiformat organisiert zu halten, und wird verschwinden, wenn jede Variable in ihrer eigenen Datei ist.

Versuchen Sie auch, diese Dateien auf dem lokalen Dateisystem zu behalten; es wird viel schneller sein als Netzlaufwerke. Wenn sie auf ein Netzlaufwerk zugreifen müssen, sollten Sie in Erwägung ziehen, die lokalen temporären Dateien save() und load() (möglicherweise mit tempname() ausgewählt) zu kopieren und dann auf das Netzlaufwerk zu kopieren. Das Speichern und Laden von Matlab ist bei lokalen Dateisystemen viel schneller, so dass das lokale Speichern/Laden und eine Kopie einen beträchtlichen Nettogewinn bedeuten.

Hier ist eine grundlegende Implementierung, mit der Sie Variablen in separaten Dateien mit den bekannten save() - und load() - Signaturen speichern können. Sie haben das Präfix "d", um anzuzeigen, dass es sich um die verzeichnisbasierten Versionen handelt. Sie benutzen ein paar Tricks mit evalin() und assignin(), also dachte ich, es wäre es wert, den vollständigen Code zu veröffentlichen.

function dsave(file, varargin) 
%DSAVE Like save, but each var in its own file 
% 
% dsave filename var1 var2 var3... 
if nargin < 1 || isempty(file); file = 'matlab'; end 
[tfStruct,loc] = ismember({'-struct'}, varargin); 
args = varargin; 
args(loc(tfStruct)) = []; 
if ~all(cellfun(@isvarname, args)) 
    error('Invalid arguments. Usage: dsave filename <-struct> var1 var2 var3 ...'); 
end 
if tfStruct 
    structVarName = args{1}; 
    s = evalin('caller', structVarName); 
else 
    varNames = args; 
    if isempty(args) 
     w = evalin('caller','whos'); 
     varNames = { w.name }; 
    end 
    captureExpr = ['struct(' ... 
     join(',', cellfun(@(x){sprintf('''%s'',{%s}',x,x)}, varNames)) ')']; 
    s = evalin('caller', captureExpr); 
end 

% Use Java checks to avoid partial path ambiguity 
jFile = java.io.File(file); 
if ~jFile.exists() 
    ok = mkdir(file); 
    if ~ok; 
     error('failed creating dsave dir %s', file); 
    end 
elseif ~jFile.isDirectory() 
    error('Cannot save: destination exists but is not a dir: %s', file); 
end 
names = fieldnames(s); 
for i = 1:numel(names) 
    varFile = fullfile(file, [names{i} '.mat']); 
    varStruct = struct(names{i}, {s.(names{i})}); 
    save(varFile, '-struct', 'varStruct'); 
end 

function out = join(Glue, Strings) 
Strings = cellstr(Strings); 
if length(Strings) == 0 
    out = ''; 
elseif length(Strings) == 1 
    out = Strings{1}; 
else 
    Glue = sprintf(Glue); % Support escape sequences 
    out = strcat(Strings(1:end-1), { Glue }); 
    out = [ out{:} Strings{end} ]; 
end 

Hier ist die Last() gleichwertig.

function out = dload(file,varargin) 
%DLOAD Like load, but each var in its own file 
if nargin < 1 || isempty(file); file = 'matlab'; end 
varNames = varargin; 
if ~exist(file, 'dir') 
    error('Not a dsave dir: %s', file); 
end 
if isempty(varNames) 
    d = dir(file); 
    varNames = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', ''); 
end 

out = struct; 
for i = 1:numel(varNames) 
    name = varNames{i}; 
    tmp = load(fullfile(file, [name '.mat'])); 
    out.(name) = tmp.(name); 
end 

if nargout == 0 
    for i = 1:numel(varNames) 
     assignin('caller', varNames{i}, out.(varNames{i})); 
    end 
    clear out 
end 

Dwhos() ist das Äquivalent von whos ('- Datei').

function out = dwhos(file) 
%DWHOS List variable names in a dsave dir 
if nargin < 1 || isempty(file); file = 'matlab'; end 
out = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', ''); 

Und ddelete(), um die einzelnen Variablen zu löschen, wie Sie gefragt.

function ddelete(file,varargin) 
%DDELETE Delete variables from a dsave dir 
if nargin < 1 || isempty(file); file = 'matlab'; end 
varNames = varargin; 
for i = 1:numel(varNames) 
    delete(fullfile(file, [varNames{i} '.mat'])); 
end 
+0

Interessanterweise verwende ich eine bestimmte Datenanalyse-Toolbox, und sie empfehlen zu tun, was Sie sagen; Verwenden einer einzelnen Datei für jede Variable. Ich habe das nicht getan, weil ich die Argumentation nicht gesehen habe, aber Ihr detaillierter Beitrag erklärt es. Vielen Dank! – eykanal

Verwandte Themen