01 · R 语言数据类型与相应运算
1 变量与类型检查
在 R 里可以把“变量”理解成给一块数据贴上的标签:把一个数值、字符或逻辑值存到某个名字下面,后面就可以一直用这个名字来引用它。在中医药数据里,剂量、药名、是否复诊、证型 等信息,都会被存成不同类型的变量。掌握如何创建变量、以及用函数检查它们的类型,是后面一切数据分析的起点。
1.1 创建变量(把数据存到名字里)
# 在中医处方数据里,“剂量”通常是数值
dose_g <- 10
# “药名”是字符
herb <- "黄芪"
# “是否复诊”可以用逻辑
revisit <- TRUE
1.2 类型查看函数
class(dose_g)
typeof(dose_g)
str(dose_g)
class(herb)
class(revisit)
2 数值:剂量与运算
数值型是医学数据中最常见的一类,包括药物剂量、体温、血压、实验室检验值、疗程天数等。R 里所有的数值最终都会以向量的形式存在,可以是一个数,也可以是一整列数据。熟悉整数/小数的表示方式,以及四则运算、取余、幂运算等,是进行剂量计算、指标换算和各种统计量(均值、方差、标准差)分析的基础。
2.1 整数(integer)与小数(double)
R 里 1 默认是小数类型(double),想表示整数可以写 1L。
x <- 1
class(x) # "numeric"(通常是 double)
i <- 1L
class(i) # "integer"
2.2 常用运算(剂量/天数/分次)
# 假设:黄芪 30g,分 2 次
huangqi_g <- 30
times_per_day <- 2
each_time_g <- huangqi_g / times_per_day
each_time_g
# 取余:比如 7 天为一疗程,15 天能完整做几疗程?剩几天?
days <- 15
days %/% 7 # 完整疗程数
days %% 7 # 剩余天数
2.3 数值向量与“向量化运算”(一次算一串)
# 一张处方里 5 味药的剂量(单位 g)
doses <- c(15, 10, 6, 12, 3)
# 全部剂量加 1g(比如统一加量做对照)
doses + 1
# 计算每味药占总剂量的比例
doses / sum(doses)
3 逻辑:筛选条件(TRUE / FALSE)
逻辑型变量只取 TRUE / FALSE(以及可能的缺失 NA),在医学数据中常用于表示“是否”类信息,例如“是否合并糖尿病”“是否为女性”“是否完成随访”等。比较运算和逻辑运算(>=、&、| 等)会生成一整列 TRUE/FALSE,配合下标就能完成数据筛选,是做“按条件取子集”的核心工具。
3.1 比较运算:会得到 TRUE/FALSE
age <- c(18, 20, 19, 22)
age >= 20
doses > 10
doses == 10
3.2 & 与 && 的区别
& 对向量逐个比较;&& 只看第一个元素(常用于 if)。
c(TRUE, FALSE) & c(TRUE, TRUE)
c(TRUE, FALSE) && c(TRUE, TRUE)
4 字符:药名与文本处理(character)
字符型变量用于存放文本信息,例如中药名、方剂名、证型描述、主诉和诊断等。和 Excel 一样,R 也可以对字符串做拼接、替换、截取等操作;配合正则表达式和 stringr 这类包,还能从中医病案全文中批量提取药名、剂量、证型标签,为后续结构化建库和文本挖掘做准备。
4.1 拼接与长度
herbs <- c("黄芪", "当归", "党参")
nchar(herbs) # 每个药名的字数
paste(herbs, "10g") # 拼接(默认有空格)
paste0(herbs, "_10g") # 拼接(不加空格)
4.2 替换与截取
s <- "当归 10g"
gsub("10g", "12g", s)
substr(s, 1, 2) # 截取前 2 个字符
4.3 字符转数值(能转就转,不能转就 NA)
as.numeric("12") # 12
as.numeric("12g") # NA(转不了)
5 因子:证型分类(factor)
factor 专门用来表示“类别”型数据,是做统计建模时非常关键的一种类型。像 性别(男/女)、证型(气虚/血虚/痰湿/湿热…)、分组(对照/实验) 等,都适合存成因子而不是普通字符。因子带有 levels(水平)和可能的顺序关系(有序因子),很多统计函数会根据这些水平自动生成分组统计或虚拟变量。
5.1 levels 与频数
# 证型(分类变量)
zheng <- factor(c("气虚", "血虚", "气虚", "湿热", "气虚"))
levels(zheng)
table(zheng) # 每类出现几次
5.2 因子常见坑:别把因子当字符串乱拼
z <- factor(c("A", "B", "A"))
paste0("组别=", z) # 会工作,但很多文本处理建议先转字符
paste0("组别=", as.character(z))
6 缺失值:NA(真实临床数据非常常见)
真实世界的医学数据几乎不可能“完完整整”,量血压忘记记录舒张压、实验室报告缺乏某项指标、随访病人失访,这些都需要在 R 中用 NA 来表示“缺失”。一旦数据里出现 NA,很多运算(如 mean、sum)默认都会给出 NA 作为结果,因此要学会先用 is.na() 找出缺失,再用 na.rm = TRUE 或其他方法进行恰当处理。
6.1 is.na:找出缺失
# 比如:某味药剂量未记录
doses2 <- c(10, NA, 6, 12)
is.na(doses2)
sum(is.na(doses2))
6.2 na.rm:统计时忽略 NA
mean(doses2) # NA
mean(doses2, na.rm = TRUE) # 正常数值
is.na();表达式 NA == NA 的结果仍为 NA。
7 常见容器:用“处方表”理解 vector / list / data.frame
到目前为止出现的各种类型(数值、字符、逻辑、因子)最终都要放进“容器”里,才构成完整的数据结构。在 R 中,最常用的三种基础容器是:一列同类型数据的 vector,能装下一个病例全部信息的 list,以及把很多病例按“行 × 列”排成表格的 data.frame。可以把它们类比为:单列处方剂量表、单个病历卡片、以及整张门诊登记或临床试验数据表。
7.1 vector:一列同类型
# 一列“剂量”(同类型)
dose_col <- c(10, 12, 9, 15)
7.2 list:病人信息的复合记录
patient <- list(
id = "P001",
age = 19,
zheng = "气虚",
herbs = c("黄芪", "党参", "白术"),
doses = c(30, 15, 12)
)
patient$id
patient$herbs
patient$doses
7.3 data.frame:处方数据表(最常用)
在医学统计与数据挖掘中,最常见的原始数据形式,就是“像 Excel/数据库那样”的表格:每一行是一条记录(例如一位患者一次就诊或一次随访),每一列是一个变量(如年龄、性别、证型、化验指标、用药剂量等),不同列可以是不同类型的数据。
在 R 语言里,这种“行 = 观测、列 = 变量”的结构就叫做 数据框(data.frame)。它可以看作是一个特殊的 list:每一列本质上都是一个长度相同的向量(数值、因子、字符、日期时间等),同一列中的数据类型必须一致,而不同列之间可以是不同的数据类型。这种设计非常适合承载临床试验数据表、门诊登记表、体检数据等各种医学原始数据。
rx <- data.frame(
patient_id = c("P001", "P002", "P003"),
zheng = factor(c("气虚", "湿热", "血虚")),
formula = c("补中益气汤", "三仁汤", "四物汤"),
herb = c("黄芪", "薏苡仁", "当归"),
dose_g = c(30, 20, 10),
stringsAsFactors = FALSE
)
rx
rx$dose_g
rx[1, ]
rx[, c(\"patient_id\", \"formula\", \"dose_g\")]
8 练习
- 创建向量
d <- c(30, 15, NA, 12, 9),求总剂量(忽略 NA)。 - 创建字符向量
h <- c(\"黄芪\", \"当归\"),拼出\"黄芪_当归\"。 - 创建因子
z <- factor(c(\"气虚\",\"血虚\",\"气虚\")),输出频数。 - 在上面的
rx表里,筛出dose_g >= 20的行(示例:rx[rx$dose_g >= 20, ])。
vector / data.frame / list,并掌握 is.na() 与向量化运算的基本用法。