matlab - borrando variables de un archivo.mat
mat-file (4)
10 GB de datos? La actualización de archivos MAT multivariables puede resultar costosa debido a la sobrecarga del formato MAT. Considere la posibilidad de dividir los datos y guardar cada variable en un archivo MAT diferente, utilizando directorios para la organización si es necesario. Incluso si tuviera una función conveniente para eliminar variables de un archivo MAT, sería ineficiente. Las variables en un archivo MAT están dispuestas de forma contigua, por lo que reemplazar una variable puede requerir leer y escribir gran parte del resto. Si están en archivos separados, puedes eliminar todo el archivo, lo cual es rápido.
Para ver esto en acción, intente este código, páselo por el depurador mientras usa algo como Process Explorer (en Windows) para monitorear su actividad de E / S.
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;
En mi máquina, los resultados se ven así. (La lectura y la escritura son acumulativas, el tiempo es por operación).
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
Tenga en cuenta que actualizar la pequeña variable x es más costoso que actualizar la gran y. Gran parte de esta actividad de E / S es un trabajo de mantenimiento "redundante" para mantener el formato del archivo MAT organizado, y desaparecerá si cada variable está en su propio archivo.
Además, trate de mantener estos archivos en el sistema de archivos local; Será mucho más rápido que las unidades de red. Si necesitan ir a una unidad de red, considere guardar () y cargar () en los archivos temporales locales (tal vez se elija con nombre de temp ()) y luego cópielos a / desde la unidad de red. El guardado y la carga de Matlab tienden a ser mucho más rápidos con los sistemas de archivos locales, lo suficiente para que el guardado / carga local más una copia puedan ser una ganancia neta sustancial.
Aquí hay una implementación básica que le permitirá guardar variables en archivos separados utilizando las conocidas firmas de guardar () y cargar (). Tienen el prefijo "d" para indicar que son las versiones basadas en directorios. Usan algunos trucos con evalin () y assignin (), así que pensé que valdría la pena publicar el código completo.
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
Aquí está la carga () equivalente.
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 () es el equivalente de whos (''- archivo'').
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$'', '''');
Y ddelete () para eliminar las variables individuales como pediste.
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
¿Alguien aquí sabe cómo eliminar una variable de un archivo matlab? Sé que puede agregar variables a un archivo matlab existente usando el método save -append
, pero no hay documentación sobre cómo eliminar variables del archivo.
Antes de que alguien diga, "simplemente guárdelo", es porque estoy guardando los pasos del procesamiento intermedio en el disco para aliviar los problemas de memoria, y al final habrá casi 10 GB de datos intermedios por rutina de análisis. ¡Gracias!
Curiosamente, puede usar la opción -append
con SAVE para borrar efectivamente los datos de un archivo .mat. Tenga en cuenta este extracto de la documentación (negrita agregada por mí):
Para los archivos MAT,
-append
agrega nuevas variables al archivo o reemplaza los valores guardados de las variables existentes con valores en el área de trabajo .
En otras palabras, si una variable en su archivo .mat se llama A
, puede guardar sobre esa variable con una nueva copia de A
(que ha establecido en []
) usando la opción -append
. Todavía habrá una variable llamada A
en el archivo .mat, pero estará vacía y, por lo tanto, reducirá el tamaño total del archivo.
Aquí hay un ejemplo:
>> 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
El tamaño del archivo será de unos 7.21 MB. Ahora hacer esto:
>> 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
Y ahora el tamaño del archivo será de alrededor de 169 bytes. La variable todavía está allí, pero está vacía.
La única forma de hacer esto que conozco es usar la función de API MAT-file matDeleteVariable
. Supongo que sería bastante fácil escribir una rutina de Fortran o C para hacer esto, pero parece un gran esfuerzo para algo que debería ser mucho más fácil.
Le sugiero que cargue las variables del archivo .mat que desea conservar y las guarde en un nuevo archivo .mat. Si es necesario, puede cargar y guardar (usando ''-append''
) en un bucle.
S = load(filename, ''-mat'', variablesYouWantToKeep);
save(newFilename,''-struct'',S,variablesYouWantToKeep);
%# then you can delete the old file
delete(filename)