---
title: 基础数学概念
subtitle: 基础篇
author: 胡悦
institute: Learning R with Dr. Hu and His Friends Workshop Series
---

{{< include _extensions/r-wasm/live/_knitr.qmd >}}

# 基础数学概念 {#sec-algebra}

::: {.callout-note title="本章重点"}

1. 基础代数
2. 向量
3. 矩阵与解方程

*本章研究问题*：R 语言中数据分析的底层逻辑是什么？

:::

## 基本运算

- R中的运算符与数学一致：`+`、`-`、`*`、`/`
- 在Console中直接书写算式即可运算

```{webr}
#| label: algebraBasics

# 基础四则运算 (加、减、乘、除)
1 + 2
3 - 4
5 * 6
7 / 8

# 复合运算
(2 + 4) / (5 - 3)
```

---

::: {.callout-tip title="空格的使用"}

- 空格不影响运算，但能提高可读性
- Tidyverse style guide推荐使用空格和空行
- 可用`styler`、`air`等包统一格式

:::

```{webr}
#| label: woSpace

# 虽然下面这行代码加了很多不规则的空格，看起来很乱，但 R 依然能正确运行
(2+4) / (  5-  3            )
```

---

- 幂运算`^`、取余`%%`、对数`log()`/`log10()`、指数`exp()`
- 常用缩写命令：`sqrt()`（平方根）、`abs()`（绝对值）

```{webr}
#| label: moreAlgebra

10^2
5 %% 3 
log(11)
log10(100)
exp(12)

# 开方两种方式
9^(1/2)
sqrt(9)

# 取绝对值
abs(-9)
```

---

- 三角函数：`sin()`、`cos()`、`tan()`、`acos()`、`asin()`、`atan()`
- `pi`是R预存的圆周率常量
- 其他预存常量：`letters`、`LETTERS`、`month.name`、`month.abb`

```{webr}
#| label: trigFunctions

sin(pi)
cos(pi)
tan(pi / 2)
acos(1)
asin(1)
atan(0.5)

```

---

::: {.callout-important title="科学计数法"}

- `e`连接系数与指数，表示10的幂
- 例：200 = 2e2；0.002 = 2e-3

:::

---

- 布尔代数：`TRUE`/`FALSE`（可简写`T`/`F`）
- 逻辑运算：`&`（与）、`|`（或）、`!`（非）
- 空集对象：`NULL`
- 不等式判断：`==`、`!=`、`>`、`<`、`>=`、`<=`

```{webr}
#| label: boolean

# 等式
1 == 2
1 == TRUE # TRUE、FALSE是赋予逻辑属性的1和0
0 != F

# 不等式
1 != 2
1 > 2
1 < 2
1 >= 2
1 <= 2

# 布尔运算

3 > 2 & 2 > 1
12 & 2 > 2
-3 | 2 > 2
```

---

- 布尔运算次序放在最后：先算不等式，再算逻辑
- 单定值参与布尔运算时，会进行自相等判断

::: {.callout-tip title="等于的使用"}

- `==`表达等于，`=`留作赋值符
- 初学者常误用`=`代替`==`，多加练习即可

:::

## 向量

- 向量（vector）：一串有方向的数
- 创建方式：`c()`、`:`（连续整数）、`seq()`

```{webr}
#| label: sequence

# 方式一：使用 c() 函数逐个录入（最基础的方法）
a <- c(11, 12, 13, 14, 15)
# 方式二：使用冒号 : 运算符（仅适用于连续整数）
a1 <- 11:15
# 方式三：使用 seq() 函数（适用于更复杂的序列）
a2 <- seq(from = 11, to = 15, by = 1)
a3 <- seq(11, 15)

# 验证三种方式生成的结果是否完全一致
a == a1
a == a2
a == a3
```

---

- 向量索引：`[]`提取子集
- `a[2]`提取第2个元素，`a[c(3,4)]`提取多个元素

```{webr}
#| label: vector

# 创建演示向量
a <- c(11, 12, 13, 14, 15)

# 提取单个元素（直接写位置编号）
a[2]
a[5]

# 提取多个元素（在方括号内放入一个位置向量）
a[c(3,4)]
```

---

::: {.callout-important title="赋值符`<-`"}

- `<-`是R最常用的赋值符，箭头表示"存进"
- 快捷键：Windows/Linux `Alt + -`，Mac `option + -`
- R几乎是唯一使用`<-`的流行语言，源自APL键盘布局

:::

---

- 向量加减法：对应元素相加减
- 标量与向量运算：标量作用于每个元素

```{webr}
#| label: vectorAdd

a <- c(11, 12, 13, 14, 15)

# 向量与标量加减
b <- a + 4 
c <- a - 0.5 

# 向量加减
a + b 
a - c
```

---

- 元素积（Hadamard积）：`*`，对应位置相乘
- 内积（点乘）：`%*%`，结果为标量
- 张量积（外积）：`%o%`或`outer()`，结果为矩阵

```{webr}
#| label: vecTimes

# 元素积 (Element-wise product)
# 对应位置元素相乘：(a1*b1, a2*b2, ...)
a * b

# 内积 (Inner product / Dot product)
# 结果是一个标量：sum(a*b)
a %*% b

# 外积/张量积 (Outer product)
# 结果是一个矩阵：A[i,j] = a[i] * b[j]
a %o% b

```

---

::: {.callout-tip title="向量的“非常规”运算"}

- R中`a / b`为逐项除法，数学上向量无除法
- 回收原则（recycling rule）：短向量自动重复匹配长向量

:::

```{webr}
#| label: vectorDiv

# 元素逐项相除
# 对应位置元素相除：(a1/b1, a2/b2, ...)
a / b

# 验证运算的可逆性
# 先创建一个新向量 d，它是 a 的 313 倍
d <- a * 313

# 再用 d 除以 a，结果应该全为 313
d / a

```

---

```{webr}
#| label: recycle

# 定义一个短向量 (长度为 2)
e <- c(1, 2)

a * e 
```

---

- 可用`c()`创建字符型向量，需加双引号

```{webr}
#| label: character

# 创建字符向量，注意每个元素需用双引号包裹
aSentence<-c("I","am","from","People's Republic of China", ".")

aSentence

```

## 现学现练 {.unnumbered}

**练习1**：向量回收原则

根据`a`和`e`的赋值，解释并推算下面算式的结果。

::: { .hint exercise="recycle_rule" }

- `a`长度为5，`e`长度为2
- R会将`e`循环扩展为`c(1, 2, 1, 2, 1)`
- 然后逐元素进行运算

:::

```{webr}
#| label: recycle_rule
#| exercise: recycle_rule

a <- 11:15
e <- c(1, 2)

a - e
a / e

```

---

::: { .solution exercise="recycle_rule" }

```r
a <- 11:15
e <- c(1, 2)

# e 被循环为 c(1, 2, 1, 2, 1)
# a - e: c(10, 10, 12, 12, 14)
a - e

# a / e: c(11, 6, 13, 7, 15)
a / e
```

:::

---

**练习2**：推演干支纪年系统

利用向量操作推演六十甲子。规则：阳干配阳支，阴干配阴支。

::: { .hint exercise="ganzhi" }

- 用`seq()`和`%%`区分奇偶位（阴阳属性）
- 用`outer()`生成两组向量的所有组合
- 用`paste0()`将天干地支拼接为文字

:::

```{webr}
#| label: ganzhi
#| exercise: ganzhi

tiangan <- c("甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸")
dizhi <- c("子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥")


```

---

::: { .solution exercise="ganzhi" }

```r
tiangan <- c("甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸")
dizhi <- c("子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥")

# 提取阳性天干（奇数位）和阴性天干（偶数位）
tg_yang <- tiangan[seq(tiangan) %% 2 == 1]
tg_yin <- tiangan[seq(tiangan) %% 2 == 0]

# 提取阳性地支（奇数位）和阴性地支（偶数位）
dz_yang <- dizhi[seq(dizhi) %% 2 == 1]
dz_yin <- dizhi[seq(dizhi) %% 2 == 0]

# 阳干配阳支
outer(tg_yang, dz_yang, FUN = paste0)
# 阴干配阴支
outer(tg_yin, dz_yin, FUN = paste0)
```

:::

## 矩阵

- 矩阵：二维，由多个向量组成
- `matrix()`创建，按列填充（column-major order）
- `nrow`或`ncol`指定维度（二选一）

```{webr}
#| label: matrix

# 创建一个 2 行的矩阵，数据按列填充
matrix(c(1, 2, 3, 4), nrow = 2)
```

---

- 矩阵也遵循回收原则

```{webr}
#| label: matrixRecycle

# 创建一个 2 行的矩阵
matrix(1:3, nrow = 2)

```

---

- 矩阵索引：`A[行, 列]`
- 行或列留空代表选择全行或全列

```{webr}
#| label: matrixCell

# 准备工作：先建立矩阵 A
A <- matrix(1:3, nrow = 2)

# 精确提取：提取第 1 行、第 2 列的那个特定元素
A[1, 2]

# 行提取：提取第 1 行的所有元素
A[1, ]
# 列提取：提取第 2 列的所有元素
A[, 2]
```

---

- 转置：`t()`，行列互换
- 两次转置还原

```{webr}
#| label: matrixTrans

# 查看原始矩阵
A
# 进行一次转置
t(A)
# 进行两次转置（还原）
t(t(A))
```

---

::: {.callout-important title="嵌套调用的逻辑"}

- "由内而外"：先算最内层，结果作为外层输入
- 类似数学复合函数 $g(f(x))$

:::

---

- 矩阵加减法：同维矩阵，对应元素相加减
- 矩阵乘法：元素积`*`、内积`%*%`（前列=后行）、张量积`%o%`、交叉积`crossprod()`

```{webr}
#| label: matrixTimes

# 准备数据：创建不同维度的矩阵
B <- matrix(1:6, nrow = 2)
C <- matrix(6:1, nrow = 2)
D <- matrix(6:1, nrow = 3)

# 查看矩阵结构
B
C
D

# 基础运算 (要求维度相同)
B + C
B - C

# 乘法"大观园"：分别是元素积、内积、张量积、交叉积
B * C
B %*% D
B %o% C
crossprod(B, C)

```

---

- `solve()`求解线性方程组
- 解方程与回归方程的矩阵表示高度相似

```{webr}
#| label: solve

# 定义方程组的系数矩阵 B (3x3)
# 对应方程左边的系数：a, b, c 的参数
B <- matrix(c(1, 3, 2, 1, 2, 2, 1, 4, -6), nrow = 3)
B

# 定义方程组的常数项向量 y
# 对应方程右边的结果：6, 9, 4
y <- c(6, 9, 4)

# 求解线性方程组
# 寻找向量 x，使得 B %*% x = y (即求出 a, b, c 的值)
x <- solve(B, y)
x

```

## 本章重点及回顾

::: {.callout-note title="小提示"}

本章以及后续章节将涵盖较多知识点。
其中，部分内容无需一次性掌握，建立初步印象即可，很多知识点的内涵以及操作将会在后续章节的场景应用中逐步深化理解。而另外一些内容则构成当前阶段的关键基础，若未能及时掌握，将直接影响后续理解。
因此，每章结尾将设置要点小结，明确标识读者当前必须掌握的核心内容。

:::

:::: {.columns}

::: {.column width="50%"}

- 数据赋值：`<-`
- 布尔逻辑
    - 判断符：`==`, `!=`, `>`, `<`
    - 逻辑符：`&` (与), `|` (或), `! `(非)
- 向量及索引
    - 向量创建:`c()`
    - 生成特定序列:`seq()`
    - 向量索引:`[]`

:::

::: {.column width="50%"}

- 矩阵
    - 创建矩阵:`matrix()`
    - 维度查看:`nrow()`, `ncol()`
    - 矩阵转置:`t()`
    - 矩阵求解/求逆：`solve()`

:::

::::


