R 数据清洗杂记(1)---列/行0值替换为非零最小正值/2和低于检测限的值替换为检测限/根号2

这篇博客介绍了如何在分子检测数据中处理0值和低于检测限(LOD)的值。使用R语言的dplyr包和apply函数,将0替换为最小非零值、其一半或LOD/√2。同时展示了按列和按行替换的方法,并处理了数据结构的转换。此外,还提到了如何用平均值替换数据框中每一列的NA值。
摘要由CSDN通过智能技术生成

背景说明

在一些分子/物质的含量检测时候,往往一些样本的含量非常低没有检测到,导致机器给的数值是0,或者是小于检测限(LOD)的值,我们这个时候要建模的话就需要将这些0值进行变换,一些文献推荐将其替换为非0最小值的1/2,也有一些推荐将低于LOD的值替换为LOD/ 2 \sqrt 2 2 ,其实都是可以的。

0.示例数据

##构建实例数据:5行4列
df <- data.frame(a = 1:5, b = c(3, 0, 4, 2, 3), c = c(0, 2, 3, 0, 4), d = c(4:0))
df
#  a b c d
#1 1 3 0 4
#2 2 0 2 3
#3 3 4 3 2
#4 4 2 0 1
#5 5 3 4 0

以下操作都基于此示例数据框

1.按替换

这里是数据框中的每一列是检测的各种因子或指标,每一行是每个样本
用mutate_all() 函数,这是个函数是基于dplyr包的,属于mutate函数的变种,详细参数介绍见帮助文档。

1.1. 将0替换为最小正值

library(dplyr)
##0至替换为非零最小正值
df1 <- 
  df %>% 
  mutate_all(., ~ replace(., . == 0, min(as.numeric(.[.>0]))))
df1
#  a b c d
#1 1 3 2 4
#2 2 2 2 3
#3 3 4 3 2
#4 4 2 2 1
#5 5 3 4 1

1.2. 将0替换为最小正值的一半

##0替换为非零最小正值的二分之一
df2 <- 
  df %>% 
  mutate_all(., ~ replace(., . == 0, min(as.numeric(.[.>0]))/2))
df2
#  a b c   d
#1 1 3 1 4.0
#2 2 1 2 3.0
#3 3 4 3 2.0
#4 4 2 1 1.0
#5 5 3 4 0.5

1.3. 将低于检测限(LOD)的值替换为LOD/ 2 \sqrt 2 2

与上面不同的是这里用到了apply()函数,apply函数非常强大
我们把第一行作为每个指标的LOD值

df99 <- apply(df, 2, function(x){
  x[x<x[1]]=x[1]/(2^0.5)
  return(x)
})
df99
#     a       b c        d
#[1,] 1 3.00000 0 4.000000
#[2,] 2 2.12132 2 2.828427
#[3,] 3 4.00000 3 2.828427
#[4,] 4 2.12132 0 2.828427
#[5,] 5 3.00000 4 2.828427

df  #与df对比
#  a b c d
#1 1 3 0 4
#2 2 0 2 3
#3 3 4 3 2
#4 4 2 0 1
#5 5 3 4 0

这个时候还不能得意忘形觉得万事大吉可以开始后面分析。仔细的人会发现df99的结果与df不同,这里说的不是数值不同,而是两个数据结构不同。那么我们接下来看看df99是什么的数据结构:

class(df99)
#[1] "matrix" "array" 
df99_0 <- data.frame(df99)
class(df99_0)
df99_0
#[1] "data.frame"
#  a       b c        d
#1 1 3.00000 0 4.000000
#2 2 2.12132 2 2.828427
#3 3 4.00000 3 2.828427
#4 4 2.12132 0 2.828427
#5 5 3.00000 4 2.828427

通过class()我们发现df99其实是矩阵/数组,而不是我们需要数据框结构,因此我们需要通过上面的方法将其结构转换。

2. 按替换

相反,这里是数据框中的每一行是检测的各种因子或指标,每一列是每个样本
这里会用到apply()这个函数

2.1. 将0替换为最小正值

df3 <- df
df3[] <- t(apply(df, 1, function(x) 
  replace(x, x == 0, min(x[x > 0], na.rm = TRUE))))
df3
#  a b c d
#1 1 3 1 4
#2 2 2 2 3
#3 3 4 3 2
#4 4 2 1 1
#5 5 3 4 3

2.2. 将0替换为最小正值的一半

df4 <- df
df4[] <- t(apply(df, 1, function(x) 
  replace(x, x == 0, min(x[x > 0], na.rm = TRUE)/2)))
df4
#  a b   c   d
#1 1 3 0.5 4.0
#2 2 1 2.0 3.0
#3 3 4 3.0 2.0
#4 4 2 0.5 1.0
#5 5 3 4.0 1.5

2.3. 将低于检测限(LOD)的值替换为LOD/ 2 \sqrt 2 2

这里横向的表(即列是样本,行是变量),需要用t()进行转置,否则得到的是纵向数据

df100 <- t(apply(df, 1, function(x){
  x[x<x[1]]=x[1]/(2^0.5)
  return(x)
}))
df100
#     a        b         c        d
#[1,] 1 3.000000 0.7071068 4.000000
#[2,] 2 1.414214 2.0000000 3.000000
#[3,] 3 4.000000 3.0000000 2.121320
#[4,] 4 2.828427 2.8284271 2.828427
#[5,] 5 3.535534 3.5355339 3.535534

##与前面一样的要进行数据框转换
df100_0 <- data.frame(df100)
df100_0
#  a        b         c        d
#1 1 3.000000 0.7071068 4.000000
#2 2 1.414214 2.0000000 3.000000
#3 3 4.000000 3.0000000 2.121320
#4 4 2.828427 2.8284271 2.828427
#5 5 3.535534 3.5355339 3.535534

3.额外的内容

假如我们由一个数据框包含一下NA,要将每列的NA值替换为平均值,我们该怎么做:

##新建一个矩阵1:40(8*5),包含8个随机的NA(数据框也可以,多一个data.frame步骤)
raw <- 1:40  
raw[sample(raw,8)] <- NA
dim(raw) <- c(8,5)
raw
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    9   17   25   NA
#[2,]    2   10   18   26   34
#[3,]   NA   11   19   NA   35
#[4,]    4   12   20   28   36
#[5,]   NA   13   NA   29   37
#[6,]    6   14   NA   30   38
#[7,]    7   15   23   31   39
#[8,]    8   16   24   32   40
# 按照列,替换每一列的NA值为该列的平均值
new <- apply(raw,2,function(x){
  x[is.na(x)]=mean(x,na.rm = T)
  return(x)
})
new
#         [,1] [,2]     [,3]     [,4] [,5]
#[1,] 1.000000    9 17.00000 25.00000   37
#[2,] 2.000000   10 18.00000 26.00000   34
#[3,] 4.666667   11 19.00000 28.71429   35
#[4,] 4.000000   12 20.00000 28.00000   36
#[5,] 4.666667   13 20.16667 29.00000   37
#[6,] 6.000000   14 20.16667 30.00000   38
#[7,] 7.000000   15 23.00000 31.00000   39
#[8,] 8.000000   16 24.00000 32.00000   40

##注意:这里的产生的new仍旧是矩阵

其他的还有中位数替换都是类似的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值