完全指南:创建、操作与实战示例)
1. 引言在 R 语言中数组Array是一种重要的数据结构用于存储多维数据。与向量Vector和矩阵Matrix相比数组可以拥有两个以上的维度非常适合处理多维表格、图像数据、时间序列等多维场景。本文将系统介绍 R 数组的创建、索引、运算和实际应用并提供丰富的可运行代码示例。2. 数组的基本概念数组是 R 中用于存储同类型元素的多维数据结构。它的核心特点包括多维性数组可以是一维、二维、三维甚至更高维度。同质性数组中的所有元素必须是相同的数据类型如数值、字符、逻辑值。维度属性每个数组都有一个dim属性用于描述各维度的大小。从本质上讲矩阵是二维数组的特例而向量可以看作一维数组。理解数组有助于掌握 R 中更复杂的数据操作。3. 创建数组在 R 中最常用的创建数组的函数是array()。其基本语法为array(data, dim length(data), dimnames NULL)data要填充到数组中的数据通常是向量。dim指定数组各维度大小的整数向量。dimnames可选参数用于给各维度命名。3.1 创建一维数组一维数组本质上等同于向量但显式指定维度后即为数组# 创建一维数组 arr1 - array(1:6, dim 6) print(arr1) # 输出: [1] 1 2 3 4 5 6 查看维度 dim(arr1) # 输出: [1] 63.2 创建二维数组矩阵二维数组即矩阵通过dim c(行数, 列数)指定# 创建 2 行 3 列的二维数组 arr2 - array(1:6, dim c(2, 3)) print(arr2) # [,1] [,2] [,3] # [1,] 1 3 5 # [2,] 2 4 6 查看维度 dim(arr2) # 输出: [1] 2 3注意R 默认按列填充数据即先填满第一列再填第二列以此类推。3.3 创建三维数组三维数组是数组最典型的应用场景例如存储多个矩阵的堆叠# 创建 2 行 3 列 2 层的三维数组 arr3 - array(1:12, dim c(2, 3, 2)) print(arr3) # , , 1 # # [,1] [,2] [,3] # [1,] 1 3 5 # [2,] 2 4 6 # # , , 2 # # [,1] [,2] [,3] # [1,] 7 9 11 # [2,] 8 10 12 查看维度 dim(arr3) # 输出: [1] 2 3 23.4 使用 dim() 将向量转换为数组除了array()函数还可以通过给向量添加dim属性来创建数组# 先创建向量 vec - 1:8 通过 dim() 赋予维度属性 dim(vec) - c(2, 2, 2) print(vec) , , 1 [,1] [,2] [1,] 1 3 [2,] 2 4 , , 2 [,1] [,2] [1,] 5 7 [2,] 6 83.5 为数组添加维度名称使用dimnames参数可以为各维度命名使数据更易读# 创建带维度名称的三维数组 arr_named - array( 1:12, dim c(2, 3, 2), dimnames list( 行 c(行1, 行2), 列 c(列A, 列B, 列C), 层 c(第一层, 第二层) ) ) print(arr_named) # , , 层 第一层 # # 列 # 行 列A 列B 列C # 行1 1 3 5 # 行2 2 4 6 # # , , 层 第二层 # # 列 # 行 列A 列B 列C # 行1 7 9 11 # 行2 8 10 124. 数组的索引与访问数组的索引方式与矩阵类似通过方括号[]指定各维度的下标。三维数组的索引格式为数组[行, 列, 层]。4.1 访问单个元素arr - array(1:12, dim c(2, 3, 2)) 访问第 1 行、第 2 列、第 1 层的元素 arr[1, 2, 1] # 输出: [1] 3 访问第 2 行、第 3 列、第 2 层的元素 arr[2, 3, 2] # 输出: [1] 124.2 访问整行、整列或整层arr - array(1:12, dim c(2, 3, 2)) 访问第 1 层的所有元素即整个矩阵 arr[, , 1] [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 访问第 1 层第 2 列的所有行 arr[, 2, 1] # 输出: [1] 3 4 访问第 2 行第 1 层的所有列 arr[2, , 1] # 输出: [1] 2 4 64.3 使用维度名称索引如果创建数组时指定了维度名称可以直接用名称访问arr_named - array( 1:12, dim c(2, 3, 2), dimnames list( 行 c(行1, 行2), 列 c(列A, 列B, 列C), 层 c(第一层, 第二层) ) ) 按名称访问 arr_named[行1, 列B, 第一层] # 输出: [1] 3 arr_named[行2, , 第二层] # 输出: 列A 列B 列C # 8 10 124.4 使用向量索引多个元素arr - array(1:12, dim c(2, 3, 2)) 访问第 1 层第 1 行和第 2 行的第 1、3 列 arr[c(1, 2), c(1, 3), 1] [,1] [,2] [1,] 1 5 [2,] 2 65. 数组的常用操作5.1 查看数组的维度与长度arr - array(1:24, dim c(2, 3, 4)) 查看维度 dim(arr) # 输出: [1] 2 3 4 查看元素总个数 length(arr) # 输出: [1] 24 查看维度名称 dimnames(arr) # 输出: NULL未命名时5.2 数组的算术运算数组支持与标量、向量以及其他数组的算术运算遵循 R 的循环规则arr - array(1:12, dim c(2, 3, 2)) 与标量运算 arr 10 , , 1 [,1] [,2] [,3] [1,] 11 13 15 [2,] 12 14 16 , , 2 [,1] [,2] [,3] [1,] 17 19 21 [2,] 18 20 22 两个相同维度的数组相加 arr2 - array(rep(1, 12), dim c(2, 3, 2)) arr arr2 , , 1 [,1] [,2] [,3] [1,] 2 4 6 [2,] 3 5 7 , , 2 [,1] [,2] [,3] [1,] 8 10 12 [2,] 9 11 135.3 数组的汇总统计arr - array(1:12, dim c(2, 3, 2)) 求和 sum(arr) # 输出: [1] 78 平均值 mean(arr) # 输出: [1] 6.5 最大值与最小值 max(arr) # 输出: [1] 12 min(arr) # 输出: [1] 1 按维度求和margin 1 表示按行2 表示按列3 表示按层 apply(arr, 1, sum) # 按行求和输出: [1] 36 42 apply(arr, 2, sum) # 按列求和输出: [1] 18 22 26 apply(arr, 3, sum) # 按层求和输出: [1] 21 575.4 使用 apply() 进行维度运算apply()函数是数组操作的核心工具可以对指定维度应用任意函数arr - array(1:12, dim c(2, 3, 2)) 计算每一层的平均值 apply(arr, 3, mean) 输出: [1] 3.5 9.5 计算每一列的标准差 apply(arr, 2, sd) 输出: [1] 3.559026 3.559026 3.559026 自定义函数计算每一行的最大值与最小值之差 apply(arr, 1, function(x) max(x) - min(x)) 输出: [1] 10 105.5 数组的转置使用aperm()函数可以重新排列数组的维度顺序arr - array(1:12, dim c(2, 3, 2)) 将维度顺序从 (行, 列, 层) 调整为 (层, 行, 列) arr_t - aperm(arr, c(3, 1, 2)) dim(arr_t) # 输出: [1] 2 2 3 print(arr_t) , , 1 [,1] [,2] [1,] 1 2 [2,] 7 8 , , 2 [,1] [,2] [1,] 3 4 [2,] 9 10 , , 3 [,1] [,2] [1,] 5 6 [2,] 11 126. 数组与矩阵、向量的转换6.1 数组转换为矩阵arr - array(1:12, dim c(2, 3, 2)) 将三维数组转换为矩阵按层合并 mat - matrix(arr, nrow dim(arr)[1] * dim(arr)[3], ncol dim(arr)[2]) print(mat) [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 [3,] 7 9 11 [4,] 8 10 126.2 矩阵转换为数组mat - matrix(1:12, nrow 4, ncol 3) 将矩阵转换为三维数组 arr - array(mat, dim c(2, 2, 3)) print(arr) , , 1 [,1] [,2] [1,] 1 3 [2,] 2 4 , , 2 [,1] [,2] [1,] 5 7 [2,] 6 8 , , 3 [,1] [,2] [1,] 9 11 [2,] 10 126.3 数组转换为向量arr - array(1:12, dim c(2, 3, 2)) 使用 as.vector() 或 c() 展平数组 vec - as.vector(arr) print(vec) 输出: [1] 1 2 3 4 5 6 7 8 9 10 11 127. 实战案例7.1 案例一学生成绩多维分析假设有 3 个班级每个班级 4 名学生参加了 3 门考试可以用三维数组存储数据# 生成模拟成绩数据3 个班级 × 4 名学生 × 3 门课程 set.seed(42) scores - array( round(runif(36, 60, 100)), dim c(4, 3, 3), dimnames list( 学生 c(张三, 李四, 王五, 赵六), 课程 c(数学, 语文, 英语), 班级 c(一班, 二班, 三班) ) ) print(scores) 计算每个班级的平均分 班级平均分 - apply(scores, 3, mean) print(班级平均分) 一班 二班 三班 82.50000 82.41667 82.58333 计算每门课程的平均分 课程平均分 - apply(scores, 2, mean) print(课程平均分) 数学 语文 英语 82.88889 82.11111 82.50000 找出每个班级的最高分学生 apply(scores, 3, function(x) { idx - which(x max(x), arr.ind TRUE) paste0(最高分: , max(x), 学生: , rownames(x)[idx[1, 1]]) }) 一班 二班 三班 最高分: 99学生: 李四 最高分: 99学生: 王五 最高分: 98学生: 赵六7.2 案例二图像数据表示灰度图像可以表示为二维矩阵而彩色图像通常用三维数组表示高度 × 宽度 × 颜色通道# 模拟一张 4×4 的 RGB 彩色图像4 行 × 4 列 × 3 通道 set.seed(123) image_data - array( sample(0:255, 4 * 4 * 3, replace TRUE), dim c(4, 4, 3), dimnames list( 行 paste0(行, 1:4), 列 paste0(列, 1:4), 通道 c(R, G, B) ) ) 查看红色通道 image_data[, , R] 列 行 列1 列2 列3 列4 行1 31 79 51 14 行2 67 42 50 43 行3 14 25 100 51 行4 41 17 77 32 计算整张图像的平均亮度三个通道的平均值 平均亮度 - apply(image_data, c(1, 2), mean) print(平均亮度) 列1 列2 列3 列4 行1 111.3333 151.3333 126.6667 105.3333 行2 139.3333 126.6667 151.3333 126.6667 行3 105.3333 111.3333 151.3333 126.6667 行4 126.6667 105.3333 151.3333 111.33337.3 案例三时间序列的多维存储对于多个站点、多个指标、多个时间点的数据三维数组是理想的存储结构# 模拟 3 个站点、2 个指标温度、湿度、7 天的数据 set.seed(2024) weather - array( round(runif(3 * 2 * 7, 0, 40), 1), dim c(3, 2, 7), dimnames list( 站点 c(北京, 上海, 广州), 指标 c(温度, 湿度), 日期 paste0(第, 1:7, 天) ) ) 查看第 1 天的数据 weather[, , 第1天] 指标 站点 温度 湿度 北京 20.3 31.0 上海 25.7 12.4 广州 30.1 22.1 计算每个站点一周的平均温度 apply(weather[, 温度, ], 1, mean) 北京 上海 广州 20.61429 22.70000 22.51429 找出每个站点温度最高的一天 apply(weather[, 温度, ], 1, which.max) 北京 上海 广州 5 4 68. 数组的注意事项与常见陷阱8.1 数据填充顺序R 数组默认按列填充数据这与许多其他编程语言如 Python 的 NumPy 默认按行填充不同容易造成混淆# 按列填充 arr_col - array(1:6, dim c(2, 3)) print(arr_col) # [,1] [,2] [,3] # [1,] 1 3 5 # [2,] 2 4 6 如需按行填充需要转置 arr_row - t(array(1:6, dim c(3, 2))) print(arr_row) [,1] [,2] [,3] [1,] 1 2 3 [2,] 4 5 68.2 维度丢失问题当索引数组的某个维度时R 默认会丢弃该维度可能导致结果降维arr - array(1:12, dim c(2, 3, 2)) 访问第 1 层时返回的是矩阵维度为 2×3 layer1 - arr[, , 1] dim(layer1) # 输出: [1] 2 3 如果希望保留三维结构使用 drop FALSE layer1_keep - arr[, , 1, drop FALSE] dim(layer1_keep) # 输出: [1] 2 3 18.3 数组元素类型必须一致# 混合类型会被强制转换 mixed - array(c(1, 2, a, b), dim c(2, 2)) print(mixed) # [,1] [,2] # [1,] 1 a # [2,] 2 b # 注意数值被强制转换为字符类型8.4 使用 c() 展平数组时的顺序arr - array(1:12, dim c(2, 3, 2)) c() 按列优先顺序展平 flat - c(arr) print(flat) 输出: [1] 1 2 3 4 5 6 7 8 9 10 11 129. 总结本文系统介绍了 R 数组的创建、索引、运算和实战应用核心要点总结如下创建使用array()函数或通过dim()属性赋值创建多维数组。索引通过方括号按各维度下标访问元素支持名称索引和向量索引。运算数组支持标量运算、逐元素运算配合apply()可进行灵活的维度聚合。转换数组可以与矩阵、向量相互转换aperm()可重排维度顺序。实战数组非常适合存储成绩数据、图像数据、多维时间序列等结构化数据。掌握数组操作是深入学习 R 语言数据分析和科学计算的重要基础。建议读者结合本文代码动手实践并尝试将数组应用到自己的真实数据场景中。