簡體   English   中英

動態生成結構的解決方法-Matlab / Octave問題

[英]Workaround for dynamically generating a structure - Matlab/Octave issues

我以文件名標准組織了許多.csv格式的數據集,因此我可以第二次使用正則表達式。 但是,我遇到了一個小問題。 我的數據文件標題為“ 2012001_C335_2000MHZ_P_1111.CSV”。 有四年的興趣,兩個頻率和四個不同的C335樣式標簽來描述位置。 我需要對每個文件進行大量的數據處理,因此,我想將它們全部讀入一個巨大的結構,然后對文件的不同部分進行處理。 我在寫:

for ix_id = 1:length(ids)
 for ix_years = 1:2:length(ids_years{ix_id})
  for ix_frq = 1:length(frqs)
   st = [ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids_frqs{ix_id}{ix_frq}'_P_1111.CSV'];
   data.(ids_frqs{ix_id}{ix_frq}).(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}]) =...
        dlmread(st);
  end
 end
end

所有ids變量都是1x4單元格數組,其中每個單元格都包含字符串。

這將產生錯誤:“錯誤:cs列表無法進一步建立索引”和“錯誤:對cs列表的無效分配在多個分配之外”

我在互聯網上搜索了這些錯誤,並發現了一些日期從2010年到2012年的帖子,例如thisthis ,作者認為這是Octave本身的問題。 我可以做一個解決方法,其中包括定義兩個單獨的結構,方法是刪除ix_frq上最里面的for循環,然后將以“ st”和“ data”開頭的行替換為

data.1500.(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}]) = ...
  dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids{ix_id} '_1500MHZ_P_1111.CSV']);
data.2000.(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}]) = ...
  dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids{ix_id} '_2000MHZ_P_1111.CSV']);

因此,當我嘗試制作更嵌套的結構時,似乎會出現麻煩。 我想知道這是Octave所獨有的還是在Matlab中是相同的,以及是否存在比定義兩個單獨的結構更好的解決方法,因為我希望這種結構盡可能地可移植。 如果您對錯誤消息的含義有任何了解,我也對此感興趣。 謝謝!

編輯:這是完整的腳本-現在生成一些虛擬.csv文件。 在Octave v。3.8上運行

clear all
%this program tests the creation of various structures.  The end goal is to have a structure of the format frequency.beamname.year(1) = matrix of the appropriate file
A = rand(3,2);
csvwrite('2009103_C115_1500MHZ.CSV',A)
csvwrite('2009103_C115_2000MHZ.CSV',A)
csvwrite('2010087_C115_1500MHZ.CSV',A)
csvwrite('2010087_C115_2000MHZ.CSV',A)
csvwrite('2009103_C335_1500MHZ.CSV',A)
csvwrite('2009103_C335_2000MHZ.CSV',A)
csvwrite('2010087_C335_1500MHZ.CSV',A)
csvwrite('2010087_C335_2000MHZ.CSV',A)

data = dir('*.CSV');  %imports all of the files of a directory
files = {data.name};  %cell array of filenames
nfiles = numel(files);

%find all the years
years = unique(cellfun(@(x)x{1},regexp(files,'\d{7}','match'),'UniformOutput',false));  
%find all the beam names
ids = unique(cellfun(@(x)x{1},regexp(files,'([C-I]\d{3})|([C-I]\d{1}[C-I]\d{2})','match'),'UniformOutput',false));
%find all the frequencies
frqs = unique(cellfun(@(x)x{1},regexp(files,'\d{4}MHZ','match'),'UniformOutput',false));

%now, vectorize to cover all the beams
for id_ix = 1:length(ids)
  expression_yrs = ['(\d{7})(?=_' ids{id_ix} ')'];
  listl_yrs = regexp(files,expression_yrs,'match');
  ids_years{id_ix} = unique(cellfun(@(x)x{1},listl_yrs(cellfun(@(x)~isempty(x),listl_yrs)),'UniformOutput',false));  %returns the years for data collected with both the 1500 and 2000 MHZ antennas along each of thebeams
  expression_frqs = ['(?<=' ids{id_ix} '_)(\d{4}MHZ)']; 
  listfrq = regexp(files,expression_frqs,'match'); %finds every frequency that was collected for C115, C335
  ids_frqs{id_ix} = unique(cellfun(@(x)x{1},listfrq(cellfun(@(x)~isempty(x),listfrq)),'UniformOutput',false));
end

%% finally, dynamically generate a structure data.Beam.Year.Frequency
%this works
for ix_id = 1:length(ids)
  for ix_year = 1:length(ids_years{ix_id})
    data1500.(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}])=dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids_frqs{1}{1} '.CSV']);
    data2000.(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}])=dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids_frqs{1}{2} '.CSV']);
  end
end

%this doesn't work
for ix_id=1:length(ids)
  for ix_year=1:length(ids_years{ix_id})
    for ix_frq = 1:numel(frqs)
        data.(['F' ids_frqs{ix_id}{ix_frq}]).(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}])=dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids_frqs{ix_id}{ix_frq} '.CSV']);
    end 
  end
end

希望這有助於澄清問題-我不確定此處的禮節與發布編輯和代碼。

問題是,當您進入導致問題的for循環時,數據已經存在並且是一個結構數組。

octave> data
data =

  8x1 struct array containing the fields:

    name
    date
    bytes
    isdir
    datenum
    statinfo

當您從結構體數組中選擇一個字段時,將獲得一個cs列表(以逗號分隔的列表),除非您還索引了該結構體數組中的哪個結構體。 看到:

octave> data.name
ans = 2009103_C115_1500MHZ.CSV
ans = 2009103_C115_2000MHZ.CSV
ans = 2009103_C335_1500MHZ.CSV
ans = 2009103_C335_2000MHZ.CSV
ans = 2010087_C115_1500MHZ.CSV
ans = 2010087_C115_2000MHZ.CSV
ans = 2010087_C335_1500MHZ.CSV
ans = 2010087_C335_2000MHZ.CSV
octave> data(1).name
ans = 2009103_C115_1500MHZ.CSV

因此,當您這樣做時:

data.(...) = dlmread (...);

您不會在左側得到期望的結果,將得到一個cs列表。 但是我猜測這是偶然的,因為當前data僅具有文件名,因此只需創建一個新的空結構:

data = struct (); # this will clear your previous data
for ix_id=1:length(ids)
  for ix_year=1:length(ids_years{ix_id})
    for ix_frq = 1:numel(frqs)
        data.(['F' ids_frqs{ix_id}{ix_frq}]).(ids{ix_id}).(['Y' ids_years{ix_id}{ix_year}])=dlmread([ids_years{ix_id}{ix_year} '_' ids{ix_id} '_' ids_frqs{ix_id}{ix_frq} '.CSV']);
    end 
  end
end

我還建議您更好地考慮當前的解決方案。 這段代碼對我來說太復雜了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM