2. R语言基础

在精算建模与保险数据分析中,R语言之所以成为主流工具,核心在于它围绕“数据结构”构建了一整套高效、可复用的分析范式。精算工作面对的数据往往同时包含数值型保费、分类型险种、字符型保单号、时间型承保日期,以及由多个字段组合而成的复杂赔付记录。理解R的数据类型与容器结构,是后续完成经验分析、损失分布拟合、准备金评估和GLM定价的前提。

一、核心原理:R的数据对象是“类型+结构”的组合

R中每一个对象都同时具有数据类型和数据结构两个属性。数据类型决定单个元素如何存储与运算,包括数值型(numeric)、整型(integer)、字符型(character)、逻辑型(logical)、复数型(complex)等;数据结构决定多个元素如何组织,包括向量、矩阵、数组、数据框和列表。精算建模中最常见的误区,是把“数据框”误认为一种数据类型,实际上它是列表的一种特殊形式,每一列可以是不同类型。

向量是R中最基本的容器,要求所有元素类型一致;若混合类型,R会执行强制转换,例如数值与字符混合时全部转为字符。矩阵是二维的同类型向量,适合存放赔付额矩阵、转移概率矩阵或相关系数矩阵。数据框是精算数据集的默认形态,行表示保单或赔案,列表示变量。列表则允许元素类型和长度完全不同,常用于存放模型对象、参数估计结果和多个表格。

R 数据结构与精算数据映射 向量 vector 同类型一维序列 保费、年龄、赔付额 矩阵 matrix 同类型二维结构 转移概率、相关系数 数据框 data.frame 列可不同类型 保单表、赔案表 列表 list 任意类型嵌套 模型结果、参数集 因子 factor 分类变量编码 数值 numeric 连续型金额、比率 字符 character 保单号、险种名称 逻辑 logical 筛选、条件判断 上层为容器结构,下层为元素类型;数据框与列表可容纳多种类型

二、方法流程:从原始数据到可建模对象

在保险数据分析中,建议按以下流程组织R对象:第一步,用c()创建向量,录入保费、赔付额等基础序列;第二步,用matrix()或array()构造多维同类型数据,例如险种间的转移矩阵;第三步,用data.frame()或read.csv()整合为保单—赔案表;第四步,用factor()将险种、地区、渠道等字符变量转为因子,供建模使用;第五步,用list()封装模型输出、参数和诊断结果。

# 1. 向量:录入10张保单的保费
premium <- c(1200, 980, 1500, 760, 2100, 1350, 890, 1750, 640, 1980)

# 2. 因子:险种分类
line <- factor(c("车险","车险","寿险","寿险","车险",
                 "健康险","健康险","车险","寿险","健康险"))

# 3. 数据框:整合为保单数据集
policy <- data.frame(
  policy_id = paste0("P", 1001:1010),
  premium = premium,
  line = line,
  claim = c(0, 500, 0, 1200, 800, 0, 300, 0, 0, 1500)
)

# 4. 矩阵:险种间转移频数
trans_mat <- matrix(c(50, 10, 5,
                      8, 40, 12,
                      6, 9, 35), nrow = 3, byrow = TRUE,
                    dimnames = list(c("车险","寿险","健康险"),
                                    c("车险","寿险","健康险")))

# 5. 列表:封装分析结果
result <- list(
  data = policy,
  mean_premium = mean(policy$premium),
  claim_rate = mean(policy$claim > 0),
  trans = trans_mat
)

三、案例场景:用数据框与因子完成险种经验分析

假设我们需要按险种计算平均保费与出险率。数据框的列选择、因子分组和聚合函数是精算汇总的核心操作。以下代码展示如何用tapply()与aggregate()完成分组统计,并输出可读结果。

# 按险种计算平均保费
tapply(policy$premium, policy$line, mean)

# 按险种汇总保费与出险次数
agg <- aggregate(cbind(premium, claim) ~ line,
                 data = policy,
                 FUN = function(x) c(mean = mean(x), sum = sum(x)))
print(agg)

# 查看因子水平与频数
table(policy$line)
levels(policy$line)

该案例中,factor不仅用于分组,还决定了建模时参照组的设置。若险种因子水平顺序不合理,GLM系数解释会发生变化。因此,精算建模前应使用relevel()明确基准水平,例如将“车险”设为参照组。

提示:数据框默认会将字符列转换为因子(R 4.0之前),R 4.0之后stringsAsFactors默认改为FALSE。读取CSV时建议显式指定stringsAsFactors = FALSE,再按需手动转换因子,避免意外编码。

四、常用函数清单与误区复盘

函数 作用 精算场景
c()创建向量录入保费、赔付额序列
matrix()创建矩阵转移概率、相关系数矩阵
data.frame()创建数据框保单—赔案主表
list()创建列表封装模型结果与参数
factor()创建因子险种、地区、渠道分类
str()查看对象结构检查数据类型是否正确
summary()描述性统计保费与赔付分布概览
tapply()分组聚合按险种计算均值
aggregate()多列分组汇总险种维度经验分析
subset()条件筛选提取已决赔案子集
常见误区:第一,认为数据框每列类型必须相同,实际上每列可独立为数值、字符或因子;第二,用as.numeric()直接转换因子,会得到水平序号而非原始数值,正确做法是先转字符再转数值;第三,矩阵按列填充而byrow默认FALSE,构造转移矩阵时若忽略该参数会导致行列错位;第四,列表用[ ]提取返回子列表,用[[ ]]才返回元素本身,建模取参时需特别注意。