R 学习笔记(2) -- 矩阵和数组

作者: wangpeng905 | 来源:发表于2017-03-29 09:04 被阅读54次

    矩阵和数组是向量的两种特例

    矩阵在 R 中是按列(column)存储的,但是通过设置 matrix 的参数 byrow 为 TRUE 可以将矩阵元素按照行排列,矩阵本身仍是按列存储的。

    > y <- matrix(c(1,2,3,4,5,6),nrow=2)
    > y
         [,1] [,2] [,3]
    [1,]    1    3    5
    [2,]    2    4    6
    > y <- matrix(c(1,2,3,4,5,6),nrow=2,byrow=T)
    > y
         [,1] [,2] [,3]
    [1,]    1    2    3
    [2,]    4    5    6
    

    可以对一个矩阵的子矩阵索引赋值:

    > y
         [,1] [,2]
    [1,]    1    4
    [2,]    2    5
    [3,]    3    6
    > y[c(1,3),]
         [,1] [,2]
    [1,]    1    4
    [2,]    3    6
    > y[c(1,3),] <- matrix(c(1,1,8,12),nrow=2)
    > y
         [,1] [,2]
    [1,]    1    8
    [2,]    2    5
    [3,]    1   12
    

    对向量的负索引可以排除元素(类似取反),对矩阵同样有效:

    > y
         [,1] [,2]
    [1,]    1    4
    [2,]    2    5
    [3,]    3    6
    > y[-2,]
         [,1] [,2]
    [1,]    1    4
    [2,]    3    6
    

    矩阵也可以用类似向量筛选的方法进行筛选:

    > x
         [,1] [,2]
    [1,]    1    2
    [2,]    2    3
    [3,]    3    4
    > x[x[,2]>=3,]
         [,1] [,2]
    [1,]    2    3
    [2,]    3    4
    

    apply() 函数

    apply() 函数的一般形式为:

    apply(m, dimcode, f, fargs)
    

    m 为矩阵
    dimcode 为维度编号,1 代表对每一行应用 f 函数,2 代表对每一列应用 f 函数。
    f 为函数
    fargs 为函数的可选参数集。
    使用 apply() 函数可以让程序更加紧凑易读,同时避免循环语句可能产生的 bug。


    增加或删除矩阵的行和列

    严格来说,矩阵的长度和维度是固定的,不能删除或增加行和列,但可以通过为矩阵重新赋值达到相同的效果。
    函数 rbind() 按行组合,cbind() 按列组合,可以为矩阵增加行和列:

    > z
         [,1] [,2] [,3]
    [1,]    1    1    1
    [2,]    2    1    0
    [3,]    3    0    1
    [4,]    4    0    0
    > one
    [1] 1 1 1 1
    > two
    [1] 2 2 2
    > cbind(one, z)
         one      
    [1,]   1 1 1 1
    [2,]   1 2 1 0
    [3,]   1 3 0 1
    [4,]   1 4 0 0
    > rbind(two,z)
        [,1] [,2] [,3]
    two    2    2    2
           1    1    1
           2    1    0
           3    0    1
           4    0    0
    

    使用 rbind 和 cbind 会生成新的矩阵,如果在循环中频繁生成新矩阵,是会很耗时的,最好一开始定义好一个大矩阵,每次循环时逐行或逐列进行赋值,以避免每次循环时进行耗时的矩阵内存分配。


    向量与矩阵的差异

    矩阵比向量多了两个属性,行数和列数:

    > z <- matrix(1:8,nrow=4)
    > z
         [,1] [,2]
    [1,]    1    5
    [2,]    2    6
    [3,]    3    7
    [4,]    4    8
    > length(z)
    [1] 8
    > typeof(z)
    [1] "integer"
    > class(z)
    [1] "matrix"
    > attributes(z)
    $dim
    [1] 4 2
    > dim(z)
    [1] 4 2
    > nrow(z)
    [1] 4
    > ncol(z)
    [1] 2
    > nrow
    function (x) 
    dim(x)[1L]
    <bytecode: 0x2335e18>
    <environment: namespace:base>
    

    避免意外降维

    对一个矩阵取子集,比如取某一行,结果会变成向量:

    > z
         [,1] [,2]
    [1,]    1    5
    [2,]    2    6
    [3,]    3    7
    [4,]    4    8
    > r <- z[2,]
    > r
    [1] 2 6
    > class(r)
    [1] "integer"
    > attributes(r)
    NULL
    > attributes(z)
    $dim
    [1] 4 2
    > str(r)
     int [1:2] 2 6
    > str(z)
     int [1:4, 1:2] 1 2 3 4 5 6 7 8
    

    r 变成了向量,在某些矩阵运算是可能产生错误,为了避免意外降维可以使用 drop 参数:

    > r <- z[2,, drop=FALSE]
    > r
         [,1] [,2]
    [1,]    2    6
    > dim(r)
    [1] 1 2
    

    这时 r 是一个 1 x 2 的矩阵,而不是向量。
    对原本就是向量的对象,可以用 as.matrix() 转化为矩阵:

    > u
    [1] 1 2 3
    > v <- as.matrix(u)
    > attributes(u)
    NULL
    > attributes(v)
    $dim
    [1] 3 1
    
    

    矩阵的行和列命名问题

    访问矩阵元素最直接的方法是通过行号和列号,但是也可以用行名和列名,在分析某些数据时很有用,colnames() 和 rownames() 函数。

    > z
         [,1] [,2]
    [1,]    1    3
    [2,]    2    4
    > colnames(z)
    NULL
    > colnames(z) <- c('a','b')
    > z
         a b
    [1,] 1 3
    [2,] 2 4
    > colnames(z)
    [1] "a" "b"
    > z[,'a']
    [1] 1 2
    

    高维数组

    矩阵只有行和列两个维度,举个例子,学生成绩,有三个学生,考试分两部分,考试成绩每一行代表一个学生,第一个学生两部分考试得分分别是46和30:

    > firsttest
         [,1] [,2]
    [1,]   46   30
    [2,]   21   25
    [3,]   50   50
    

    如果还有第二次考试,成绩如下:

    > secondtest
         [,1] [,2]
    [1,]   46   43
    [2,]   41   35
    [3,]   50   50
    

    现在把两次考试的成绩合并到一个数据结构中,命名为 tests,这种数据结构就是数组。用 array() 函数创建这个数据结构:

    > tests <- array(data=c(firsttest,secondtest), dim=c(3,2,2))
    > tests
    , , 1
    
         [,1] [,2]
    [1,]   46   30
    [2,]   21   25
    [3,]   50   50
    
    , , 2
    
         [,1] [,2]
    [1,]   46   43
    [2,]   41   35
    [3,]   50   50
    
    > attributes(tests)
    $dim
    [1] 3 2 2
    

    dim=c(3,2,2) 是指这个数据有两层,每层有三行两列。
    tests 中每一个元素都有三个下标,比矩阵多一个,三个下标顺序与 $dim 中三个元素相同。例如第 3 个学生在第 1 次考试的第 2 部分得分:

    > tests[3,2,1]
    [1] 50
    

    两个矩阵可以合并为一个三维数组,两个或者多个三维数组可以合并成一个四维数组。


    把理想运用到真实的事物上,便有了文明。

    相关文章

      网友评论

      • 谢俊飞:写的真好,很多新鲜的知识点

      本文标题:R 学习笔记(2) -- 矩阵和数组

      本文链接:https://www.haomeiwen.com/subject/coqeottx.html