缺失值是我们进行批量数据处理中常常遇到的一个问题,比如研究中常常遇到指标缺失,需要对缺失进行统计,然后进一步判断,是丢弃这些变量呢(丢弃一般不太好),还是对数据进行替换,插补等操作后进行建模。下面讲一下R中的缺失值的识别与处理:

0、缺失值定义

缺失值从数据分布上可被分为三类 :完全随机缺失(MCAR), 随机缺失(MAR), 非随机缺失(NMAR)。

  • 完全随机缺失(MCAR):若某变量的缺失数据与其他任何观测或未观测变量都不相关
  • 随机缺失(MAR):若某变量上的缺失数据与其他观测变量相关,与它自己的未观测值不相关
  • 非随机缺失(NMAR):某一变量的缺失和该变量本身的数值相关;或者若缺失数据不属于MCAR或MAR,则数据为非随机缺失。如,仪器的最低检测线:某被检测物质的含量低于该检测线则会产生非随机缺失(left-censored missing);做梦时长越短的动物也更可能有做梦数据的缺失(可能由于难以测量时长较短的事件), 那么数据可认为是NMAR。

目前大部分填补缺失值的方法都是基于MCAR和MAR,对于这些数据,可以忽略缺失数据的生成机制,并且(在替换或删除缺失数据后)可以直接对感兴趣的关系进行建模。当数据是NMAR时,想对它进行恰当地分析比较困难,你既要对感兴趣的关系进行建模,还要对缺失值的生成机制进行建模。(目前分析NMAR数据的方法有模型选择法和模式混合法。由于NMAR数据的分析十分复杂,我们将忽略对它的讨论。)

1、识别缺失值

a <- c(1,2,3,4)
b <- c(6,7,8,NA)
m <- cbind(a,b)
m# m
#     a  b
#[1,] 1  6
#[2,] 2  7
#[3,] 3  8
#[4,] 4 NA

  • 1.1 对NA进行统计,可以用sum函数和is.na连用;或用colSums函数
> sum(is.na(m))
[1] 1
#或者对行和列分别进行统计,注意colSums和rowSums是中间的大写
> colSums(is.na(m))
a b
0 1
> rowSums(is.na(m))
[1] 0 0 0 1

  • 或者可以用summary函数
  • 可以用sapply函数,sapply(m, function(x) sum(is.na(x)))
  • 1.2 用Hmisc包中的describe()
> library(Hmisc)
> Hmisc::describe(m)
m 2  Variables      4  Observations
--------------------------------------------------------------------------------------------------
a n  missing distinct     Info     Mean      Gmd 4        0        4        1      2.5    1.667 Value         1    2    3    4
Frequency     1    1    1    1
Proportion 0.25 0.25 0.25 0.25
--------------------------------------------------------------------------------------------------
b n  missing distinct     Info     Mean      Gmd 3        1        3        1        7    1.333 Value          6     7     8
Frequency      1     1     1
Proportion 0.333 0.333 0.333
--------------------------------------------------------------------------------------------------

  • 1.3psych包中的describe()计算缺失值(效果较好)
psych::describe(m)vars n mean   sd median trimmed  mad min max range skew kurtosis   se
a    1 4  2.5 1.29    2.5     2.5 1.48   1   4     3    0    -2.08 0.65
b    2 3  7.0 1.00    7.0     7.0 1.48   6   8     2    0    -2.33 0.58

  • 1.4 mice包中的mice包中的md.pattern()函数。会出现一个二维的表格,以及对应的图(如果数据较多,作图可能会慢一些)
#从这开始以diabetes数据集为例,包含在VIM包中
library(VIM)
library(mice)
data('diabetes')
d <- diabetes

diabetes数据集
查看缺失值个数

md.pattern(d)

  • 1.5 library(VIM)的aggr函数画图
library(VIM)
aggr(d)
#代码aggr(sleep, prop = TRUE, numbers = TRUE)将生成相同的图形,但用比例代替了计数。选项numbers = FALSE(默认)删去数值型标签。

  • 或者也可以使用VIM包的matrixplot函数
> matrixplot(d)

#或者用VIM 包的marginplot ,注意,这个图只适用于对两个变量作图
marginplot(m)

  • 1.6 可以用Amelia包中的missmap函数(这个函数对大量的数据,效果会好一些,运行速度相对较快;格式必须是data.frame输入,matrix不行
library(Amelia)
m <- as.data.frame(d)
missmap(d, col = c("white", "lightblue"))

2、定位和去除缺失值

2.1 行删除

  • 最简单的方法就是is.na(),返回的是ture和false,然后就可以定位缺失值
r <- is.na(d)

is.na返回的结果
  • 根据某一列来选择
d1 <- d[!r$BloodPressure, ]
#选择BloodPressure不是NA的行

可以看到,这样用false的反面(true)选择了733行,含有NA的35行被丢弃
  • 同样可以使用na.omit函数(去除所有含缺失值的行)
可以看到na.omit去除了所有含缺失值的行
  • 或者用complete.case函数

2.2 80%规则。在代谢组学中,有一个80%规则,少于80%的variable应当去除。

 rowSums(is.na(d))/ncol(d) #计算缺失值的比例

r1 <- rowSums(is.na(d))/ncol(d) >= 0.2
#r1是缺失值大于0.2的行
d5 <- d[!r1, ]
#取子集

3、缺失值填补(包括单变量填补和多变量填补)

单变量填补(即单一变量,如0,均值,中位数,众数等等)

简单插补的一个优点是,解决“缺失值问题”时不会减少分析过程中可用的样本量。虽然简单插补用法很简单,但是对于非MCAR的数据会产生有偏的结果。若缺失数据的数目非常大,那么简单插补很可能会低估标准差、曲解变量间的相关性,并会生成不正确的统计检验的p值。与成对删除一样,我建议在解决缺失数据的问题时尽量避免使用该方法。
from 《R语言实战》

  • 3.1 使用固定值,如0,进行填补, 用R编写一个函数,然后用apply或者sapply进行遍历
fix(m)#修改m,修改后如下:
> ma  b
1 1 10
2 3  1
3 3  8
4 9 NA
#def function
fun1 <- function(x) {x[is.na(x)] <- 0x
}
> sapply(m, fun1)a  b
[1,] 1 10
[2,] 3  1
[3,] 3  8
[4,] 9  0

  • 或者直接用is.na进行0的赋值
m[is.na(m)] <- 0
#############
ma  b
1 1 10
2 3  1
3 3  8
4 9  0

  • 3.2 使用均值、中位数填补,同样:
#mean
fun2 <- function(x) {x[is.na(x)] <- mean(x, na.rm = TRUE)x
}
sapply(m, fun2)a         b
[1,] 1 10.000000
[2,] 3  1.000000
[3,] 3  8.000000
[4,] 9  6.333333
#median
fun3 <- function(x) {x[is.na(x)] <- median(x, na.rm = TRUE)x
}
sapply(m, fun3)a  b
[1,] 1 10
[2,] 3  1
[3,] 3  8
[4,] 9  8

多变量填补:如随机森林(RF),奇异值分解(SVD),k最近邻(kNN)和左删失数据的分位数回归插补(QRILC)等

  • 3.3 其它赋值方式,如随机森林(RF),奇异值分解(SVD),k最近邻(kNN)和左删失数据的分位数回归插补(QRILC)等,这些方法由于时间原因,留待以后进行实现。
  • 可参考:R语言之缺失值和异常值处理
  • 我觉得下面一张图能够很好的总结我上面讨论的,缺失值识别的一系列问题,以及相对应的解决方法:
from 《R语言实战》

Reference:

  1. 数据预处理中的缺失值问题
  2. Wei, R. , Wang, J. , Su, M. , Jia, E. , Chen, S. , & Chen, T. , et al. (2018). Missing value imputation approach for mass spectrometry-based metabolomics data.Scientific Reports,8(1), 663.
  3. Bijlsma, S. , Bobeldijk, I. , Verheij, E. R. , Ramaker, R. , Kochhar, S. , & Macdonald, I. A. , et al. (2006). Large-scale human metabolomics studies:? a strategy for data (pre-) processing and validation.Analytical Chemistry,78(2), 567-574.
  4. RobertI.Kabacoff, 卡巴科弗, 陈钢, 肖楠, & 高涛. (2013). R语言实战.

取datatable某一列的值_R-缺失值识别与处理相关推荐

  1. datatable中某一列最小值_获取DataTable 某一列所有值

    //获取某一列值 string orderids = (from d in dt.AsEnumerable() select d.Field("OrderID")).ToList( ...

  2. 创建DataTable并把列默认值

    DataTable dt=new DataTable();dt.Columns.Add("id");dt.Columns["id"].DefaultValue= ...

  3. matlab 求取矩阵中值,matlab中取矩阵中指定列的值组成新矩阵

    matlab 矩阵中怎么加入冒号,比如我想矩阵A的第一列都为"1:" A(:,1)='1:';再问:不行的再答:用结构矩阵或者单元矩阵试试吧. 诚教:matlab中取矩阵的其中几行 ...

  4. DataTable某一列的值转化成集合

    DataTable dt = new DataTable(); dt.Columns.Add("name",typeOf(string)); dt.Rows.Add(dt.NewR ...

  5. python 筛选重复数据和不重复数据_[Python] Pandas 对数据进行查找、替换、筛选、排序、重复值和缺失值处理...

    1. 数据文件 2. 读数据 import pandas as pd data = pd.read_csv('D:\git\python\code\第5章\产品统计表.csv') print(data ...

  6. 取二维数组某一列的值

    arr = [[1,2],[3,4],[5,6]] 取第一列的值 v = [x[0] for x in arr]

  7. python读取前两列数据对比_使用Python的Dataframe取两列时间值相差一年的所有行方法...

    在使用Python处理数据时,经常需要对数据筛选. 这是在对时间筛选时,判断两列时间是否相差一年,如果是,则返回符合条件的所有列. data原始数据: data[map(lambda x:dateti ...

  8. python提取两列数据对比_使用Python的Dataframe取两列时间值相差一年的所有行方法...

    在使用Python处理数据时,经常需要对数据筛选. 这是在对时间筛选时,判断两列时间是否相差一年,如果是,则返回符合条件的所有列. data原始数据: data[map(lambda x:dateti ...

  9. python 根据判断产生新列_pandas DataFrame 根据多列的值做判断,生成新的列值实例...

    环境:Python3.6.4 + pandas 0.22 主要是DataFrame.apply函数的应用,如果设置axis参数为1则每次函数每次会取出DataFrame的一行来做处理,如果axis为1 ...

  10. MySQL内核月报 2015.01-MySQL · 捉虫动态· InnoDB自增列重复值问题

    问题重现 先从问题入手,重现下这个bug 这里我们关闭mysql,再启动mysql,然后再插入一条数据 我们看到插入了(2,2),而如果我没有重启,插入同样数据我们得到的应该是(4,2). 上面的测试 ...

最新文章

  1. C#实现一个用于开机启动其他程序的Windows服务
  2. 利用CSDN将图片自动存入AI Studio :pic2bml
  3. wampserver运行后报错问题
  4. 解决问题 com.alibaba.fastjson.JSONObject cannot be cast to xxx
  5. eclipse启动提示java,Eclipse启动时报错-JSP教程,Java技巧及代码
  6. 【CVPR2019】完整论文列表二
  7. 【汇编语言与计算机系统结构笔记19】虚存概念初步,MIPS内存管理
  8. r语言 怎么把字调大_R语言中的字体调整
  9. sybase默认数据库
  10. 直播组装服务器,快速搭建直播服务器
  11. /usr/include/gnu/stubs.h:7:27: 致命错误:gnu/stubs-32.h:没有那个文件或目录
  12. 计算机之父童年的故事ppt,24计算机之父童年的故事
  13. 洛谷P4158 [SCOI2009]粉刷匠 题解
  14. 【Java 8 新特性】Java CompletableFuture applyToEither()
  15. 一年级上册计算机教学计划,一年级信息技术上册教学计划
  16. 拉卡拉支付开启生态化移动支付新趋势
  17. C:\Users\123\AppData\Roaming\Python\Python38\Scripts which is not on PATH
  18. 笔记:蛋白质结构预测在线工具
  19. 一帘心事碎碎念,一眸雪舞剪剪风
  20. 【互联网广告】移动互联网广告

热门文章

  1. 如何让普通人了解网络隐私的重要性
  2. 12.软件架构设计:大型网站技术架构与业务架构融合之道 --- CAP理论
  3. 8.企业安全建设指南(金融行业安全架构与技术实践) --- 安全考核
  4. 58. 网络驱动器设备: iSCSI 服务器
  5. 页面定时跳转的js和php的代码实现和页面定时刷新
  6. 应用安全 - 工具使用 - Nmap
  7. 知物由学 | 如何应对日益强大的零日攻击
  8. 2013.10.28—2013.11.1周总结
  9. vs2010下libevent的使用
  10. inner join、 left join 、right join、full outer join之间的区别