R 中的矩阵函数:创建、打印、添加列和切片

⚡ 智能摘要

R 语言中的矩阵是一个二维数组,它包含 m 行 n 列,每种数据类型只占 1000 行。矩阵由 matrix() 函数构建,通过 cbind() 和 rbind() 函数扩展,并通过方括号访问。

  • 🧩 结构体: 矩阵是具有维度属性的向量,因此每个单元格必须共享一种数据类型。
  • 🛠️ 创建: matrix(data, nrow, ncol, byrow) 排列一个序列,R 推断缺失的维度。
  • 🔄 完成订单: byrow = FALSE 表示按列填充,而 byrow = TRUE 表示按行填充。
  • 成长: cbind() 添加列,rbind() 添加行,前提是共享维度匹配。
  • 切片: m[row, column] 首先读取行,空白侧选择该侧的所有内容。
  • 🏷️ 标签: dimnames、rownames() 和 colnames() 将 [,1] 占位符替换为可读的名称。
  • ➕➖ 算术: 星号表示元素逐个相乘,而 %*% 表示矩阵乘法。

R 语言中的矩阵函数:创建、打印、添加列和切片

R 中的矩阵函数

R 中的矩阵函数是一个二维数组,有 m 行和 n 列。换句话说,R 编程中的矩阵是两个或多个具有相同数据类型的向量的组合。

本质上,矩阵就是一个带有长度为 2 的 dim 属性的向量。这就是为什么每个元素必须只属于一种类型:一旦字符值与数字连接,整个矩阵就会被强制转换为字符型。R 将这些值按列存储在单个数组中,并使用 dim 属性来确定每一行的结束位置,因此选择合适的 dim 属性至关重要。 数据类型 一次性应用于整个对象。

注意: `matrix()` 函数本身总是返回二维数据。要在 R 语言中构建三维或更高维度的结构,可以使用带有 `dim` 向量的 `array()` 函数,或者直接使用 `dim()` 函数赋值。下图展示了所有矩阵遵循的行和列布局。

R语言中矩阵函数的行和列布局

如何在 R 中创建矩阵

我们可以使用函数创建一个矩阵。 矩阵(). 基本 R 函数签名接受五个参数,以下列出其中最常用的三个:

matrix(data, nrow, ncol, byrow = FALSE)

参数:

  • data:R 将排列成矩阵的行和列的元素集合。
  • 行数。
  • 恩科尔列数。
  • 拜罗:一个逻辑标志。默认值为 FALSE 时,矩阵按列从上到下填充;默认值为 TRUE 时,矩阵按行从左到右填充。
  • 维度名称:一个长度为 2 的可选列表,用于提供行名和列名。

在看第一个示例之前,需要了解 R 基础参考文档中的两个细节。如果只指定了 nrow 和 ncol 中的一个,R 会根据数据长度推断另一个。如果数据元素太少,无法填充所需的形状,R 会回收利用这些值,而不是直接丢弃。

让我们用 1 到 10 的数字序列构造两个 5×2 矩阵,一个 byrow = TRUE,一个 byrow = FALSE,看看有什么区别。

# Construct a matrix with 5 rows that contain the numbers 1 up to 10 and byrow =  TRUE 
matrix_a <-matrix(1:10, byrow = TRUE, nrow = 5)
matrix_a

输出:

因为使用了 byrow = TRUE,所以控制台会在第一行填充 1 和 2,在第二行填充 3 和 4,依此类推。

控制台输出矩阵_a逐行填充,且byrow = TRUE

现在,让我们使用 dim() 打印 R 中矩阵的维度。使用 dim() 在 R 中打印矩阵的语法是:

# Print dimension of the matrix with dim()
dim(matrix_a)

输出:

## [1] 5 2

dim() 首先返回行数,然后返回列数,证实了 5×2 的形状。

按列填充矩阵,byrow = FALSE

同样的十个数字和同样的行数,一旦填充方向改变,就会产生不同的排列方式。基ping 按行模式默认会将值向下移动到第一列,然后再移动到第二列。

# Construct a matrix with 5 rows that contain the numbers 1 up to 10 and byrow =  FALSE
matrix_b <-matrix(1:10, byrow = FALSE, nrow = 5)
matrix_b

输出:

控制台输出矩阵 matrix_b 按列填充,byrow = FALSE

再次使用 dim() 打印矩阵的维度。以下是 R 打印矩阵维度的语法:

# Print dimension of the matrix with dim()
dim(matrix_b)

输出:

## [1] 5 2

5×2 的形状保持不变,因为 byrow 改变的是填充顺序,而不是尺寸。

注意:使用命令 matrix_b <-matrix(1:10, byrow = FALSE, ncol = 2) 将产生与上述相同的效果,因为 R 会从提供的十个值推断出 nrow = 5。

您还可以使用 `ncol` 函数创建一个 4×3 的矩阵。R 将创建 3 列,并从上到下填充每一列。请查看示例。

matrix_c <-matrix(1:12, byrow = FALSE, ncol = 3)
matrix_c

输出:

##       [,1] [,2] [,3]
## [1,]    1    5    9
## [2,]    2    6   10
## [3,]    3    7   11
## [4,]    4    8   12

列标题 [,1] 到 [,3] 和行标签 [1,] 到 [4,] 是 R 的默认占位符。一旦提供了实际的维度名称,它们就会消失,正如本教程后面所示。

计费示例:

dim(matrix_c)

输出:

## [1] 4 3

使用 cbind() 向矩阵添加列

您可以使用 `cbind()` 命令向 R 矩阵添加列。`cbind()` 表示列绑定,它可以连接指定数量的矩阵或列。例如,我们之前的示例创建了一个 5×2 的矩阵。我们连接第三列,并验证其维度变为 5×3。

计费示例:

# concatenate c(1:5) to the matrix_a
matrix_a1 <- cbind(matrix_a, c(1:5))
# Check the dimension
dim(matrix_a1)

输出:

## [1] 5 3

计费示例:

matrix_a1

输出

##       [,1] [,2] [,3]
## [1,]    1    2    1
## [2,]    3    4    2
## [3,]    5    6    3
## [4,]    7    8    4
## [5,]    9   10    5

计费示例:

我们还可以同时绑定多列。下一个代码块构建矩阵 matrix_a2,这是一个 4×3 的矩阵,包含数字 13 到 24,以便将其与 4×3 的矩阵 matrix_c 连接,生成一个 4×6 的结果,涵盖 1 到 24。

matrix_a2 <-matrix(13:24, byrow = FALSE, ncol = 3)

输出:

##      [,1] [,2] [,3]
## [1,]   13   17   21
## [2,]   14   18   22
## [3,]   15   19   23
## [4,]   16   20   24

计费示例:

matrix_c <-matrix(1:12, byrow = FALSE, ncol = 3)		
matrix_d <- cbind(matrix_a2, matrix_c)
dim(matrix_d)

输出:

## [1] 4 6

注意在 R 语言中,矩阵的行数必须相等,cbind() 函数才能正常工作。如果行数不同,R 要么会重用较短的输入,要么会抛出错误,因此,先检查两个对象的 dim() 值是否相等是更稳妥的做法。

cbind() 连接列,rbind() 连接行。让我们向 matrix_c 矩阵添加一行,并验证其维度是否为 5×3。

matrix_c <-matrix(1:12, byrow = FALSE, ncol = 3)
# Create a vector of 3 columns
add_row <- c(1:3)
# Append to the matrix
matrix_c <- rbind(matrix_c, add_row)
# Check the dimension
dim(matrix_c)

输出:

## [1] 5 3

请注意,绑定一个命名向量(例如 add_row)也会给新行赋予该名称,这是迈向下文将要介绍的带标签矩阵的第一步。

矩阵切片

我们可以从矩阵中选择一个或多个元素。 R编程 使用方括号 [ ] 即可。在方括号内,行选择器在前,列选择器在后,两者之间用逗号分隔。这就是切片操作的用武之地。

例如:

  • matrix_c[1,2] 选择第一行第二列的元素。
  • matrix_c[1:3,2:3] 的结果是一个 R 切片矩阵,其中数据位于第 1、2、3 行和第 2、3 列。
  • matrix_c[,1] 选择第一列的所有元素。
  • matrix_c[1,] 选择第一行的所有元素。

因此,逗号一侧留空意味着该侧的所有值都将被保留。但有一个容易让初学者犯错的地方:当选择单行或单列时,R 会丢弃空的维度,并返回一个普通的向量。添加 `drop = FALSE`,例如 `matrix_c[1, , drop = FALSE]`,可以保持结果为矩阵。

以下是上述代码的输出

R语言中四个矩阵切片表达式的控制台结果

在 R 语言中,如何命名矩阵的行和列?

默认标签(例如 [,1] 和 [3,])会使矩阵的输出难以阅读,尤其是在矩阵具有实际含义的情况下。`dimnames` 参数以及 `rownames()` 和 `colnames()` 替换函数会为矩阵添加文本标签,这些标签会随矩阵一起经过 `cbind()`、`t()` 以及所有切片操作。

# Name the rows and columns while the matrix is built
sales <- matrix(1:6, nrow = 2, ncol = 3,
                dimnames = list(c('north', 'south'), c('q1', 'q2', 'q3')))

# Or attach the names afterwards
rownames(sales) <- c('north', 'south')
colnames(sales) <- c('q1', 'q2', 'q3')

# Read the names back as a list of two character vectors
dimnames(sales)

# Names make label based slicing possible
sales['north', 'q2']
功能 套数
dimnames(m) 两个维度都表示为两个向量的列表 dimnames(m) <- list(rows, cols)
行名(m) 行标签 rownames(m) <- rows
colnames(m) 列标签 colnames(m) <- cols
dim(m) 行和列用两个整数表示 dim(m) <- c(nrow, ncol)

一旦标签存在,`sales['north', 'q2']` 比 `sales[1, 2]` 清晰得多,并且在行重新排序后仍然有效。将 `dimnames` 组件设置为 NULL 会再次移除这组标签,而使用 `as.data.frame()` 转换的矩阵会将行名和列名直接带入数据框中。 数据框.

矩阵 OperaR 语言中的运算:算术、转置和乘法

矩阵运算正是单类型规则发挥作用的地方。R 基础包无需额外包即可处理所有类型,但有两个运算符容易混淆:* 表示元素逐个相乘,而 %*% 执行的是真正的矩阵乘法,并且要求左操作数的列与右操作数的行完全匹配。

m1 <- matrix(1:4, nrow = 2)
m2 <- matrix(5:8, nrow = 2)

m1 + m2          # element by element addition
m1 * m2          # element by element product, NOT matrix multiplication
m1 %*% m2        # true matrix multiplication
t(m1)            # transpose: rows become columns
solve(m1)        # inverse, for a square matrix that is not singular

rowSums(m1)      # one total per row
colMeans(m1)     # one mean per column
apply(m1, 1, max)   # any function, applied row by row
  • t(m):转置矩阵,使元素 [i, j] 变为 [j, i]。维度名称保持不变。
  • 求解(m)返回方阵、非奇异矩阵的逆矩阵,solve(a, b) 求解线性系统。
  • 行总和 / 列总和 / 行均值 / 列均值:文档显示其等效于使用 sum 或 mean 的 apply() 函数,但速度要快得多。
  • apply(m, MARGIN, FUN)对于您提供的任何函数,MARGIN = 1 遍历行,MARGIN = 2 遍历列。
  • 诊断,检测,交叉产品:对角线、行列式和 t(x) %*% y 的更快形式。

由于这些操作是向量化的,它们取代了循环,而不是嵌套在循环内部。原本需要对数千个单元格进行嵌套 for 循环才能完成的汇总,现在只需调用一次 colMeans() 函数即可,这在数据量增长时尤为重要。

R语言中的矩阵、数据框和数组的区别

矩阵、数据框和数组在控制台中看起来都是矩​​形的,但它们回答的问题却各不相同。表格将它们并排列出。

特性 矩阵 数据框 排列
尺寸 恰好2 恰好2 任何数字
列类型 整个对象使用一种类型 每列不同类型的 整个对象使用一种类型
内置 矩阵() 数据框() 阵列()
典型用途 数值计算和线性代数 混合观测数据 堆叠表,例如按年份计数
行标签 可选的维度名称 行名称始终存在 可选的维度名称
# A matrix holds one type only, so mixing coerces everything to character
mixed <- matrix(c(1, 2, 'a', 'b'), nrow = 2)
class(mixed[1, 1])

# Convert between the structures
as.data.frame(matrix_c)
as.matrix(mtcars)

# A matrix is the two dimensional case of an array
is.matrix(matrix_c)
inherits(matrix_c, 'array')

当每个单元格中的数字类型相同且运算只是算术运算时,就应该使用矩阵。 数据框 当列包含不同类型的数据时,例如,字符型名称旁边是数值型价格,而其他列则包含数字型价格。 因素伸手去拿 名单 当各个部分长度不同,或者数组中确实存在诸如时间或地区之类的第三个索引时,使用 `as.matrix()` 和 `as.data.frame()` 进行双向转换的成本都很低,因此数据结构可以跟随任务,而不是反过来。

常见问题

R 会重复使用数据值而不是丢弃它们,因此 `matrix(1:3, nrow = 2, ncol = 3)` 会重复序列。只有当长度不是单元格数量的整数倍时才会出现警告,这使得静默重复使用数据成为一个很容易被忽略的错误。

使用负索引:m[-2, ] 删除第二行,m[, -3] 删除第三列。可以使用 m[-c(1, 4), ] 一次删除多个行。在将结果赋值给原始对象之前,原始对象不会改变。

默认情况下,选择单行或单列会删除空维度。添加 `drop = FALSE`,例如 `m[1, , drop = FALSE]`,可以保留单行矩阵。当结果传递给需要二维矩阵的函数时,这一点很重要。

`which(m == value, arr.ind = TRUE)` 返回一个两列的结果,分别给出每个匹配项的行号和列号。如果没有 `arr.ind`,结果将是一个按列向下计数的线性索引,这通常不是你想要的。

使用 `array(data, dim = c(rows, columns, layers))` 或直接对向量赋值 `dim(x)`。切片操作需要每个维度一个索引,例如 `a[2, 3, 1]`。矩阵本质上是二维数组。

是的。R 基础参考手册指出,rowSums 和 colMeans 等价于使用 apply() 函数并传入 sum 或 mean,但速度更快,而且它们都优于显式的 for 循环,因为迭代是在编译后的代码中发生的,而不是在解释器中发生的。

模型拟合本质上是线性代数:特征构成矩阵,系数构成向量,预测结果则是一个简单的乘积。 机器学习 因此,这些软件包需要数值矩阵而不是数据框作为输入。

是的。 GitHub 副驾驶 可在 RStudio 2023.09.0 及更高版本中运行,并能根据打开文件中的注释补全代码。请检查其维度逻辑。 RStudio因为错误的行数仍然会产生一个有效的矩阵。

总结一下这篇文章: