Pregunta

¿Alguien aquí sabe cómo eliminar una variable a partir de un archivo de Matlab? Sé que se puede añadir variables para un archivo de Matlab existente utilizando el método save -append, pero no hay documentación sobre cómo eliminar variables del archivo.

Antes de que alguien dice, "simplemente guardarlo", es porque estoy ahorrando pasos de procesamiento intermedios en el disco para aliviar los problemas de memoria, y al final habrá casi 10 GB de datos intermedios por cada rutina de análisis. Gracias!

¿Fue útil?

Solución

Curiosamente, puede utilizar la opción -append con GUARDAR a efectivamente los datos de borrado de un archivo .mat. Nota este extracto de la documentación (negrita añadida por mí):

  
    

Para MAT-archivos, -append añade nuevas variables en el fichero o reemplaza los valores guardados de las variables existentes con valores en el espacio de trabajo .

  

En otras palabras, si una variable en el archivo de .mat se llama A, puede ahorrar más de esa variable con un nueva copia de A (que ha establecido a []) utilizando el -append opción. Todavía habrá una variable llamada A en el archivo .mat, pero va a estar vacío y por lo tanto reducir el tamaño total del archivo.

Este es 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 sigue ahí, pero está vacío.

Otros consejos

10 GB de datos? Actualización de archivos MAT múltiples variables podría conseguir debido caro a formato MAT sobrecarga. Considere dividir los datos y ahorro de cada variable a un archivo MAT diferente, utilizando los directorios para la organización si es necesario. Aún si tiene una función que le permite eliminar variables de un archivo MAT, sería ineficiente. Las variables en un archivo MAT se nos extienden de forma contigua, por lo que la sustitución de una variable puede requerir leer y escribir gran parte del resto. Si están en archivos separados, puede simplemente eliminar el archivo completo, que es rápido.

Para ver esto en acción, probar este código, paso a paso a través de él en el depurador durante el uso de algo así como Process Explorer (en Windows) para supervisar 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í. (Lectura y escritura son acumulativos, 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 la actualización de la pequeña variable x es más cara que la actualización de la gran y. Gran parte de esta actividad de E / S es "redundante" el trabajo de limpieza para mantener el formato de archivo MAT organizada, y desaparecerá si cada variable está en su propio archivo.

Además, trate de mantener estos archivos en el sistema de archivos local; que va a ser mucho más rápido que las unidades de red. Si tienen que ir en una unidad de red, considere hacer la memorización () y la carga () en los archivos temporales locales (tal vez elegido con tempname ()) y luego copiarlos a / desde la unidad de red. Guardar de Matlab y de carga tienden a ser mucho más rápido con sistemas de archivos locales, lo suficiente para que las autoridades locales Guardar / Cargar más una copia puede ser una ganancia neta sustancial.


Aquí hay una aplicación básica que le permitirá guardar las variables en archivos separados utilizando el familiar save () y la carga () las firmas. Están el prefijo "d" para indicar que son las versiones basadas en directorio. Utilizan 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

La única manera de hacer esto que sé es utilizar el archivo MAT-función de la API matDeleteVariable. Sería, supongo, ser bastante fácil de escribir una rutina Fortran o C para hacer esto, pero parece como un gran esfuerzo para obtener algo que debería ser mucho más fácil.

Sugiero que carga las variables del archivo .mat desea mantener, y guardarlos 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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top