1. 程式人生 > >Matlab讀取txt資料的實用方法

Matlab讀取txt資料的實用方法

需求

有個朋友需要我幫忙寫個matlab指令碼讀取100個txt文件的實驗資料,這些文件的結構相同,分為四列,從第一列到第四列依次是時間、位置、速度、加速度。讀取完資料之後需要對資料進行處理,具體的處理方式是:提取以0.002為取樣週期的資料,分類儲存起來。
檔案內容是這樣的:
在這裡插入圖片描述

技術難點

技術難點在於,這些檔案中的資料是從一個軟體中模擬得到的,由於採用的是變步長模擬,因此取樣時間不統一,很難採用對時間取餘的操作來實現。

解決辦法

首先對於給定的文件結構,採用textread函式讀取四列資料分別存放在四個變數a1,a2,a3,a4中。小夥伴兒可能會問,由於檔案頭的存在,讀取的資料前面幾行並不是實際資料,怎麼辦?好辦,把前幾行去掉不就行了,使用MATLAB很容易提取。

[a1,a2,a3,a4]=textread(filename,'%s%s%s%s','headerlines',4);

由於讀入到matlab中的資料屬於文字變數,對應的型別是cell,而我們需要的資料型別是double,怎麼辦?型別轉換吧;處理過程:cell->mat->double

function res=cell2double(input)
[n,m]=size(input);
res=zeros(n,1);
for i=1:n
   temp=cell2mat(input(i));
   res(i)=str2double(temp);
end
end

重點來了,由於取樣時間不是固定的(變步長取樣時間有些地方大,有些地方小),因此採用

mod(time(i),0.002)==0

這樣的簡單判斷是不行的,本人試過這種方式來提取資料,結果有的檔案提取的資料多,有的檔案提取的資料少,無法跟時間進行對齊,確實很讓人頭疼。
考慮到取樣時間精度在0.002秒以下,如果只是採用時間除以0.002取餘數,很多資料會被錯誤判定為不合適,從而丟失資料。怎麼辦呢?
對時間四捨五入嘛,將時間四捨五入到小數點後3位不就行了。
但是呢,問題又來了,比如取樣時間0.0082,0.0084時,則這兩個資料都會被加入,這是行不通的,處理的結果依然跟前面的一樣。
從四捨五入後的資料中尋找特徵吧。對於四捨五入後的時間點,當存在相同的取樣時間是隻取其中的一個即可,仔細觀察可以發現這樣的資料特徵,每一個滿足要求的資料,它的後面一個數據的時間節點總是比它大。


程式碼就這樣寫吧:

  for j=1:time_rows-5-1
          if mod(time(j),0.002)==0%能被0.002整除,條件1
              if time(j+1)>time(j)%後一個取樣時間比前一個大,條件2
                   tempTime(k)=time(j);
                   tempPos(k)=pos(j);
                   tempSpeed(k)=speed(j);
                   tempAcc(k)=acc(j);
                   k=k+1;
              end
          end
      end

好啦,貼一下完整的程式碼,僅供參考。

參考程式碼

clc;
clear all;
N=100;
M=5000;
dataToGetPos=zeros(M,N+1);
dataToGetSpeed=zeros(M,N+1);
dataToGetAcc=zeros(M,N+1);
for i=1:N
    str1='result';
    str2='.txt';
    filename=sprintf('%s%d%s',str1,i,str2);
   [a1,a2,a3,a4]=textread(filename,'%s%s%s%s','headerlines',4);
   [pos_rows,pos_cols]=size(a2);
   [time_rows,time_cols]=size(a1);
   [speed_rows,speed_cols]=size(a3);
   [acc_rows,acc_cols]=size(a4);
   tempPos=zeros(M,1);
   tempTime=zeros(M,1);
   tempSpeed=zeros(M,1);
   tempAcc=zeros(M,1);
   time=cell2double(a1(5:time_rows));
   pos=cell2double(a2(5:pos_rows));
   speed=cell2double(a3(5:speed_rows));
   acc=cell2double(a4(5:acc_rows));
   time=round(time,3);
   k=1;
   if i==1 
      for j=1:time_rows-5-1
          if mod(time(j),0.002)==0
              if time(j+1)>time(j)
                   tempTime(k)=time(j);
                   tempPos(k)=pos(j);
                   tempSpeed(k)=speed(j);
                   tempAcc(k)=acc(j);
                   k=k+1;
              end
          end
      end
      [tempPosRows,tempPoscols]=size(tempPos);
       if tempPosRows<M
          for l=tempPosRows+1:M
             tempPos(l)=0;
             tempTime(l)=0;
             tempSpeed(l)=0;
             tempAcc(l)=0;
          end
      end
      dataToGetPos(:,1)=tempTime;
      dataToGetPos(:,2)=tempPos;
      dataToGetSpeed(:,1)=tempTime;
      dataToGetSpeed(:,2)=tempSpeed;
      dataToGetAcc(:,1)=tempTime;
      dataToGetAcc(:,2)=tempAcc;
   else
      for j=1:time_rows-5-1
         if mod(time(j),0.002)==0
              if time(j+1)>time(j)
                tempPos(k)=pos(j);
                tempTime(k)=time(j);
                tempSpeed(k)=speed(j);
                tempAcc(k)=acc(j);
                k=k+1;
              end
          end
      end
      [tempPosRows,tempPoscols]=size(tempPos);
      if tempPosRows<M
          for l=tempPosRows+1:M
             tempPos(l)=0;
             tempSpeed(l)=0;
             tempAcc(l)=0;
          end
      end
      dataToGetPos(:,i+1)=tempPos;
      dataToGetSpeed(:,i+1)=tempSpeed;
      dataToGetAcc(:,i+1)=tempAcc;
   end
   disp(['Processing: ',num2str(i/N*100),'%.......']);
end
save dataToGetPos.mat dataToGetPos;
save dataToGetSpeed.mat dataToGetSpeed;
save dataToGetAcc.mat dataToGetAcc;
figure(1)
plot(dataToGetPos(:,1),dataToGetPos(:,2:101));
xlabel('時間/s');
ylabel('位置/mm');
set(gca,'FontSize',13);

figure(2)
plot(dataToGetSpeed(:,1),dataToGetSpeed(:,2:101))
xlabel('時間/s');
ylabel('速度/mm.s^{-1}');
set(gca,'FontSize',13);

figure(3)
plot(dataToGetAcc(:,1),dataToGetAcc(:,2:101))
xlabel('時間/s');
ylabel('加速度/mm.s^{-2}');
set(gca,'FontSize',13);
disp('Done!');

資料轉換函式:

function res=cell2double(input)
[n,m]=size(input);
res=zeros(n,1);
for i=1:n
   temp=cell2mat(input(i));
   res(i)=str2double(temp);
end
end

執行以上程式碼生成下面的幾幅圖:
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述