一、孕婦建檔月份頻次統計
源資料樣本,為某醫院一段時間內的孕婦建檔時間
2015-04-22 10:12:52
2014-11-21 17:16:47
2013-12-16 17:35:44
2013-12-26 16:58:46
2013-12-27 16:44:33
2013-12-27 16:45:32
2013-12-30 8:26:20
2013-12-30 9:47:27
2013-12-30 8:46:42
2013-12-30 11:00:06
2013-12-30 11:08:42
分析目的:統計每個月的孕婦建檔頻次,這就要提取源資料的第一列,同擷取年月資料,然後做頻次直方圖,看孕婦建檔頻次有沒有隨月份變化的規律。
Matlab 程式碼:
%孕婦建檔日期統計 [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); f=cell2mat(datestr); f=f(:,1:7); f=tabulate(f); f=sortrows(f,1); bar(cell2mat(f(:,2)),1); set(gca,'XTickLabel',f(:,1),'XTick',[1:length(f(:,1))]); title( '孕婦建檔時間統計' );%下面的程式碼是為了旋轉橫座標軸標籤 xtb = get(gca,'XTickLabel');% 獲取橫座標軸標籤控制程式碼 xt = get(gca,'XTick');% 獲取橫座標軸刻度控制程式碼 yt = get(gca,'YTick'); % 獲取縱座標軸刻度控制程式碼 xtextp=xt;%每個標籤放置位置的橫座標 ytextp=yt(1)*ones(1,length(xt)); text(xtextp,ytextp,xtb,'HorizontalAlignment','right','VerticalAlignment','top','rotation',45,'fontsize',10); set(gca,'xticklabel','');% 將原有的標籤隱去
最終生成效果圖:
下面將對上面的 Matlab 程式碼進行分析。
1、讀取 txt 中的日期時間資料
如果 txt 中是兩列數值,譬如「1981 1986」,那隻需要用 M = load('shuzhi.txt') 就可讀取進 M 矩陣中,如下圖所示。
>> M = load('CoupleBirth.txt'); >> M(1:4,:) ans = 1981 1986 1988 1993 1985 1989 1984 1984
然後就可以用 M(:,1) 和 M(:,2) 訪問這兩列資料。
但本例中我們要讀取的不是數值資料,而是包含日期的字串,我們就不能再用 load 函式讀取了,要用 textread 函式。因為是兩列資料,就不能用 M=textread('PregnantWomanFileTime.txt','%s'); 來讀取了,如果硬要這樣讀,那日期和時間就會在返回的元胞陣列 M 中混到一塊,如下所示:
>> M=textread('PregnantWomanFileTime.txt','%s'); >> M(1:4) ans = '2015-04-22' '10:12:52' '2014-11-21' '17:16:47'
為了把兩列資料分別讀進兩個元胞陣列,要使用:
>> [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); >> datestr(1:4) ans = '2015-04-22' '2014-11-21' '2013-12-16' '2013-12-26'
textread 函式返回的是裝滿資料的元胞陣列,datestr 和 timestr 都是元胞陣列。
元胞陣列是MATLAB的一種特殊資料型別,可以將元胞陣列看做一種無所不包的通用矩陣。通過小括號()裡面加下標,訪問cell陣列中的資料,返回的是對應的cell。通過大括號{}裡面加下標,訪問cell陣列中的資料,返回的是對應cell的內容。
>> [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); >> datestr(1) ans = '2015-04-22' >> class(datestr(1)) ans = cell >> datestr{1} ans = 2015-04-22 >> class(datestr{1}) ans = char
2、從 2015-04-22 中提取出 2015-04 來
可以用正規表示式,但我們這裡使用矩陣的方法,正規表示式的方法我們後面介紹。目前 datestr 還是 cell 元胞陣列,我們先把元胞陣列轉成 char 矩陣,使用 cell2mat 函式。
>> [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); >> class(datestr) ans = cell >> f=cell2mat(datestr); >> class(f) ans = char >> f(1:4,:) ans = 2015-04-22 2014-11-21 2013-12-16 2013-12-26
然後對 char 矩陣提取所需字元即可。
>> f=f(:,1:7); >> f(1:4,:) ans = 2015-04 2014-11 2013-12 2013-12
3、統計月份的頻次
如果 f 是一維數值矩陣,那隻需要使用 hist 函式就可以了,但因為這裡要統計的是日期字元的頻次,hist 就不能用了。
>> hist(f) ??? Error using ==> hist Input arguments must be numeric.
還好 Matlab 提供了另一個類似的頻數統計函式 tabulate。
>> f=tabulate(f); >> f f = '2015-04' [1386] [6.4706] '2014-11' [ 582] [2.7171] '2013-12' [ 84] [0.3922] '2014-01' [ 766] [3.5761] '2014-09' [ 587] [2.7404] '2014-02' [ 616] [2.8758]
……
使用 sortrows 函式對根據第一列元素對 f 排序。
>> f=sortrows(f,1); >> f f = '2013-12' [ 84] [0.3922] '2014-01' [ 766] [3.5761] '2014-02' [ 616] [2.8758] '2014-03' [1000] [4.6685] '2014-04' [ 977] [4.5612] '2014-05' [ 948] [4.4258] '2014-06' [ 961] [4.4865]
4、繪直方圖
繪圖就很簡單了,bar 函式就可以。首先我們要 f 轉成一維矩陣,因為上面 tabulate 返回的是元胞陣列。轉成行矩陣、列矩陣均可。然後再呼叫 bar 繪製 f 第二列的資料圖,並使用 f 的第一列設定 x 軸標籤,再加上 Title。
>> bar(cell2mat(f(:,2)),1); >> set(gca,'XTickLabel',f(:,1),'XTick',[1:length(f(:,1))]); >> title( '孕婦建檔時間統計' );%下面的程式碼是為了旋轉橫座標軸標籤
本來到這裡繪圖可以算完成了,但是,看看 x 軸標籤擁擠得,完全沒法看,所以需要對 x 軸標籤的顯示進行下調整。需要旋轉 x 軸標籤了,才發現強大的 Matlab 實現這個功能竟然這麼麻煩,需要通過下一小節來說明。
5、旋轉 x 軸標籤
下面是旋轉 x 軸標籤的程式碼,當時找這段程式碼比較煩惱,因為實在不能相信 Matlab 旋轉個標籤都這麼麻煩。其實這段程式碼也很簡單,就是獲取 x 軸標籤控制程式碼,並設定到相應的位置,然後將原有標籤隱去。xt 和 yt 不重要,只是用了下 xt 的長度和 yt(1) 的 0 值。xtb 是標籤內容,xtextp 和 ytextp 是標籤位置座標。text 函式可查閱相關手冊瞭解。
xtb = get(gca,'XTickLabel');% 獲取橫座標軸標籤控制程式碼 xt = get(gca,'XTick');% 獲取橫座標軸刻度控制程式碼 yt = get(gca,'YTick'); % 獲取縱座標軸刻度控制程式碼 xtextp=xt;%每個標籤放置位置的橫座標 ytextp=yt(1)*ones(1,length(xt)); text(xtextp,ytextp,xtb,'HorizontalAlignment','right','VerticalAlignment','top','rotation',45,'fontsize',10); set(gca,'xticklabel','');% 將原有的標籤隱去
最終圖形顯示如第一張圖所示。
二、孕婦建檔某一月頻次統計
上面的例子選取的第一列的所有資料,只是提取了每個資料的年月。現在要統計某一個月份的資料,就要對資料進行過濾。這裡我們使用正規表示式進行過濾,程式碼如下。繪圖程式碼跟上面一樣。
%孕婦建檔時間一個月內 [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); k=regexp(datestr,'^2015-07.*$', 'match'); ix=~cellfun('isempty',k); index=find(ix~=0); f=datestr(index); f=tabulate(f); f=sortrows(f,1); bar(cell2mat(f(:,2)),1); set(gca,'XTickLabel',f(:,1),'XTick',[1:length(f(:,1))]); title( '孕婦建檔時間一個月內' );%下面的程式碼是為了旋轉橫座標軸標籤 xtb = get(gca,'XTickLabel');% 獲取橫座標軸標籤控制程式碼 xt = get(gca,'XTick');% 獲取橫座標軸刻度控制程式碼 yt = get(gca,'YTick'); % 獲取縱座標軸刻度控制程式碼 xtextp=xt;%每個標籤放置位置的橫座標 ytextp=yt(1)*ones(1,length(xt)); text(xtextp,ytextp,xtb,'HorizontalAlignment','right','VerticalAlignment','top','rotation',45,'fontsize',10); set(gca,'xticklabel','');% 將原有的標籤隱去
生成的圖形如下:
下面對上面使用正規表示式的程式碼進行解析。
k=regexp(datestr,'^2015-07.*$', 'match');
regexp 查詢每個元素中匹配字元的位置並返回,k 的值擷取如下:
{1x1 cell}
{1x1 cell}
{1x1 cell}
{1x1 cell}
{1x1 cell}
{}
{}
{}
{}
程式碼 ix=~cellfun('isempty',k) 是判斷元胞陣列中的元素是否為空,ix 的值擷取如下:
1 1 1 0 0 0
index=find(ix~=0) 是找到上面元胞陣列中不為空的元素座標,這是根據正規表示式提取資料很重要的一步,很有技巧。index 的值擷取如下:
>> index=find(ix~=0); >> index index = 11269 11287 11597 11672 11695
下面就需要根據上面的 index 提取相應的資料了。會者不難,難者不會。
>> f=datestr(index); >> f f = '2015-07-07' '2015-07-09' '2015-07-15' '2015-07-06'
繪圖功能跟上面一樣。
三、孕婦建檔時間一天內統計
對一天內的孕婦建檔頻次進行統計。
[datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); f=regexprep(timestr,':\d+:\d+$',''); f=str2num(char(f));%這個程式碼可是幾經坎坷 hist(f); title( '孕婦建檔時間一天內頻次統計' );
生成圖形如下:
程式碼解析如下:
f=regexprep(timestr,':\d+:\d+$','') 是把時間列的分和秒都去掉,返回的就是小時。原理是用 regexprep 把時間的分秒都替換成空,剩下的就是小時。
>> f=regexprep(timestr,':\d+:\d+$',''); >> f(1:4) ans = '10' '17' '17' '16'
下面就是要想辦法把 f 中表示小時的字元轉換成數值型別,因為如果跟上面一樣用 tabulate 進行統計,並使用 sortrows 排序時,出發生把 8 排在 12 後面的情況,而這裡正好又都是數值型別,我們何不直接轉換成數值,然後用 hist 呢?
>> [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); f=regexprep(timestr,':\d+:\d+$',''); >> f(1:4) ans = '10' '17' '17' '16' >> f=str2num(char(f));%這個程式碼可是幾經坎坷 >> f(1:4) ans = 10 17 17 16
其中 f=str2num(char(f)) 這個程式碼找得我好苦。因為起初我想到用 cell2mat 把元胞陣列內的字元轉換成數值,結果是這樣的。
>> [datestr,timestr]=textread('PregnantWomanFileTime.txt','%s%s'); f=regexprep(timestr,':\d+:\d+$',''); >> f(1:4) ans = '10' '17' '17' '16' >> abc=cell2mat(f) ??? Error using ==> cat CAT arguments dimensions are not consistent. Error in ==> cell2mat at 95 m = cat(1,m{:}); >> abc=cell2mat(f') abc = 10171716161689811……
無力吐槽……
後來終於找到正確的轉換方式:f=str2num(char(f))
後面的繪圖,直接用 hist,就沒什麼難度了。