统计软件 R 语言学习笔记 (4) R 语言初步:自定义函数、简单模拟与数据清洗
R 语言初步 (3) 自定义函数、简单模拟与数据清洗
本章介绍 R 语言的函数定义方法,以及进行统计模拟、数据清洗的方法。function
关键字自定义函数;r*
p*
d*
q*
分别进行各种分布的模拟;sample
函数进行简单随机抽样;数据清洗包括了缺失数据处理、按行排序、选取/删除部分数据、添加变量/特征和合并数据集操作。
代码和笔记存储在 GitHub 库 【持续更新中,建议 star!】
1 自定义函数
1.1 函数定义
定义函数的一般形式:
1 | myfunction <- function(a, b, c) { |
myfunction
:自定义的函数名称function()
:关键字,告诉 R 语言这是自定义的函数a, b, c
:为函数的参数,表明函数需要传入的参数statement
:函数体,编写函数的操作return(object)
:函数的返回值
1.2 传参方式
- 方式一:按照参数顺序逐个传入
1 | myfunction(x1, x2, x3) |
- 方式二:指定参数
1 | myfunction(a = x1, b = x2, c = x3) |
1.3 示例
- 函数名:
my.data.ana
- 输入:一个向量
x
- 任务:计算向量的平均值、最大值、最小值
- 输出:一个列表储存的结果
1 | my.data.ana <- function(x) { |
2 简单模拟
2.1 有关统计分布的函数
r*
:*
分布的随机数函数
d*
:*
分布的密度函数
p*
:*
分布的分布函数
q*
:*
分布的分位数函数
例如:
- 正态分布的相关函数
rnorm()
dnorm()
pnorm()
qnorm()
- Gamma 分布的相关函数
rgamma()
dgamma()
pgamma()
qgamma()
- 泊松分布相关函数
rpois()
dpois()
ppois()
qpois()
2.1.1 正态分布
格式
1 | # 传入分位数点,得到密度函数值 |
参数
参数 | 含义 |
---|---|
x q |
分位数向量 |
p |
概率值向量 |
n |
rnorm(n) 返回随机数的个数 |
mean |
均值向量 |
sd |
标准差向量 |
log log.p |
是否取对数,为 TRUE ,则传入 log(p) |
lower.tail |
为 TRUE ,则概率表达式为 否则, |
2.1.2 Poisson 分布
格式
1 | # 计算概率密度函数 (PMF) 值 |
参数
参数 | 说明 |
---|---|
x q |
非负整数分位数点。若输入非整数,dpois 返回 0;ppois 自动取 floor(q) 计算。 |
p |
概率值向量,范围必须在 [0, 1] 之间。 |
n |
生成的随机数数量。 |
lambda |
非负向量。若为负数,返回 NaN 。 |
log log.p |
逻辑值。若为 TRUE ,概率以自然对数形式输入/输出。 |
lower.tail |
逻辑值。若为 TRUE (默认),计算 P(X ≤ x) 或 P(X ≤ q) ;否则计算 P(X > x) 或 P(X > q) 。 |
关键细节
-
离散性处理
•dpois(x, lambda)
仅在x
为整数时返回非零值,否则返回 0。
•ppois(q, lambda)
会对非整数q
向下取整(等效计算P(X ≤ floor(q))
)。 -
分位数函数逻辑
•qpois(p, lambda)
返回最小整数k
,使得P(X ≤ k) ≥ p
。
• 当lower.tail = FALSE
时,寻找最小k
使得P(X > k) ≤ p
(即右尾分位数)。 -
向量化运算
所有参数均支持向量化输入,按元素循环计算。例如:
1 | # 分别计算 λ=2 时 x=1,λ=3 时 x=2,λ=4 时 x=3 的概率 |
2.1.3 二项分布
格式
1 | # 计算概率密度函数 (PMF) 值 |
参数
参数 | 说明 |
---|---|
x q |
整数分位数点。若输入非整数,dbinom 返回 0;pbinom 自动取 floor(q) 计算。 |
p |
概率值向量,范围必须在 [0, 1] 之间。 |
n |
生成的随机数数量。若输入向量(如 n = c(2,3) ),实际生成 sum(n) 个随机数。 |
size |
试验次数(非负整数),若为小数会自动截断为整数。 |
prob |
单次试验成功概率,范围 [0, 1]。若输入负数或 >1 返回 NaN 。 |
log log.p |
逻辑值。若为 TRUE ,概率以自然对数形式输入/输出(例如 log(0.05) )。 |
lower.tail |
逻辑值。若为 TRUE (默认),计算 P(X ≤ x) 或 P(X ≤ q) ;否则计算 P(X > x) 或 P(X > q) 。 |
2.2 随机抽样函数 sample
格式
1 | sample(x, size, replace = FALSE, prob = NULL) |
参数
参数 | 说明 |
---|---|
x |
抽样来源。可以是向量或单个整数:若为向量,直接从中抽样;若为整数 n ,等价于从 1:n 抽样 |
size |
抽样数量。必须为非负整数,且当 replace=FALSE 时,size ≤ length(x) |
replace |
是否放回抽样。默认 FALSE (无放回);TRUE 时为有放回抽样 |
prob |
权重向量。指定每个元素的抽样概率(自动归一化),需与 x 等长。默认等概率抽样 |
关键细节
- 当
x
为整数时的特殊行为
1 | sample(5, 3) # 等价于从 1:5 中无放回抽3个数(如 2,4,1) |
- 权重概率:若
prob
的和不为1,会自动归一化处理
1 | sample(c("A","B"), size=5, replace=TRUE, prob=c(3,1)) # "A"出现概率为 3/(3+1)=75% |
- 边界条件限制:
size
在无放回时一定要比x
的长度小
1 | sample(1:10, size=15, replace=TRUE) # 允许(有放回) |
2.3 随机种子 set.seed()
在电脑上生成随机数字时,生成的数字并不是真正的随机数,它们叫做伪随机数 (pseudo random number)。当从任意分布模拟随机数字时,设置随机数字生成器种子 (seed) 是非常重要的。设置随机种子使得实验结果可复现。
1 | # n 指定一个整数 |
- 当设置随机种子后,随机结果将会相同
1 | set.seed(1) |
3 数据清洗
结构化数据:表格形式的数据。每一行代表一个样本/观测,每一列对应一个变量/特征。
创建示例数据表
1 | manager <- c(1, 2, 3, 4, 5) |
1 | leadership |
3.1 缺失数据
is.na()
逐个元素比较是否为空 NA
1 | is.na(leadership) |
直接删除 na.omit
非替换操作,删除空值的行
1 | newdata <- na.omit(leadership) |
1 | newdata |
或者采用均值填充
mean(leadership$age)
1 | # 用中位数代替 q1 列的缺失值 |
其中 na.rm = TRUE
表示在计算均值/中位数等统计量时忽略空值。
3.2 数据按行排序
操作 | 函数/方法 | 说明 |
---|---|---|
对向量排序 | sort() |
返回排序后的值 |
获取排序索引 | order() |
返回排序后的索引值,用于按行排序 |
按列升序排序 | data[order(data$column), ] |
按指定列升序排列数据框 |
降序排序 | order(x, decreasing = TRUE) |
按指定列降序排列数据框 |
处理缺失值 | na.last = TRUE/FALSE |
控制缺失值在排序中的位置(默认放在最后) |
例如:按照 age
升序排序
1 | newdata <- leadership[order(leadership$age), ] |
好的,用户需要整理关于R语言中选取和删除部分数据的笔记,特别是使用下标运算、列名以及subset()函数的方法。他们已经提供了一些之前的笔记结构,我需要保持一致的风格和格式。
首先,我需要回忆R语言中数据框的基本操作。下标运算[ , ]的使用是关键,参数可以是正数、负数、逻辑值或空。用户还提到数据框有行名和列名,可以按列名选取列。另外,subset()函数也是一个重要的方法。
接下来,我需要确定如何组织内容。之前的笔记有参数详解、关键细节、示例和注意事项,我应该沿用这个结构。需要解释不同的下标类型如何影响选取或删除数据,比如正数选择特定行或列,负数排除,逻辑值过滤,空表示全选。还要说明如何使用列名来选取列,以及subset()函数的参数和使用场景。
需要注意常见的陷阱,比如混合使用正负下标可能导致错误,逻辑值的回收机制可能引发意外结果,subset()函数在处理变量时的环境问题。还要提到drop参数的影响,避免数据框降维为向量。
然后,准备示例代码。例如,用正数选取行和列,用负数删除,用逻辑表达式过滤行,按列名选取,以及subset()的使用。同时提供输出结果,帮助理解。
最后,总结不同方法的适用场景,帮助用户根据需求选择合适的方式。确保内容清晰,结构合理,语言简洁,符合用户之前的笔记风格。
3.3 选取/删除部分数据
3.3.1 基础方法:下标运算符 [ ]
格式
1 | 数据框[行下标, 列下标] # 行和列下标可为正数、负数、逻辑值或空(保留所有行/列) |
参数
下标类型 | 说明 |
---|---|
正数 | 选取指定位置的行/列(如 1:3 选取前3行或前3列) |
负数 | 排除指定位置的行/列(如 -c(2,4) 删除第2和第4行/列) |
逻辑值 | 按 TRUE/FALSE 筛选行/列(如 数据框$列名 > 5 筛选满足条件的行) |
空值 | 保留所有行或列(如 数据框[, 2:4] 保留所有行,选取第2到4列) |
列名 | 通过列名字符串筛选(如 数据框[, c("列名1", "列名2")] ) |
示例
- 按照数字索引取/删除
1 | # 选取前3行和前2列 |
- 按逻辑条件筛选行
1 | # 筛选年龄 >30 的行 |
- 按列名选取列
1 | # 选取指定列 |
3.3.2 subset() 函数
格式
1 | subset(数据框, subset=行筛选条件, select=列筛选条件) |
参数
参数 | 说明 |
---|---|
subset |
逻辑表达式,筛选符合条件的行(如 age > 30 ) |
select |
指定要保留的列,支持列名或列位置(如 c("age", "gender") 或 2:4 ) |
示例
- 筛选年龄 > 30 且性别为男性的行,保留年龄和性别列
1 | subset(df, subset = age > 30 & gender == "M", select = c("age", "gender")) |
subset()
的select
参数支持负列名,表示删除/不取对应的列
1 | subset(数据框, select = -c(列名1, 列名2, ...)) |
3.4 添加变量/特征
3.4.1 直接赋值法
通过 $
符号直接创建新变量
1 | # 计算 q1 到 q5 的总和 (qsum) |
3.4.2 within() 函数
1 | leadership <- within(leadership, { |
3.5 合并数据集
3.5.1 基础合并函数 cbind() rbind()
cbind()
:按列合并
-
语法
1
cbind(数据框1, 数据框2)
-
示例
1
2
3df1 <- data.frame(ID = 1:3, Name = c("A", "B", "C"))
df2 <- data.frame(Age = c(20, 25, 30), Score = c(85, 90, 88))
combined_col <- cbind(df1, df2) # 合并后列数为 df1 列数 + df2 列数
ID | Name | Age | Score |
---|---|---|---|
1 | A | 20 | 85 |
2 | B | 25 | 90 |
3 | C | 30 | 88 |
若行数不同,会报错;列名重复时自动添加后缀(如
Score
和Score.1
)
rbind()
:按行合并
-
语法
1
rbind(数据框1, 数据框2)
-
示例
1
2df3 <- data.frame(ID = 4:5, Name = c("D", "E"), Age = c(22, 28), Score = c(92, 80))
combined_row <- rbind(combined_col, df3) # 合并后行数为原两数据框行数之和结果:
| ID | Name | Age | Score |
| ---- | ---- | ---- | ----- |
| 1 | A | 20 | 85 |
| 2 | B | 25 | 90 |
| 3 | C | 30 | 88 |
| 4 | D | 22 | 92 |
| 5 | E | 28 | 80 |
若列名不一致,会报错
3.5.2 高级合并函数 merge()
根据共同列(键)合并两个数据框。
-
语法
1
merge(数据框1, 数据框2, by = "列名", all = FALSE)
-
核心参数
参数 | 说明 |
---|---|
by |
指定合并的列名(如 by = "ID" ),若未指定则自动匹配同名列。 |
all.x |
是否保留左表所有行(左外连接),默认 FALSE 。 |
all.y |
是否保留右表所有行(右外连接),默认 FALSE 。 |
all |
all = TRUE 表示全外连接(保留所有行)。 |
左/右/外连接:按照某列合并时,可能会存在其他列个数不匹配。采用左外连接,则保留左表所有行,右表不足则复制,填入空值;采用右外连接,则保留右表所有行,左表不足则复制,填入空值;采用全连接,则保留左右表所有行,不足则复制,填入空值。
-
示例
1
2orders <- data.frame(OrderID = c(101, 102, 103), CustomerID = c(1, 2, 4))
customers <- data.frame(CustomerID = 1:3, Name = c("A", "B", "C"))
1 | # 内连接(默认)取交集,[1,2,4] 和 [1, 2, 3] 只有 [1, 2] 相交 |
内连接结果
CustomerID | OrderID | Name |
---|---|---|
1 | 101 | A |
2 | 102 | B |
1 | # 左外连接,左表的 [1, 2, 4] 都保留,则多出来的无法匹配的留空 |
左外连接结果
CustomerID | OrderID | Name |
---|---|---|
1 | 101 | A |
2 | 102 | B |
4 | 103 | NA |