R语言学习笔记缺失数据的Bootstrap与Jackknife方法

目录
  • 一、题目
  • 二、解答
    • a)Bootstrap与Jackknife进行估计
    • b)均值与变异系数(大样本)的标准差解析式推导与计算
    • c)缺失插补前的Bootstrap与Jackknife
    • d)比较各种方式的90%置信区间情况(重复100次实验)
    • 填补之前进行Bootstrap或Jackknife
    • 填补之后进行Bootstrap或Jackknife

一、题目

下面再加入缺失的情况来继续深入探讨,同样还是如习题1.6的构造方式来加入缺失值,其中a=2, b = 0

我们将进行如下几种操作:

二、解答

a)Bootstrap与Jackknife进行估计

首先构建生成数据函数。

# 生成数据
# 生成数据
GenerateData <- function(a = 0, b = 0) {
  y <- matrix(nrow = 3, ncol = 100)
  z <- matrix(rnorm(300), nrow = 3)

  y[1, ] <- 1 + z[1, ]
  y[2, ] <- 5 + 2 * z[1, ] + z[2, ]

  u <- a * (y[1, ] - 1) + b * (y[2, ] - 5) + z[3, ]
  # m2 <- 1 * (u < 0)

  y[3, ] <- y[2, ]
  y[3, u < 0] <- NA

  dat_comp <- data.frame(y1 = y[1, ], y2 = y[2, ])
  dat_incomp <- data.frame(y1 = y[1, ], y2 = y[3, ])
  # dat_incomp <- na.omit(dat_incomp)

  return(list(dat_comp = dat_comp, dat_incomp = dat_incomp))
}

Bootstrap与Jackknife的函数:

Bootstrap1 <- function(Y, B = 200, fun) {
  Y_len <- length(Y)
  mat_boots <- matrix(sample(Y, Y_len * B, replace = T), nrow = B, ncol = Y_len)
  statis_boots <- apply(mat_boots, 1, fun)
  boots_mean <- mean(statis_boots)
  boots_sd <- sd(statis_boots)
  return(list(mean = boots_mean, sd = boots_sd))
}

Jackknife1 <- function(Y, fun) {
  Y_len <- length(Y)
  mat_jack <- sapply(1:Y_len, function(i) Y[-i])
  redu_samp <- apply(mat_jack, 2, fun)
  jack_mean <- mean(redu_samp)
  jack_sd <- sqrt(((Y_len - 1) ^ 2 / Y_len) * var(redu_samp))
  return(list(mean = jack_mean, sd = jack_sd))
}

进行重复试验所需的函数:

RepSimulation <- function(seed = 2018, fun) {
  set.seed(seed)
  dat <- GenerateData()
  dat_comp_y2 <- dat$dat_comp$y2
  boots_sd <- Bootstrap1(dat_comp_y2, B = 200, fun)$sd
  jack_sd <- Jackknife1(dat_comp_y2, fun)$sd
  return(c(boots_sd = boots_sd, jack_sd = jack_sd))
}

下面重复100次实验进行 Y2​的均值与变异系数标准差的估计:

nrep <- 100
## 均值
fun = mean
mat_boots_jack <- sapply(1:nrep, RepSimulation, fun)
apply(mat_boots_jack, 1, function(x) paste(round(mean(x), 3), '±', round(sd(x), 3)))
## 变异系数
fun = function(x) sd(x) / mean(x)
mat_boots_jack <- sapply(1:nrep, RepSimulation, fun)
apply(mat_boots_jack, 1, function(x) paste(round(mean(x), 3), '±', round(sd(x), 3)))

从上面可以发现,Bootstrap与Jackknife两者估计结果较为相近,其中对均值标准差的估计,Jackknife的方差更小。这其实较为符合常识:Jackknife估计每次只取出一个样本,用剩下的样本来作为样本整体;而Bootstrap每次都会比较随机地重抽样,随机性相对较高,所以重复100次模拟实验,导致其方差相对较大。

下面我们用计算公式来进行推导。

b)均值与变异系数(大样本)的标准差解析式推导与计算

均值

变异系数(大样本近似)

## 变异系数
sd(sapply(1:10000, function(x) {
  set.seed(x)
  dat <- GenerateData(a = 0, b = 0)
  sd(dat$dat_comp$y2) / mean(dat$dat_comp$y2)
}))

变异系数大样本近似值为:0.03717648,说明前面的Bootstrap与Jackknife两种方法估计的都较为准确。

c)缺失插补后的Bootstrap与Jackknife

构造线性填补的函数,并进行线性填补。

DatImputation <- function(dat_incomp) {
  dat_imp <- dat_incomp
  lm_model = lm(y2 ~ y1, data = na.omit(dat_incomp))

  # 找出y2缺失对应的那部分data
  na_ind = is.na(dat_incomp$y2)
  na_dat = dat_incomp[na_ind, ]

  # 将缺失数据进行填补
  dat_imp[na_ind, 'y2'] = predict(lm_model, na_dat)
  return(dat_imp)
}

dat <- GenerateData(a = 2, b = 0)
dat_imp <- DatImputation(dat$dat_incomp)
fun = mean
Bootstrap1(dat_imp$y2, B = 200, fun)$sd
Jackknife1(dat_imp$y2, fun)$sd
fun = function(x) sd(x) / mean(x)
Bootstrap1(dat_imp$y2, B = 200, fun)$sd
Jackknife1(dat_imp$y2, fun)$sd

Bootstrap与Jackknife的填补结果,很大一部分是由于数据的缺失会造成距离真实值较远。但单从两种方法估计出来的值比较接近。

c)缺失插补前的Bootstrap与Jackknife

先构建相关的函数:

Array2meancv <- function(j, myarray) {
  dat_incomp <- as.data.frame(myarray[, j, ])
  names(dat_incomp) <- c('y1', 'y2')
  dat_imp <- DatImputation(dat_incomp)
  y2_mean <- mean(dat_imp$y2)
  y2_cv <- sd(dat_imp$y2) / y2_mean
  return(c(mean = y2_mean, cv = y2_cv))
}

Bootstrap_imp <- function(dat_incomp, B = 200) {
  n <- nrow(dat_incomp)
  array_boots <- array(dim = c(n, B, 2))
  mat_boots_ind <- matrix(sample(1:n, n * B, replace = T), nrow = B, ncol = n)

  array_boots[, , 1] <- sapply(1:B, function(i) dat_incomp$y1[mat_boots_ind[i, ]])
  array_boots[, , 2] <- sapply(1:B, function(i) dat_incomp$y2[mat_boots_ind[i, ]])

  mean_cv_imp <- sapply(1:B, Array2meancv, array_boots)
  boots_imp_mean <- apply(mean_cv_imp, 1, mean)
  boots_imp_sd <- apply(mean_cv_imp, 1, sd)
  return(list(mean = boots_imp_mean, sd = boots_imp_sd))
}

Jackknife_imp <- function(dat_incomp) {
  n <- nrow(dat_incomp)
  array_jack <- array(dim = c(n - 1, n, 2))

  array_jack[, , 1] <- sapply(1:n, function(i) dat_incomp[-i, 'y1'])
  array_jack[, , 2] <- sapply(1:n, function(i) dat_incomp[-i, 'y2'])

  mean_cv_imp <- sapply(1:n, Array2meancv, array_jack)
  jack_imp_mean <- apply(mean_cv_imp, 1, mean)
  jack_imp_sd <- apply(mean_cv_imp, 1, function(x) sqrt(((n - 1) ^ 2 / n) * var(x)))
  return(list(mean = jack_imp_mean, sd = jack_imp_sd))
}

然后看看两种方式估计出来的结果:

Bootstrap_imp(dat$dat_incomp)$sd
Jackknife_imp(dat$dat_incomp)$sd

缺失插补前进行Bootstrap与Jackknife也还是有一定的误差,标准差都相对更大,表示波动会比较大。具体表现情况下面我们多次重复模拟实验,通过90%置信区间来看各个方法的优劣。

d)比较各种方式的90%置信区间情况(重复100次实验)

RepSimulationCI <- function(seed = 2018, stats = 'mean') {
  mean_true <- 5
  cv_true <- sqrt(5) / 5

  myjudge <- function(x, value) {
    return(ifelse((x$mean - qnorm(0.95) * x$sd < value) & (x$mean + qnorm(0.95) * x$sd > value), 1, 0))
  }

  if(stats == 'mean') {
    fun = mean
    value = mean_true
  } else if(stats == 'cv') {
    fun = function(x) sd(x) / mean(x)
    value = cv_true
  }

  set.seed(seed)
  boots_after_ind <- boots_before_ind <- jack_after_ind <- jack_before_ind <- 0

  dat <- GenerateData(a = 2, b = 0)
  dat_incomp <- dat$dat_incomp

  # after imputation
  dat_imp <- DatImputation(dat_incomp)

  boots_after <- Bootstrap1(dat_imp$y2, B = 200, fun)
  boots_after_ind <- myjudge(boots_after, value)
  jack_after <- Jackknife1(dat_imp$y2, fun)
  jack_after_ind <- myjudge(jack_after, value)

  # before imputation
  boots_before <- Bootstrap_imp(dat_incomp)
  jack_before <- Jackknife_imp(dat_incomp)

  if(stats == 'mean') {

    boots_before$mean <- boots_before$mean[1]
    boots_before$sd <- boots_before$sd[1]
    jack_before$mean <- jack_before$mean[1]
    jack_before$sd <- jack_before$sd[1]

  } else if(stats == 'cv') {

    boots_before$mean <- boots_before$mean[2]
    boots_before$sd <- boots_before$sd[2]
    jack_before$mean <- jack_before$mean[2]
    jack_before$sd <- jack_before$sd[2]

  }

  boots_before_ind <- myjudge(boots_before, value)
  jack_before_ind <- myjudge(jack_before, value)

  return(c(boots_after = boots_after_ind,
           boots_before = boots_before_ind,
           jack_after = jack_after_ind,
           jack_before = jack_before_ind))
}

重复100次实验,均值情况:

nrep <- 100
result_mean <- apply(sapply(1:nrep, RepSimulationCI, 'mean'), 1, sum)
names(result_mean) <- c('boots_after', 'boots_before', 'jack_after', 'jack_before')
result_mean

变异系数情况:

result_cv <- apply(sapply(1:nrep, RepSimulationCI, 'cv'), 1, sum)
names(result_cv) <- c('boots_after', 'boots_before', 'jack_after', 'jack_before')
result_cv

上面的数字越表示90%置信区间覆盖真实值的个数,数字越大表示覆盖的次数越多,也就说明该方法会相对更好。

填补之前进行Bootstrap或Jackknife

无论是均值还是变异系数,通过模拟实验都能看出,在填补之前进行Bootstrap或Jackknife,其估计均会远优于在填补之后进行Bootstrap或Jackknife。而具体到Bootstrap或Jackknife,这两种方法相差无几。

填补之后进行Bootstrap或Jackknife

在填补之后进行Bootstrap或Jackknife,效果都会很差,其实仔细思考后也能够理解,本身缺失了近一半的数据,然后填补会带来很大的偏差,此时我们再从中抽样,有很大可能抽出来的绝大多数都是原本填补的有很大偏差的样本,这样估计就会更为不准了。

当然,从理论上说,填补之前进行Bootstrap或Jackknife是较为合理的,这样对每个Bootstrap或Jackknife样本,都可以用当前的观测值去填补当前的缺失值,这样每次填补可能花费的时间将对较长,但实际却更有效。

以上就是R语言学习笔记缺失数据的Bootstrap与Jackknife方法的详细内容,更多关于R语言学习笔记的资料请关注我们其它相关文章!

(0)

相关推荐

  • R语言学习Rcpp基础知识全面整理

    目录 1. 相关配置和说明 2. 常用数据类型 3. 常用数据类型的建立 4. 常用数据类型元素访问 5. 成员函数 6. 语法糖 6.1 算术和逻辑运算符 6.2. 常用函数 7. STL 7.1. 迭代器 7.2. 算法 7.3. 数据结构 7.3.1. Vectors 7.3.2. Sets 7.3.3. Maps 8. 与R环境的互动 9. 用Rcpp创建R包 10. 输入和输出示例 如何传递数组 通过.attr("dim")设置维数 函数返回一维STL vector 函数返回

  • R语言数据可视化学习之图形参数修改详解

    1.图形参数的修改par()函数 我们可以通过使用par()函数来修改图形的参数,其调用格式为par(optionname=name, optionname=name,-).当par()不加参数时,返回当前图形参数设置的列表:par(no.readonly=T)将生成一个可以修改当前参数设置的列表.注意以这种方式修改参数设置,除非参数再次被修改,否则一直执行此参数设置. 例如现在想画出mtcars数据集中mpg的折线图,并用虚线代替实线,并将两幅图排列在同一幅图里,代码及图形如下: > opar

  • R语言科学计算RcppArmadillo简明手册

    目录 1. 常用数据类型 2. 数学运算 3. 向量.矩阵和域的创建 基本创建 用函数创建 4. 初始化,元素访问,属性和成员函数 4.1. 元素初始化 Element initialization 4.2. 元素访问 Element access 4.3. 子矩阵访问 Submatrix view 矩阵X的连续子集访问 向量V的连续子集访问 向量或矩阵X的间断子集访问 立方体(三维矩阵)Q 的切片 slice 域F的子集访问 4.4. 属性 Attribute 4.5. 其他成员函数 Othe

  • R语言学习笔记之lm函数详解

    在使用lm函数做一元线性回归时,发现lm(y~x+1)和lm(y~x)的结果是一致的,一直没找到两者之间的区别,经过大神们的讨论和测试,才发现其中的差别,测试如下: ------------------------------------------------------------- ------------------------------------------------------------- 结果可以发现,两者的结果是一样的,并无区别,但是若改为lm(y~x-1)就能看出+1和

  • R语言学习笔记缺失数据的Bootstrap与Jackknife方法

    目录 一.题目 二.解答 a)Bootstrap与Jackknife进行估计 b)均值与变异系数(大样本)的标准差解析式推导与计算 c)缺失插补前的Bootstrap与Jackknife d)比较各种方式的90%置信区间情况(重复100次实验) 填补之前进行Bootstrap或Jackknife 填补之后进行Bootstrap或Jackknife 一.题目 下面再加入缺失的情况来继续深入探讨,同样还是如习题1.6的构造方式来加入缺失值,其中a=2, b = 0 我们将进行如下几种操作: 二.解答

  • MySQL学习笔记之数据定义表约束,分页方法总结

    本文实例讲述了MySQL学习笔记之数据定义表约束,分页方法.分享给大家供大家参考,具体如下: 1. primary key 主键 特点:主键是用于唯一标识一条记录的约束,一张表最多只能有一个主键,不能为空也不能重复 create table user1(id int primary key,name varchar(32)); mysql> insert into user1 values(1,'hb'); Query OK, 1 row affected (0.10 sec) mysql>

  • R语言刷题检验数据缺失类型过程详解

    目录 题目 解答 下面考虑三种情况: 1. a = 0, b = 0 2. a = 2, b = 0 3. a = 0, b = 2 题目 解答 由于题目要求需要重复三次类似的操作,故首先载入所需要的包,构造生成数据的函数以及绘图的函数: library(tidyr) # 绘图所需 library(ggplot2) # 绘图所需 # 生成数据 GenerateData <- function(a = 0, b = 0, seed = 2018) { set.seed(seed) z1 <- r

  • R语言学习ggplot2绘制统计图形包全面详解

    目录 一.序 二.ggplot2是什么? 三.ggplot2能画出什么样的图? 四.组装机器 五.设计图纸 六.机器的零件 1. 零件--散点图 1) 变换颜色 2) 拟合曲线 3) 变换大小 4) 修改透明度 5) 分层 6) 改中文 2. 零件--直方图与条形图 1) 直方图 2) 润色 3) 条形图 3. 零件--饼图 4. 零件--箱线图 5. 零件--小提琴图 6. 零件打磨 7. 超级变变变 8. 其他常用零件 七.实践出真知 八.学习资源 九.参考资料 一.序 作为一枚统计专业的学

  • R语言学习之线图的绘制详解

    目录 线图 单线图 多线图 横轴文本线图 线图 线图是反映趋势变化的一种方式,其输入数据一般也是一个矩阵. 单线图 假设有这么一个矩阵,第一列为转录起始位点及其上下游5 kb的区域,第二列为H3K27ac修饰在这些区域的丰度,想绘制一张线图展示. profile="Pos;H3K27ac -5000;8.7 -4000;8.4 -3000;8.3 -2000;7.2 -1000;3.6 0;3.6 1000;7.1 2000;8.2 3000;8.4 4000;8.5 5000;8.5"

  • Go语言学习笔记之文件读写操作详解

    目录 文件写 文件读 小结 文件操作比较多,分为几篇来写吧.首先是文件的读写,在平时的工程化操作中使用最多. 文件写 样例代码如下 package main import ( "bufio" "fmt" "io" "os" ) //写文件 func DoWriteFile() error { _filePath := "./test.txt" _file, _err := os.OpenFile(_file

  • R语言学习VennDiagram包绘制韦恩图示例

    目录 引言 一 需要安装和导入的包 二 使用函数及参数 三 知道各个数据集的个数以及重叠(交叉)的个数 2.1 两个已知数据集的韦恩图 2.2 三个已知数据集的韦恩图 四 根据数据集合绘制韦恩图 4.1 四个数据集合 4.2 五个数据集合 引言 本版块会持续分享一些常用的结果展示的图形. 在得到数据之后,我们经常会用到维恩图来展示各个数据集之间的重叠关系.本文简单的介绍R语言中的VennDiagram包绘制数据集的维恩图. 一 需要安装和导入的包 install.packages("VennDi

  • MySQL学习笔记之数据的增、删、改实现方法

    本文实例讲述了MySQL学习笔记之数据的增.删.改实现方法.分享给大家供大家参考,具体如下: 一.增加数据 插入代码格式: insert into 表明 [列名-] values (值-) create table test21(name varchar(32)); insert into test21 (name) values ('huangbiao'); 插入原则: 1.插入的数据应与字段的数据类型相同 2.数据的大小应该在列的规定范围内 3.在values中列出的数据位置必须与被加入的列

随机推荐