簡體   English   中英

從文本文件中將數據讀入MATLAB

[英]Reading data into MATLAB from a textfile

我有一個具有以下結構的文本文件:

1999-01-04
1,100.00
1,060.00
1,092.50
0
6,225
1,336,605
37
1999-01-05 
1,122.50
1,087.50
1,122.50
0
3,250
712,175
14
...

該文件包含重復的八個值集合(一個日期后跟七個數字,每個數字各自獨立)。

我想把它讀入MATLAB並將值放到不同的向量中。 我試圖用幾種不同的方法來實現這一點,但沒有一種方法有效 - 都輸出了某種錯誤。

如果它很重要,我在Mac上這樣做。

編輯:這是我之前在答案中的代碼的較短版本...

如果您想直接讀取數據文件,而不必像dstibbe建議那樣進行預處理,則以下內容應該有效:

fid = fopen('datafile.txt','rt');
data = textscan(fid,'%s %s %s %s %s %s %s %s','Delimiter','\n');
fclose(fid);
data = [datenum(data{1}) cellfun(@str2double,[data{2:end}])]';

上面的代碼將每組8個值放入8×N矩陣中,N是數據文件中8個線組的數量。 日期將轉換為序列日期編號,以便它可以包含在矩陣中的其他雙精度值中。 以下函數(在上面的代碼中使用)可能是有意義的: TEXTSCANDATENUMCELLFUNSTR2DOUBLE

我提出另一個解決方案。 這是MATLAB代碼中最短的一個。 首先使用sed ,我們將文件格式化為CSV文件(逗號分隔,每行記錄在一行):

cat a.dat | sed -e 's/,//g ; s/[ \t]*$/,/g' -e '0~8 s/^\(.*\),$/\1\n/' | 
            sed -e :a -e '/,$/N; s/,\n/,/; ta' -e '/^$/d' > file.csv

說明 :首先我們刪除數千個逗號分隔符,並在每行末尾修剪空格添加逗號。 但是我們刪除每個第8行的結尾逗號。 最后,我們加入行並刪除空行。

輸出將如下所示:

1999-01-04,1100.00,1060.00,1092.50,0,6225,1336605,37
1999-01-05,1122.50,1087.50,1122.50,0,3250,712175,14

接下來在MATLAB中,我們只需使用textscan讀取每一行,第一個字段為字符串(轉換為num),其余為數字:

fid = fopen('file.csv', 'rt');
a = textscan(fid, '%s %f %f %f %f %f %f %f', 'Delimiter',',', 'CollectOutput',1);
fclose(fid);

M = [datenum(a{1}) a{2}]

並且得到的矩陣M是:

  730124     1100     1060   1092.5    0   6225   1336605    37
  730125   1122.5   1087.5   1122.5    0   3250    712175    14

使用腳本將文本文件修改為Matlab可以讀取的內容。

例如。 使它成為一個矩陣:

M = [
1999-01-04
1,100.00
1,060.00
1,092.50
0
6,225
1,336,605;  <-- notice the ';'
37
1999-01-05 
1,122.50
1,087.50
1,122.50
0
3,250;   <-- notice the ';'
712,175
14
...
]

將其導入matlab並從矩陣中讀取各種向量。

注意:我的matlab有點生疏。 可能包含錯誤。

一旦你閱讀了數據,你想要的數據形式並不完全清楚。 下面的代碼將它全部放在一個矩陣中,每行代表文本文件中的一組8行。 您可能希望對不同的列使用不同的變量,或者(如果您有權訪問統計工具箱),請使用數據集數組。

% Read file as text
text = fileread('c:/data.txt');

% Split by line
x = regexp(text, '\n', 'split');

% Remove commas from numbers
x = regexprep(x, ',', '')

% Number of items per object
n = 8;

% Get dates
index = 1:length(x);
dates = datenum(x(rem(index, n) == 1));

% Get other numbers
nums = str2double(x(rem(index, n) ~= 1));
nums = reshape(nums, (n-1), length(nums)/(n-1))';

% Combine dates and numbers
thedata = [dates nums];

您還可以查看函數textscan以了解解決問題的其他方法。

與Richie相似。 使用str2double將文件字符串轉換為雙精度數。 此實現逐行處理,而不是使用正則表達式打破文件。 輸出是各個向量的單元陣列。

function vectors = readdata(filename)

fid=fopen(filename);

tline = fgetl(fid);
counter = 0;
vectors = cell(7,1);
while ischar(tline)
    disp(tline)
    if counter > 0
        vectors{counter} = [vectors{counter} str2double(tline)];
    end
    counter = counter + 1
    if counter > 7
        counter = 0;
    end
    tline = fgetl(fid);
end

fclose(fid);

這有正則表達式檢查,以確保您的數據格式良好。

fid = fopen('data.txt','rt');

%these will be your 8 value arrays
val1 = [];
val2 = [];
val3 = [];
val4 = [];
val5 = [];
val6 = [];
val7 = [];
val8 = [];

linenum = 0; % line number in file
valnum = 0; % number of value (1-8)

while 1
   line = fgetl(fid);
   linenum = linenum+1;
   if valnum == 8
      valnum = 1;
   else
      valnum = valnum+1;
   end

    %-- if reached end of file, end
    if isempty(line) | line == -1
      fclose(fid);
      break;
   end


   switch valnum
      case 1
         pat = '(?\d{4})-(?\d{2})-(?\d{2})'; % val1 (e.g. 1999-01-04)
      case 2
         pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val2 (e.g. 1,100.00)  [valid up to 1billion-1]
      case 3
         pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val3 (e.g. 1,060.00)  [valid up to 1billion-1]
      case 4
         pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val4 (e.g. 1,092.50)  [valid up to 1billion-1]
      case 5
         pat = '(?\d+)'; % val5 (e.g. 0)
      case 6
         pat = '(?\d*[,]*\d*[,]*\d+)'; % val6 (e.g. 6,225)  [valid up to 1billion-1]
      case 7
         pat = '(?\d*[,]*\d*[,]*\d+)'; % val7 (e.g. 1,336,605)  [valid up to 1billion-1]
      case 8
         pat = '(?\d+)'; % val8 (e.g. 37)
      otherwise
         error('bad linenum')
   end

   l = regexp(line,pat,'names'); % l is for line
    if length(l) == 1 % match
      if valnum == 1
         serialtime = datenum(str2num(l.yr),str2num(l.mo),str2num(l.dy)); % convert to matlab serial date
         val1 = [val1;serialtime];
      else
         this_val = strrep(l.val,',',''); % strip out comma and convert to number
         eval(['val',num2str(valnum),' = [val',num2str(valnum),';',this_val,'];']) % save this value into appropriate array
      end
   else
      warning(['line number ',num2str(linenum),' skipped! [didnt pass regexp]: ',line]);
   end
end

暫無
暫無

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

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