【MATLAB】cell、double、string 陣列間的型態轉換

  • 14802
  • 0
  • 2018-11-02

夏恩覺得在 MATLAB 內的資料型態中,最好用的就是細胞陣列。
最頭疼的呢,也是細胞陣列。

就如同 python 的 List 型態,我們可以放心地放入任何資料,不會受到任何制裁。
好用的前提是,我們得先明白在不同資料格式間的轉換方法。

版本資訊:
Matlab版本:R2017b (核心即可,不用多餘的工具箱)

重點整理:

先講結論:

會用 cellfun 的話,請直接使用之,用法附在最後面;
若不會,則下面提供幾個方法供您參考:

1.在 cell array 中,把文字轉數字:
string() 或 char() > str2double() > num2cell()
拆cell > 轉換型態 > 回cell

2.在 cell array 中,數字轉文字:
cell2mat() > string() 或 char() > cellstr()
拆cell > 轉換型態 > 回cell

其中 mat2cell 顏色不一樣表示使用方法較特殊,須小心使用。
以下都是關於這張表所提到之函數的詳細說明。

一、獲得一份資料:

夏恩先製作一份虛擬的訂單資料,供大家參考。
有需要的請自行複製貼上即可。

order machine quantity
S3-732 A 484
S3-676 A 638
L3-744 A 638
L3-745 B 638
L3-880 B 504
R2-719 B 282
R3-741 B 282
R3-755 C 580
L1-550 D 357
L1-611 E 336
SD-019 E 251
SD-123 E 501
SD-144 E 1153

這份表格的欄位依序是訂單編號(字串)、機台編號(字串)、訂單數量(整數)。
檔案名稱為 test,格式為 xlsx 檔案。

首先我們先使用 readtable 把檔案讀進來,示範如下:

這邊補充一點就是欄位名稱最好使用英文,若使用中文欄位名稱,
其欄位資料會呈現預設的 x_??? 格式,而實際資料則會存放到 Properties.VariableDescriptions 屬性中。

以下示範使用中文欄位名稱會發生什麼事情:

為了要找到正確的欄位名稱,還真花了本恩不少時間。
所以為了省事,還是乖乖地用英文欄位名稱吧!

table 格式非常好用,使用者可以直接結合兩份表格資料,使用 innerjoin 或是 outerjoin 都可以,
不過這不是本文的重點,所以改天再聊。

二、轉 table 為 cell:

使用 table2cell 即可滿足需求,程式碼太短不額外打字,如圖。

其實 table 有三種轉換方法,分別為:table2cell、table2struct、table2array。
其中,table2array 的限制比較多,少用。
又 cell 型態比 struct 好用,所以夏恩最常用的語法就是 table2cell 啦!

三、int(double) cell 與 array 間的轉換:

現在來了一個情境題,那就是我們希望加總所有的訂單資料。
如果直接使用 sum 指令,會報錯,如圖:

這邊需要先使用 cell2mat 做轉換後,才能做加總的動作,其他矩陣操作亦然。

操作完畢,現在我們想要把算好的資料放到原始資料的第四個欄位,
這裡使用 num2cell 轉換回去。

很多時候我們習慣直接打 mat2cell 來做轉換,通常會報錯。
mat2cell 的用法較為複雜,是專門設計來切分不同大小的 cell array 。

例如:

在這個範例中,mat2cell 可以允許使用者將原始的陣列以不同大小切開,分別放到 cell array 內。
若將上面範例中的 num2cell 改成 mat2cell 的話,寫法需改成:

newcol = mat2cell(trans .* 2, ones(length(trans), 1))

範例如下圖:

四、string(char) cell 與 array 間的轉換

下一個情境題,夏恩想要把每一筆訂單後面通通加上一個數字,
和剛剛一樣,cell 不能夠直接做陣列操作,因此需要經過轉換才可以。

把 cell array 拆開成 char or string array 的方法就是直接調用 char() 或 string() 就可以了。
反過來,若要把 char or string array 轉換成 cell array 的話,請使用 cellstr() 函數。

欸,等等...
使用 char() 或 string() 結果都一樣,那為什麼要分不同的函數勒?
別急。這個問題下一個部分會回答,先別管那麼多,看範例就是了。

string(char) cell 與 array 間的轉換,範例如下:

五、數字與文字間的轉換

數字轉文字,文字轉數字,這大概是最常見的問題了。
在一般的陣列中,我們可以直接使用 int2str 或 str2double ...等直接轉換整個陣列。
但是在 cell 中不允許這種操作,需要在中間加一層 cell2mat 之類的轉換函數才行。

在這個部分,夏恩也同時要介紹 char() 和 string() 在使用上的差異性。

再次出現情境題:夏恩想要把訂單數量改成文字格式,而非原本的數字格式,何解?
以下示範轉成 char 和轉成 string 的差別:

為了避免讓資料愈來愈亂,夏恩先把資料重新載入一遍,再來看兩者的差別。

看到紅線標起來的地方了嗎

眼尖的人可以發現:天啊!使用 char array 會多一個空格欸!!!!!

是的,這就是差別。

這個差別非常致命,尤其在進行字串比較的時候。
以上面紅線為例,程式執行字串比對時,' 968' 不等於 '968',因為多了個空白。

但實際上他們是一樣的東西!

這邊的重點絕對不是在強調誰好誰壞,每種資料格式都有其優缺點。
身為使用者的我們,責任就是了解每種資料格式的特性,並且挑選最符合需求的格式來用。

好的,處理完文字轉換後,再使用 cellstr 轉 string 為 cell。
最後,將整個欄位放到最後面,範例如下:

到這邊,我們已經成功地將數字轉換成文字了。

接著,再把剛才生出來的那一串文字轉成數字吧。

有沒有更簡單的寫法?

答案是...有的。

使用 cellfun 來幫助我們轉換吧!

% 數字轉字串
trans = cellfun(@num2str, data, 'UniformOutput', false);

% 字串轉數字
trans = cellfun(@str2double, data, 'UniformOutput', false);

一句話搞定。

小結

最後,再來複習一次,
也就是放在最前面的結論。

會用 cellfun 的話,請直接使用之;
若不會,則上述提供幾個方法供您參考:

1.在 cell array 中,把文字轉數字:
string() 或 char() > str2double() > num2cell()
拆cell > 轉換型態 > 回cell

2.在 cell array 中,數字轉文字:
cell2mat() > string() 或 char() > cellstr()
拆cell > 轉換型態 > 回cell

其實轉換的函數也就這麼幾個,用習慣了就不會搞混了。