先看数值类型
先看类别,再看存储
class()对象属于哪一类?
typeof()底层如何存储?
# 将 3 个数值组成向量,赋值给 xx <- c(18, 21, 24)class(x) # 输出:"numeric"typeof(x) # 输出:"double"
numeric- 数值型:
x属于数值对象 double- 双精度浮点型:数值在底层的存储方式
SECTION01 / 05
Data Types and Structures
Every object has a type and a structure
先问“里面是什么”,再问“这些值怎样组织”。
xyx <- c(18, 21, 24)
class(x)numeric数值型
typeof(x)double双精度浮点型
length(x) = 3
y <- data.frame(...)
| score | passed |
|---|---|
| 18 | TRUE |
| 21 | FALSE |
| 24 | TRUE |
class(y)data.frame数据框
typeof(y)list列表
dim(y) = 3 × 2
先看数值类型再看数据框
class()对象属于哪一类?
typeof()底层如何存储?
# 将 3 个数值组成向量,赋值给 xx <- c(18, 21, 24)class(x) # 输出:"numeric"typeof(x) # 输出:"double"
numericx 属于数值对象double# 将两列数据存入数据框 yy <- data.frame(score = c(18, 21, 24), passed = c(TRUE, FALSE, TRUE))class(y) # 输出:"data.frame"typeof(y) # 输出:"list"
data.framelist再看组织方式
str() 展开对象的组织方式x <- c(18, 21, 24)
str(x) # num [1:3] 18 21 24
length(x) # 3x 是长度为 3 的数值向量;数值依次排成一列。
str(y)# 'data.frame': 3 obs. of 2 variables:# $ score : num 18 21 24# $ passed: logi TRUE FALSE TRUEdim(y) # 输出:3 行、2 列y 有 3 行、2 列。每列可以存放不同类型的值,但各列长度相同。
判断顺序:先确认向量中存放的值属于什么类型,再判断这些值如何组织;"21" 看似数字,实际是文本。留意:class(y) 是 data.frame,而 typeof(y) 是 list;这两条命令查看的层次不同。
Data frames and tibbles
同一份数据,打印出来有什么区别?
data.frameR 自带的数据框:数据按行列排列,不同列可以保存不同类型的值。
tibbletidyverse 中 tibble 包提供的数据框变体;保留行列结构,打印结果更简洁。
df <- data.frame(id = sprintf("S%02d", 1:30), score = 61:90)tb <- tibble::as_tibble(df)data.frame默认继续打印> dfid score 1 S01 61 2 S02 62 3 S03 63 4 S04 64 5 S05 65 6 S06 66 7 S07 67 8 S08 68 9 S09 69 10 S10 70 11 S11 71
输出节选:后续还会继续打印至第 30 行
tibble默认预览前 10 行> tb# A tibble: 30 × 2 id score <chr> <int> 1 S01 61 2 S02 62 3 S03 63 4 S04 64 5 S05 65 6 S06 66 7 S07 67 8 S08 68 9 S09 69 10 S10 70 # ℹ 20 more rows # ℹ Use `print(n = ...)` to see more rows
SECTION02 / 05
Tidy Data
Principles of tidy data
Each variable forms a column.
Each observation forms a row.
Each type of observational unit forms a table.
Each value is a cell; each cell is a single value.
> gapminder| country<fct> | continent<fct> | year<int> | lifeExp<dbl> | pop<int> | gdpPercap<dbl> | |
|---|---|---|---|---|---|---|
| 1 | Afghanistan | Asia | 1952 | 28.8 | 8425333 | 779. |
| 2 | Afghanistan | Asia | 1957 | 30.3 | 9240934 | 821. |
| 3 | Afghanistan | Asia | 1962 | 32.0 | 10267083 | 853. |
| 4 | Afghanistan | Asia | 1967 | 34.0 | 11537966 | 836. |
| 5 | Afghanistan | Asia | 1972 | 36.1 | 13079460 | 740. |
| 6 | Afghanistan | Asia | 1977 | 38.4 | 14880372 | 786. |
| 7 | Afghanistan | Asia | 1982 | 39.9 | 12881816 | 978. |
| 8 | Afghanistan | Asia | 1987 | 40.8 | 13867957 | 852. |
| 9 | Afghanistan | Asia | 1992 | 41.7 | 16317921 | 649. |
| 10 | Afghanistan | Asia | 1997 | 41.8 | 22227415 | 635. |
print(n = ...) to see more rows注:整洁数据仍可能有缺失、录入错误、异常值或失真的测量。
Recognising Tidy Data
| district_id | district | pop_2019 | pop_2020 | pop_2021 |
|---|---|---|---|---|
| D01 | 甲区 | 118000 | 120000 | 125000 |
| D02 | 乙区 | 96000 | 98000 | 102000 |
| D03 | 丙区 | 148000 | 150000 | 154000 |
| D04 | 丁区 | 80000 | 82000 | 84000 |
| D05 | 戊区 | 111000 | 113000 | 116000 |
| D06 | 己区 | 74000 | 76000 | 79000 |
| ... 更多地区 | ||||
| Ozone | Solar.R | Wind | Temp | Month | Day |
|---|---|---|---|---|---|
| 41 | 190 | 7.4 | 67 | 5 | 1 |
| 36 | 118 | 8.0 | 72 | 5 | 2 |
| 12 | 149 | 12.6 | 74 | 5 | 3 |
| 18 | 313 | 11.5 | 62 | 5 | 4 |
| NA | NA | 14.3 | 56 | 5 | 5 |
| 28 | NA | 14.9 | 66 | 5 | 6 |
| 23 | 299 | 8.6 | 65 | 5 | 7 |
| ... 更多日期 | |||||
| site | date | reading | wind_ms | rain_mm |
|---|---|---|---|---|
| 河岸 | 2024-07-01 | 21.5°C / 66% | 2.4 | 0.0 |
| 河岸 | 2024-07-02 | 23.1°C / 61% | 3.1 | 0.2 |
| 山麓 | 2024-07-01 | 18.4°C / 74% | 1.8 | 1.4 |
| 山麓 | 2024-07-02 | 19.6°C / 72% | 2.2 | 0.6 |
| 平原 | 2024-07-01 | 26.2°C / 54% | 4.1 | 0.0 |
| 平原 | 2024-07-02 | 27.1°C / 51% | 4.6 | 0.0 |
| ... 更多地点与日期 | ||||
| neighborhood | pop_2020 | pop_2021 | respondent_id | age | satisfaction |
|---|---|---|---|---|---|
| N1 | 1000 | 1100 | R01 | 29 | 4 |
| N1 | 1000 | 1100 | R02 | 41 | 3 |
| N2 | 800 | 820 | R03 | 35 | 5 |
| N2 | 800 | 820 | R04 | 50 | 2 |
| N3 | 1200 | 1270 | R05 | 33 | 4 |
| N3 | 1200 | 1270 | R06 | 46 | 3 |
| ... 更多社区与受访者 | |||||
01 / 04第 02 组取自 R 内置 airquality;其余为教学示例
SECTION03 / 05
Data Manipulation with the tidyverse
A Coordinated Collection of R Packages
tidyverse 是一组协作的 R 包。9 个核心包覆盖数据读取、整理、变换与可视化等任务。
围绕数据科学工作流程设计的包的组合。
library(tidyverse)绘制统计图形
筛选、变换与汇总数据
整理数据的长宽结构
读取 CSV 等文本数据
迭代处理与批量运算
更易阅读的数据框
处理与匹配字符串
整理分类变量(因子)
解析与计算日期时间
Trace a tidyverse workflow, step by step
library(tidyverse)
library(gapminder)
continent_change <- gapminder %>%
filter(year %in% c(1997, 2007)) %>%
select(continent, year, lifeExp) %>%
group_by(continent, year) %>%
summarise(mean_life = mean(lifeExp), .groups = "drop") %>%
pivot_wider(names_from = year, values_from = mean_life,
names_prefix = "life_") %>%
mutate(gain = life_2007 - life_1997) %>%
arrange(desc(gain)) %>%
slice_head(n = 3)
Joining tables by a shared key
sites| site_id | district |
|---|---|
| A01 | 黄浦 |
| A02 | 徐汇 |
| A03 | 浦东 |
| A04 | 长宁 |
indicators| site_id | index | green_pct | sample_n |
|---|---|---|---|
| A01 | 84 | 23.4 | 120 |
| A02 | 76 | 18.7 | 96 |
| A03 | 91 | 27.1 | 142 |
| A05 | 68 | 15.9 | 83 |
sites %>% left_join(indicators, by = "site_id")左表 4 行全部保留。A04 没有指标,得到 NA;右表独有的 A05 不会加入。
| site_id | district | index | green_pct | sample_n |
|---|---|---|---|---|
| A01 | 黄浦 | 84 | 23.4 | 120 |
| A02 | 徐汇 | 76 | 18.7 | 96 |
| A03 | 浦东 | 91 | 27.1 | 142 |
| A04 | 长宁 | NA | NA | NA |
sites %>% inner_join(indicators, by = "site_id")只保留 两表都有 的 A01–A03;A04 和 A05 都不进入结果。
| site_id | district | index | green_pct | sample_n |
|---|---|---|---|---|
| A01 | 黄浦 | 84 | 23.4 | 120 |
| A02 | 徐汇 | 76 | 18.7 | 96 |
| A03 | 浦东 | 91 | 27.1 | 142 |
sites %>% anti_join(indicators, by = "site_id")只找出左表 没有匹配 的 A04。适合排查连接键;结果不添加右表的列。
| site_id | district |
|---|---|
| A04 | 长宁 |
chosen <- select(indicators, site_id, index)sites %>% left_join(chosen, by = "site_id")先保留连接键 site_id 和需要的 index,再连接;结果只新增这一列指标。
| site_id | district | index |
|---|---|---|
| A01 | 黄浦 | 84 |
| A02 | 徐汇 | 76 |
| A03 | 浦东 | 91 |
| A04 | 长宁 | NA |
SECTION04 / 05
Data Cleaning and Diagnostics
Diagnose before cleaning
| id | wave | district | visits | status | source |
|---|---|---|---|---|---|
| A01 | 2023 | Huangpu | 120 | 开放 | app |
| A02 | 2023 | Xuhui | NA | 开放 | NA |
| A02 | 2023 | Xuhui | 95 | 开放 | app |
| A03 | 2023 | Pudong | 0 | 暂停 | manual |
| A04 | 2024 | Huangpu | 140 | 开放 | APP |
| A05 | 2024 | Xuhui | 87 | 开放 | app |
| A06 | 2024 | Pudong | 210 | 开放 | app |
| A06 | 2024 | Pudong | 210 | 开放 | app |
Rows: 8
Columns: 6
$ id <chr> "A01", "A02", "A02", "A03", ...
$ wave <int> 2023, 2023, 2023, 2023, ...
$ district <chr> "Huangpu", "Xuhui", "Xuhui", ...
$ visits <dbl> 120, NA, 95, 0, 140, 87, ...
$ status <chr> "开放", "开放", "开放", "暂停", ...
$ source <chr> "app", NA, "app", "manual", ... Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.0 91.0 120.0 123.1 175.0 210.0 1| id | wave | district | visits | status | source |
|---|---|---|---|---|---|
| <chr> | <int> | <chr> | <dbl> | <chr> | <chr> |
| A02 | 2023 | Xuhui | NA | 开放 | NA |
| id | wave | n |
|---|---|---|
| A01 | 2023 | 1 |
| A02 | 2023 | 2 |
| A03 | 2023 | 1 |
| A04 | 2024 | 1 |
| A05 | 2024 | 1 |
| A06 | 2024 | 2 |
Handling missing data
先查缺失原因,再决定删行或填补。
drop_na()
优点简单、可解释,不凭空补值。
代价损失样本;缺失有规律时可能产生偏差。
replace_na()
mean() / median()优点保留记录,便于快速建立基线。
代价压缩差异,也可能改变变量间的关系。
利用其他变量;单次填补低估波动。
多次填补后合并,表达不确定性。
随机森林等拟合非线性关系。
扩散模型已有表格插补研究。
ARIMA 看时间;ST-ARIMA 加入空间。
按周/月汇总,并检查有效天数。
LLM 可用于探索,但不应将逐格猜值当作通用可靠的填补方法。
Sources: Journal of Big Data (2021) · Infant and Child Development (2023) · Frontiers in Big Data (2021) · ACM TKDD (2025)
Blanks, formats, and column names
str_squish()先去掉多余空格,再把空字符串转为 NA。
" "3 个空格NA真正的缺失值提醒再用 dplyr::na_if() 转成缺失值;数值 0 不是空白。
parse_number()单位和分隔符混在取值里,会妨碍直接计算。
"1,200 人"逗号与单位混在数值里1200可以参与计算提醒解析前核对单位、小数点与千位分隔符。
ymd_hms()T、Z 是格式,不是脏字符解析时间戳时,保留时区信息。
2026-09-25T14:30:00ZISO 格式时间戳2026-09-25 14:30 UTC带时区的日期时间提醒T 分隔日期与时间;Z 表示 UTC。
clean_names()空格、标点或重名都可能增加代码错误。
Student ID含空格student_id便于代码引用提醒若出现 student_id_2,应回查原始重名。
rownames_to_column()记录标识留在行名里,导出或连接时容易遗漏。
A01 · A02表内没有显式 ID 列site_idA01、A02 成为列取值提醒先确认行名能否唯一标识记录。
str_to_lower()大小写或尾部空格会制造多余类别。
"Female" / "female "看似同一类别"female"归入同一组提醒先用 str_squish() 去空格;同义词仍需数据字典。
SECTION05 / 05
Exploratory Data Analysis
Exploratory Data Analysis (EDA)
通过统计摘要、表格与图形,系统查看数据的结构、分布、异常和变量关系。
Distributions and Descriptive Statistics
Univariate exploration
一次只看一个变量的形状与异常。
本章先学读图;绘图操作后续展开。
先核对缺失与完整率,再看分布和分位数。
skimr 为扩展包,需预先安装library(tidyverse)
library(gapminder)
library(skimr)
gapminder %>%
select(lifeExp, pop, gdpPercap) %>%
skim()skim() 输出节选numeric| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
lifeExp | 0 | 1 | 59.5 | 12.9 | 23.6 | 48.2 | 60.7 | 70.8 | 82.6 | |
pop | 0 | 1 | 29601212. | 106157897. | 60011 | 2793664 | 7023596. | 19585222. | 1318683096 | |
gdpPercap | 0 | 1 | 7215. | 9857. | 241. | 1202. | 3532. | 9325. | 113523. |
统计列与数值按实际输出整理;微型直方图为分布轮廓示意。
第三周:第二章 重点解析