我有一个包含一些数字列的数据框。某些行具有值为0的值,在统计分析中应视为null。在R中,最快的方法是将所有0值替换为NULL?
替换所有的零为NA:
df[df == 0] <- NA
解释
1. 你不应该想要用 NULL
替换零值。正如在 ?'NULL'
中所述,
NULL 在 R 中代表 null 对象
它是唯一的,我想可以被看作是最没有信息和空的对象。1 那么就不足为奇了。
data.frame(x = c(1, NULL, 2))
# x
# 1 1
# 2 2
换句话说,R并不为这个空对象保留任何空间。2 同时,查看'NA'
的文档,我们可以看到:
NA
是长度为1的逻辑常量,它包含一个缺失值指示符。NA
可以强制转换为除了原始类型之外的任何其他向量类型。
重要的是,NA
的长度为1,因此R为其保留了一些空间。例如:
data.frame(x = c(1, NA, 2))
# x
# 1 1
# 2 NA
# 3 2
此外,数据框架结构要求所有列具有相同数量的元素,以便没有“空洞”(即 NULL
值)。现在,您可以将数据框架中的零替换为 NULL
,意思是完全删除至少包含一个零的所有行。当使用例如 var
, cov
或 cor
时,实际上等效于首先用 NA
替换零,并将 use
的值设置为“complete.obs”
。然而,通常情况下,这是不令人满意的,因为会导致额外的信息丢失。 在解决方案中,我使用了 df == 0
向量化,而不是运行某种循环。 df == 0
返回(请尝试)与 df
大小相同的矩阵,具有条目 TRUE
和 FALSE
。此外,我们也被允许将此矩阵传递给子集 [..]
(请参见?'['
)。最后,虽然 df [df == 0]
的结果完全直观,但 df [df == 0] <- NA
可能看起来很奇怪却能产生所需的效果。赋值运算符 <-
确实并不总是那么聪明,并且不能以这种方式与某些其他对象一起使用,但在数据框架中可以;请参见?'<-'
。假设您的数据框包含不同的数据类型,且并非所有列都需要修改。
要仅修改第12到18列(共21列),只需执行以下操作
df[, 12:18][df[, 12:18] == 0] <- NA
[]
非常棒! 显而易见,但仍然隐藏得很好:) - bathyscapherdplyr::na_if()
是一个选项:
library(dplyr)
df <- data_frame(col1 = c(1, 2, 3, 0),
col2 = c(0, 2, 3, 4),
col3 = c(1, 0, 3, 0),
col4 = c('a', 'b', 'c', 'd'))
na_if(df, 0)
# A tibble: 4 x 4
col1 col2 col3 col4
<dbl> <dbl> <dbl> <chr>
1 1 NA 1 a
2 2 2 NA b
3 3 3 3 c
4 NA 4 NA d
na_if
函数不接受 data.frame 或 tibble。 - undefined不使用[<-
函数的替代方法:
一个数据框样本dat
(从@Chase的答案中无耻地复制):
dat
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
使用is.na<-
函数可以将0替换为NA
:
is.na(dat) <- !dat
dat
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
#replace zeros with NA
dat[dat==0] <- NA
#-----
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
因为有人要求使用Data.Table版本,且给定的data.frame解决方案在data.table中无法工作,因此我提供以下解决方案。
基本上,使用:=
运算符 --> DT[x == 0, x := NA]
library("data.table")
status = as.data.table(occupationalStatus)
head(status, 10)
origin destination N
1: 1 1 50
2: 2 1 16
3: 3 1 12
4: 4 1 11
5: 5 1 2
6: 6 1 12
7: 7 1 0
8: 8 1 0
9: 1 2 19
10: 2 2 40
status[N == 0, N := NA]
head(status, 10)
origin destination N
1: 1 1 50
2: 2 1 16
3: 3 1 12
4: 4 1 11
5: 5 1 2
6: 6 1 12
7: 7 1 NA
8: 8 1 NA
9: 1 2 19
10: 2 2 40
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)
。在这里查看使用data.table查找和替换值的更详细讨论。 - JWilliman如果有人通过谷歌搜索到此处,寻找相反的问题(即如何将数据框中所有的NA替换为0),答案是:
df[is.na(df)] <- 0
或者
使用 dplyr / tidyverse 技术
library(dplyr)
mtcars %>% replace(is.na(.), 0)
以下是我的贡献,为那些在处理包含多种列类型且有多个值表示缺失数据的数据集时感到困难的人提供帮助。
dat <- data_frame(numA = c(1, 0, 3, 4),
numB = c(NA, 2, 3, 4),
strC = c("0", "1.2", "NA", "2.4"),
strD = c("Yes", "Yes", "missing", "No"))
NA
,字符串/字符类型的'NA'和'missing'值也替换为NA
。请注意,strC
列中的'NA'是字符类型的值,而不是所需的NA
值。dat
# A tibble: 4 x 4
numA numB strC strD
<dbl> <dbl> <chr> <chr>
1 1 NA 0 Yes
2 0 2 1.2 Yes
3 3 3 'NA' missing
4 4 4 2.4 No
NA
。as.numeric(dat$strC)
[1] 0.0 1.2 NA 2.4
dat[dat == "NA" | dat =="missing"] <- NA
然而,对于数字和字符0都会被改变为NA
,因此不要对0使用。这是因为在R中 "0" == 0
返回的结果为TRUE
.
library(dplyr)
dat %>%
lapply(na_if, y = "missing") %>%
lapply(na_if, y = "NA") %>%
lapply(na_if, y = 0) %>% # DONT DO THIS! It converts string 0s to NA as well!
data.frame()
在这里,我们对数据的每一列应用 na_if
函数。由于 na_if
不接受多个值转换为 NA
,因此我们需要为每个要转换为 NA
的值编写多行代码。然而,只需简单使用该函数将 0
转换为 NA
就可以同时转换数字和字符中的 0
。我们需要做些别的事情!
这是我最喜欢的解决方案。在这里,我们检查列类型并根据需要应用 na_if
函数。字符型 0
不变,而所有需要转换的值都会被转换为 NA
。
dat %>%
mutate(across(where(is.numeric), ~na_if(., 0))) %>%
mutate(across(where(is.character), ~na_if(., "NA"))) %>%
mutate(across(where(is.character), ~na_if(., "missing")))
# A tibble: 4 x 4
numA numB strC strD
<dbl> <dbl> <chr> <chr>
1 1 NA 0 Yes
2 NA 2 1.2 Yes
3 3 3 NA NA
4 4 4 2.4 No
nariar
包了nariar
是一个最近推出的包,引入了多种replace_with_
函数。
library(naniar)
将所有的'NA'和'missing'值替换为NA
:
dat %>%
replace_with_na_all(~.x %in% c("NA", "missing"))
但是,如果您将此与0
一起使用,则它仍会错误地将字符0转换为NA
:
dat %>%
replace_with_na_all(~.x %in% c(0, "NA", "missing"))
# A tibble: 4 x 4
numA numB strC strD
<dbl> <dbl> <chr> <chr>
1 1 NA NA Yes
2 NA 2 1.2 Yes
3 3 3 NA NA
4 4 4 2.4 No
#strC's first element should not be NA here!
dat %>%
replace_with_na_if(is.character, ~.x %in% c("NA", "missing")) %>%
replace_with_na_if(is.numeric, ~.x %in% c(0))
# A tibble: 4 x 4
numA numB strC strD
<dbl> <dbl> <chr> <chr>
1 1 NA 0 Yes
2 NA 2 1.2 Yes
3 3 3 NA NA
4 4 4 2.4 No
您只能在数值字段中(即排除分类型字段等)将0
替换为NA
,但它是基于列的方式工作:
col[col == 0 & is.numeric(col)] <- NA
利用一个函数,你可以将其应用到整个数据框中:
changetoNA <- function(colnum,df) {
col <- df[,colnum]
if (is.numeric(col)) { #edit: verifying column is numeric
col[col == -1 & is.numeric(col)] <- NA
}
return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))
虽然你可以用数据框中的列数或1:ncol(df)
替换1:5
。
1:ncol(df)
替换1:5
。我不想让方程过于复杂或难以阅读。 - Alium Brittmutate_all
将所有的0替换为NA
,代码如下:replace
library(dplyr)
df <- data.frame(v1 = c(1,0,4,2),
v2 = c(3,1,0,0))
df
#> v1 v2
#> 1 1 3
#> 2 0 1
#> 3 4 0
#> 4 2 0
mutate_all(df, ~replace(., .==0, NA))
#> v1 v2
#> 1 1 3
#> 2 NA 1
#> 3 4 NA
#> 4 2 NA
由reprex package (v2.0.1)于2022年7月10日创建
~na.if(.,0)
- undefined