[1] 1238.356
[1] 1.666667
[1] 2
Lecture02 : R数据结构
2024-08-23
R的工作空间(workspace)是指R语言中的当前工作环境,它存储了所有用户定义的对象,包括向量、矩阵、函数、数据框和列表等。当你在R中创建一个对象或者运行一个函数时,这些对象就会被存储在工作空间中。工作空间中的对象可以在R会话期间随时访问和修改。
如果使用RStudio,一般会针对每个项目在RStudio中单独建立一个“项目”(.RStudio
)。 不同项目使用不同的工作空间。
你可以选择将当前的工作空间保存到一个文件中,通常这个文件的扩展名为.RData
。这样,你可以在下次启动R时加载这个文件,恢复之前的工作环境。
工作目录:在进行数据分析时一般把不同的数据分析项目放在不同的文件夹中,并且设定这个文件夹为当前工作目录。可以使用getwd()
函数来查看当前的工作目录,或者使用setwd()
函数来改变当前的工作目录。
管理工作空间的常用R命令包括:
getwd() #显示当前的工作目录。
setwd("mydirectory") #将当前的工作目录修改为指定的目录。
ls() #列出当前工作空间中的对象。
dir() #列出当前工作路径下的文件和文件夹
rm(objectlist) #移除(删除)一个或多个对象。
save.image("myfile.RData") #保存工作空间数据到文件中,RData文件又被称为镜像文件。
load("myfile") #从文件中读取工作空间到当前R会话中。
q() #退出R。
以上绝大部分操作也可以通过RStudio用户界面来完成,但推荐大家使用这种命令方式。尽量少用图形界面。
四则运算
算数运算
三角函数
取整
[1] 1.12
[1] 1
[1] 2
[1] 3.556632
其它
随机数
[1] 0.4303841
[1] 1.95663806 0.85523929 -0.52562467 1.54763301 -0.11563081 -1.14099187
[7] -0.73630351 0.69478471 0.08262082 0.89860668
[1] 3.796065e+02 1.378817e+00 6.121583e-01 3.374182e-01 1.975073e-01
[6] 1.180706e-01 7.133984e-02 4.351240e-02 2.683191e-02 1.676130e-02
[11] 1.062378e-02 6.839344e-03 4.474326e-03 2.974714e-03 2.009360e-03
[16] 1.378361e-03 9.596234e-04 6.776066e-04 4.849362e-04 3.514877e-04
常量是指直接写在程序中的值,包括数值、字符串等。
程序语言中的变量用来保存输入的值或者计算得到的值。 在R中,变量可以保存所有的数据类型, 比如标量、向量、矩阵、数据框、函数等。
变量必需有变量名,程序员必需给变量起名(这是一门艺术)
R用<-
符号赋值变量。<-
也可以写成=
,但是推荐大家用<-
:
在R语言中,向量是最基本的数据结构,它是相同类型的元素的集合。
向量是一维的,并且每个元素在向量中都有一个唯一的位置或索引。
使用c()
函数来创建向量
[1] 10 6 4 7 8
[1] 1 2 3 10 11 12 13
[1] 1 2 3 4
[1] "R" "is" "awesome"
[1] TRUE FALSE TRUE TRUE FALSE
1:3 10:13
表示一个连续区间,这是R的一个惯例
通过在方括号中给定元素所处的位置,可以访问向量中的元素:
在R中,位置索引从1开始,和绝大多数语言都不同(从0开始)。
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
[1] 50
[1] 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
[1] 55 78
矩阵是一个二维数组,其中的元素通常是同一数据类型,并且以行和列的形式组织。
矩阵一般用于数值计算, 所以其元素一般是数值。
使用matrix()
函数创建矩阵
# data: 矩阵的元素,一般是一个向量
# nrow:行数
# ncol:列数
# byrow:是否按行填充
# dimnames:字符型向量表示的行名和列名
matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,
dimnames = NULL)
举例:
除了必须的第一个参数外,其余的参数均为可选
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 11 21 31 41 51 61 71 81 91
[2,] 2 12 22 32 42 52 62 72 82 92
[3,] 3 13 23 33 43 53 63 73 83 93
[4,] 4 14 24 34 44 54 64 74 84 94
[5,] 5 15 25 35 45 55 65 75 85 95
[6,] 6 16 26 36 46 56 66 76 86 96
[7,] 7 17 27 37 47 57 67 77 87 97
[8,] 8 18 28 38 48 58 68 78 88 98
[9,] 9 19 29 39 49 59 69 79 89 99
[10,] 10 20 30 40 50 60 70 80 90 100
注意:当使用 matrix()函数创建矩阵时,需要确保提供的数据长度(即向量的长度)是行数和列数乘积的倍数。
如果向量的长度小于行数×列数,则剩余的位置会从头开始循环填充:
如果向量的长度大于行数×列数,则剩余的数值会被丢弃:
用nrow()
和ncol()
函数可以访问矩阵的行数和列数
用dim()
函数同时显示行数和列数(dim()
可用于任何数据结构)
矩阵取子集:
[1] 1 11 21 31 41 51 61 71 81 91
[1] 45 67 89
矩阵指定行和列取子集(重要):
[1] 1 2 3 4 5 6 7 8 9 10
[1] 1 11 21 31 41 51 61 71 81 91
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 11 12 13 14 15 16 17 18 19 20
[2,] 21 22 23 24 25 26 27 28 29 30
[3,] 31 32 33 34 35 36 37 38 39 40
[4,] 41 42 43 44 45 46 47 48 49 50
[5,] 51 52 53 54 55 56 57 58 59 60
[6,] 61 62 63 64 65 66 67 68 69 70
[7,] 71 72 73 74 75 76 77 78 79 80
[8,] 81 82 83 84 85 86 87 88 89 90
[9,] 91 92 93 94 95 96 97 98 99 100
[,1] [,2] [,3]
[1,] 11 12 13
[2,] 21 22 23
[1] 1
用colnames()
函数可以给矩阵每列命名,也可以访问矩阵列名,用rownames()
函数可以给矩阵每行命名,也可以访问矩阵行名。
my_matrix <- matrix(1:12,ncol = 3,nrow=4 )
colnames(my_matrix) <- c("col1","col2","col3") # 赋值
rownames(my_matrix) <- c("row1","row2","row3","row4") # 赋值
colnames(my_matrix) # 取值
[1] "col1" "col2" "col3"
[1] "row1" "row2" "row3" "row4"
dimnames()
函数返回一个列表,包含行名和列名
当有了行名和列名后,就可以使用它们取子集
数组是一种多维数据结构,存储相同类型数据的集合。
实际上,数组可以被视为向量和矩阵的自然扩展,只不过数组中的数据可以有更高维度。向量和矩阵也可以视作数组的特例(一维、二维)
数组相对用的比较少,作为了解
dim = c(3, 3, 2)指定了数组的维度和每个维度的长度: 3行、3列、2层
访问数组元素
[1] 1
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
, , 1
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
drop = FALSE
是取子集时的常用选项,默认为TRUE
。设想取矩阵的一行或一列,不加这个选项将取到向量。这里不加的话将取到一个矩阵。
统计分析中最常见的原始数据形式是类似于数据库表或Excel数据表的形式。 这样形式的数据在R中叫做数据框(data.frame)。
数据框可以理解为矩阵的扩展,有n个横行、p个纵列, 但各列允许有不同类型:如数值型向量、因子、字符型向量、日期时间向量。同一列的数据类型相同。
数据框是R中最常用的数据结构
使用data.frame()
函数创建数据框
data.frame(..., row.names = NULL, check.rows = FALSE,
check.names = TRUE, fix.empty.names = TRUE,
stringsAsFactors = FALSE)
...
: 传递任意数量的向量、列表或其它数据框作为参数。每个参数代表数据框中的一列。
row.names = NULL
: 用于指定数据框的行名。
check.rows = FALSE
:用于控制是否检查输入的每一行是否具有相同的列数。
check.names = TRUE
:是否检查列名是否有效。
fix.empty.names = TRUE
:用于控制当输入数据没有列名时,data.frame() 是否会自动生成列名。
stringsAsFactors = FALSE
:用于控制字符串类型的列是否自动转换为因子类型。
创建数据框
# 创建向量
name <- c("Alice", "Bob", "Charlie")
age <- c(25, 30, 35)
height <- c(165, 180, 175)
gender <- factor(c("Female", "Male", "Male"))
is_member <- c(TRUE, FALSE, TRUE)
# 使用data.frame()创建数据框
df <- data.frame(name, age, height,gender,is_member)
print(df)
name age height gender is_member
1 Alice 25 165 Female TRUE
2 Bob 30 180 Male FALSE
3 Charlie 35 175 Male TRUE
指定列名1
姓名 年龄 身高
1 Alice 25 165
2 Bob 30 180
3 Charlie 35 175
使用行名
d <- data.frame(
name=c("李明", "张聪", "王建"),
age=c(30, 35, 28),
height=c(180, 162, 175),
stringsAsFactors=FALSE) # 4.0.0以上默认就是FALSE
print(d)
name age height
1 李明 30 180
2 张聪 35 162
3 王建 28 175
nrow()
求行数,ncol()
或length()
求列数
rownames()
可以显示/修改行名,names()
或colnames()
可以显示/修改列名
用as.data.frame(x)可以把x转换成数据框。
[1] 1 2 3 4 5 6 7 8 9 10
$name
[1] "Alice" "Bob" "Charlie"
$age
[1] 25 30 35
$height
[1] 165 180 175
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
a
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
name age height
1 Alice 25 165
2 Bob 30 180
3 Charlie 35 175
V1 V2 V3 V4 V5
1 1 5 9 13 17
2 2 6 10 14 18
3 3 7 11 15 19
4 4 8 12 16 20
使用行号和列号
使用$
符号选择列
使用 [[]]
选择列
使用逻辑条件
使用 subset() 函数
with()
允许你对数据框(或列表)的子集进行操作,而无需重复它们的名字1
下面我们使用mtcars
数据来进行演示2
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
[1] 42.0 42.0 45.6 42.8 37.4 36.2 28.6 48.8 45.6 38.4 35.6 32.8 34.6 30.4 20.8
[16] 20.8 29.4 64.8 60.8 67.8 43.0 31.0 30.4 26.6 38.4 54.6 52.0 60.8 31.6 39.4
[31] 30.0 42.8
当后续操作不止一步时要用花括号括起来
within()
函数用于在数据框或列表内执行一系列操作,这些操作可以改变数据框或列表本身。可以使用 within() 来添加新列、修改现有列或执行其他变换,而不需要重复数据框的名称。
Name Age Salary Double_Age
1 Alice 25 50000 50
2 Bob 30 60000 60
3 Charlie 35 65000 70
with() | within() | |
---|---|---|
返回值 | 返回操作的结果,而不会改变原始数据框 | 直接在原始数据框或列表上进行修改,不返回值 |
用途 | 通常用于数据子集选择或应用函数 | 用于在数据框或列表上执行一系列变换 |
数据框不能作为矩阵参加矩阵运算。需要时,可以用as.matrix()
函数转换数据框或数据框的子集为矩阵:
数据框是一个随着R语言前身S语言继承下来的概念, 现在已经有一些不足之处, tibble包提供了tibble类, 这是数据框的一个现代改进版本。
tibble 的一些特点包括:
由于tidyverse
包1也包含了tibble
,也可以一次性安装tidyverse
包
# A tibble: 32 × 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
# ℹ 22 more rows
类似数据框这样的二维表格数据是R中最为重要的数据类型,随着时间的发展,逐步出现了data.table
、tibble
这样的第三方包,以弥补R自带的dataframe的不足。
data.table是一个高性能数据管理包。可以以极快的速度处理大规模数据集(100GB规模)。
library(data.table)
三者的语法、适用场景都不一样,具体见附录3
在统计学和数据分析中,变量的类型决定了数据分析的方法和可以应用的统计测试。
连续性变量(Continuous Variables):可以取任意值,通常是数值型的,并且在两个数值之间可以有无限多个可能的值。它们通常用于量化测量,如长度、重量、时间、温度等。
分类变量
名义变量(Nominal Variables):代表的是不同的类别或名称,它们之间没有内在的顺序或等级关系。如性别、种族、血型、品牌名称等
顺序变量(Ordinal Variables):是分类变量的一种,它们的类别有明确的顺序或等级关系,例如,教育水平(小学、中学、大学)、满意度评分(不满意、一般、满意)、社会经济地位等级等。
名义变量和顺序变量(分类变量)在R中被称为因子
因子由以下几个部分组成:
水平(Levels):因子的所有可能取值。例如,性别因子的水平可能是”男”和”女”。
内部表示(Internal Representation):因子在计算机中的存储方式,通常是一个整数向量,每个整数代表一个水平。
标签(Labels):水平的文本描述,用于提高可读性。例如,水平1可能被标记为”男”,水平2被标记为”女”。如果不指定标签,那么默认标签就是水平本身。
使用factor()
函数创建因子,它可以将一个字符向量或数值向量转换为因子类型
factor(x = character(), levels = as.character(x), labels = levels,
exclude = NA, ordered = is.ordered(x), nmax = NA)
在实际使用中,最常见的参数是 x 和 levels,而其他参数根据特定需求进行设置
下面的例子中,x是一个无序向量,在不指定任何参数时,factor(x)
返回一个无序因子。而指定ordered = TRUE
后则返回了一个有序因子
[1] low medium high medium low
Levels: high low medium
[1] low medium high medium low
Levels: high < low < medium
如果不指定levels,则factor()
函数会自动判断。
我们也可以手动指定levels。但是如果指定的levels数量少于元素的种类,则结果会排除这些值
[1] low medium high medium low
Levels: low medium high
[1] low medium <NA> medium low
Levels: low medium
[1] low medium high medium low
Levels: low medium high extreme
创建一个因子并排除特定的水平
[1] "female" "male"
[1] "1" "2" "3" "4" "5"
female male
3 2
[1] TRUE
[1] 1 2 3
Levels: 1 2 3
[1] "female" "male" "female" "female" "male"
总结
因子作为R语言中内置的原生数据结构对象,它的出现就是来解决分类变量的分组、计数问题。
问题1:一个14亿人的身份证号组成的向量,如果把它变成因子,有意义吗?
没有,因为14亿人的身份证号都是不相同的,因子对这个向量作分组计数的结果,就是每个人的身份证号作为一组,计数的结果也就是一个。
问题2:一个超市的售货记录,1亿条商品出售记录的向量,商品类别数量为1W,把它变成因子,有意义吗
有,通过把这个向量变成因子,我们可以快速对这1W种商品进行分组、计数。可以很快看出,哪种商品卖得好,这样因子的作用:分组、计数的效果就出来了。而且节省了存储空间
在R语言中,列表(list)是一种复杂的数据结构,它可以包含各种类型和长度的数据元素。列表是R中非常灵活和强大的数据类型之一,因为它可以容纳不同类型的数据,如数值、字符、逻辑值、甚至是其他列表或数据框。列表通常用于存储和操作具有不同属性或维度的数据集。
异质性:列表可以包含不同类型的数据,每个元素可以是数值、字符、逻辑值、向量、矩阵、数据框或其他列表。
命名元素:列表中的每个元素可以有一个名称,这使得访问和操作列表中的特定元素更加方便。
索引:可以通过元素的名称或位置来访问列表中的元素。
动态长度:列表的长度可以根据需要动态变化,可以随时添加或删除元素。
递归结构:列表可以包含其他列表,形成嵌套结构。
创建一个简单列表
my_list <- list(
name = "Alice",
age = 25,
scores = c(90, 92, 85),
personal_info = list(height = 165, weight = 55)
)
my_list
$name
[1] "Alice"
$age
[1] 25
$scores
[1] 90 92 85
$personal_info
$personal_info$height
[1] 165
$personal_info$weight
[1] 55
使用$
访问列表元素
[1] "Alice"
[1] 25
[1] 90 92 85
$height
[1] 165
$weight
[1] 55
通过索引访问列表元素
访问嵌套列表中的元素
with()
依然可用
R中自带了很多个数据集,这些数据集覆盖了各种领域,包括经济学、生物学、医学、工程学等,它们是学习数据分析和统计方法的宝贵资源。这些数据集通常已经预加载在R会话中,可以直接通过调用它们的名字来访问。以下是一些R中自带的著名数据集:
名称 | 说明 | 使用 |
---|---|---|
mtcars | 包含1973-1974年间32款汽车的燃油消耗和其他10种汽车属性的数据 | 直接使用 |
iris | 包含3种不同鸢尾花的150个样本数据,每个样本有4个特征 | 直接使用 |
lung | 包含肺癌患者和健康人的肺活量数据,用于生存分析 | library(survival) data(lung) |
ChickWeight | 记录了不同饮食组的小鸡在不同周龄的体重数据 | 直接使用 |
AirPassengers | 提供了1949-1960年间每个月的国际航空旅客数量 | 直接使用 |
LifeCycleSavings | 记录了不同月份和不同日子的英国驾驶员死亡人数 | 直接使用 |
UKDriverDeaths | 包含3种不同鸢尾花的150个样本数据,每个样本有4个特征 | 直接使用 |
PlantGrowth | 包含了不同肥料处理下植物的生长高度数据 | 直接使用 |
ToothGrowth | 记录了豚鼠牙齿生长的实验数据,包括不同剂量和类型的维生素C补充 | 直接使用 |
OrchardSprays | 包含了苹果园喷洒不同类型杀虫剂的效果数据 | 直接使用 |
这些数据集可以直接用于数据分析练习,如数据探索、可视化、建模和统计测试。使用这些数据集可以帮助你理解数据结构,学习如何提出问题,以及如何使用R的各种函数和包来寻找答案。例如,你可以使用 summary() 函数来获取数据集的描述性统计信息,使用 plot() 函数来进行数据可视化,或者使用 lm() 函数来构建线性模型。
要查看R中所有自带数据集的列表,可以在R控制台输入 data(),这将显示所有可用的内置数据集。
tidyverse
是由 Hadley Wickham 和其他贡献者开发的 R 语言包集合,它旨在提供一套一致且高效的工具来处理和分析数据。tidyverse
中的包都遵循相同的设计哲学,使得它们可以无缝协作。以下是 tidyverse
中包含的一些核心包及其主要功能:
ggplot2:一个强大的数据可视化包,基于语法的图形系统,允许用户通过添加图层来构建复杂的图表。
dplyr:提供了一系列函数来操作数据框,包括过滤、选择、排序、汇总和分组等。
tidyr:用于数据整理的包,可以帮助用户将数据转换为“整洁”格式,即每个变量构成一列,每个观测构成一行,每种观测单位构成一个表格。
readr:提供了一系列函数来读取和写出文件,特别是文本文件、CSV 文件和固定宽度的文件。
purrr:增强了 R 的函数式编程能力,使得用户可以更有效地使用列表和函数。
tibble:提供了 tibble
数据结构,它是对传统数据框的现代化改进,提供了更好的打印方法和更严格的类型检查。
stringr:用于字符串操作的包,提供了一系列函数来搜索、替换、分割和连接字符串。
forcats:专注于因子变量的包,提供了工具来创建、转换和操作因子,这是 R 中用于分类数据的数据类型。
lubridate:用于处理日期和时间的包,它提供了一套易于理解和使用的函数来解析、操作和格式化日期和时间。
broom:将统计模型的结果转换为整洁的数据框,方便进行进一步的分析和可视化。
haven:用于读取和写入统计软件(如 SPSS、Stata 和 SAS)文件的包。
readxl:专门用于读取 Excel 文件的包。
writexl:专门用于将数据写入 Excel 文件的包。
modelr:用于构建和操作统计模型的包,它提供了一种在管道操作中构建模型的一致方法。
hms:用于处理时间数据的包,特别是小时、分钟和秒。
pillar:用于改善 R 控制台中的列数据的显示。
cli:用于创建命令行界面的包。
crayon:用于在 R 中进行颜色文本输出的包。
fansi:用于处理 ANSI 字体样式的包。
utf8:用于处理 UTF-8 编码的字符串的包。
tidyverse
包的安装非常简单,只需在 R 中运行以下命令:
加载 tidyverse 包会加载上述所有核心包,使得用户可以方便地进行数据处理和分析。通过 tidyverse 的一致性和高效性,数据分析变得更加直观和易于管理。
使用场景 | 推荐的R生态系统 | 理由 |
---|---|---|
初学者学习 | Base R → Tidyverse | 从Base R开始可以帮助掌握R的基本概念和操作;之后转向Tidyverse能够加快数据分析和可视化的上手速度。 |
日常数据分析和可视化 | Tidyverse | Tidyverse具有简洁的语法和强大的功能,适合提升数据分析和可视化的生产力。 |
处理大型数据集 | data.table | data.table提供卓越的性能和内存管理能力,虽然学习曲线较陡,但其高效的处理能力值得付出额外的学习成本。 |
Base R是R语言的基础,包含了核心的函数和操作。它的优势在于:
然而,Base R的劣势在于其相对较低的可读性和代码简洁性。对于新手来说,Base R的语法可能显得繁琐,且在处理复杂的数据操作时,其代码往往较长且不直观。
Tidyverse是一个由Hadley Wickham及其团队开发的R包集合,包含了如dplyr、ggplot2和tibble等工具。Tidyverse的主要优势包括:
然而,Tidyverse也有其局限性。例如,在处理非常大的数据集时,Tidyverse的性能可能不如data.table。此外,Tidyverse的依赖性较强,可能会导致包版本冲突问题。
data.table是一个高性能的数据操作包,特别适合大数据集的处理。其主要优点包括:
然而,data.table的缺点在于其语法复杂性和学习曲线。对于新手来说,data.table的语法相对较难理解和掌握,而且其独特的操作方式可能导致代码的可读性降低。
说明: 创建一个包含以下内容的R脚本,并将结果打印到控制台。
要求:
说明: 给定以下代码,完成练习题。
# 假设我们有以下向量
char_vec <- c("one", "two", "three", "four")
num_vec <- c(1, 2, 3, 4)
# 假设我们有以下数据框
df <- data.frame(
Character = as.factor(char_vec),
Numbers = num_vec
)
要求:
R数据结构