• Matlab 日期频次统计


    一、孕妇建档月份频次统计

    源数据样本,为某医院一段时间内的孕妇建档时间

    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,就没什么难度了。

  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/NaughtyBaby/p/4859511.html
Copyright © 2020-2023  润新知