在数据框中用NA替换字符值

92

我有一个包含字符值(比如说 "foo")的数据框,在随机位置出现,我想用NA替换掉这些值。

在整个数据框里,最好的方法是什么?


2
不要忘记重新定义你的列为.asnumeric(),将一些字符从“foo”更改为NA并不能强制将整个集合转换为数字。你必须强制它。(如果这是你正在做的事情) - Brandon Bertelsen
7个回答

129

这个:

df[df == "foo"] <- NA

21
请注意,如果您试图将NA替换为"foo",那么反向操作(df[df==NA] = "foo")将不起作用;您需要使用df[is.na(df)] <- "foo" - Andy Barbour
如果您的数据框中有日期时间列,您可能会收到类似以下错误的信息:“Error in as.POSIXlt.character(x, tz, ...) : character string is not in a standard unambiguous format”。 - Piethon

77

防止这种情况的一种方法是在读取数据时首先将该字符转换为NA。

df <- read.csv("file.csv", na.strings = c("foo", "bar"))

28

使用dplyr :: na_if,您可以将特定值替换为NA。在这种情况下,那将是"foo"

library(dplyr)
set.seed(1234)

df <- data.frame(
  id = 1:6,
  x = sample(c("a", "b", "foo"), 6, replace = T),
  y = sample(c("c", "d", "foo"), 6, replace = T),
  z = sample(c("e", "f", "foo"), 6, replace = T),
  stringsAsFactors = F
)
df
#>   id   x   y   z
#> 1  1   a   c   e
#> 2  2   b   c foo
#> 3  3   b   d   e
#> 4  4   b   d foo
#> 5  5 foo foo   e
#> 6  6   b   d   e

na_if(df$x, "foo")
#> [1] "a" "b" "b" "b" NA  "b"

如果您需要为多列执行此操作,则可以使用mutate中的across"foo"传递(更新为dplyr v1.0.0+)。
df %>%
  mutate(across(c(x, y, z), na_if, "foo"))
#>   id    x    y    z
#> 1  1    a    c    e
#> 2  2    b    c <NA>
#> 3  3    b    d    e
#> 4  4    b    d <NA>
#> 5  5 <NA> <NA>    e
#> 6  6    b    d    e

5
另一个选项是is.na<-:
is.na(df) <- df == "foo"

请注意,它的使用可能会有点违反直觉,但实际上它会在右侧索引处向df分配NA值。

2
或者使用'is.na<-'(df, df=="foo") - jogo

4

您可以使用dplyr :: mutate_all()replace来完成此操作:

library(dplyr)
df <- data_frame(a = c('foo', 2, 3), b = c(1, 'foo', 3), c = c(1,2,'foobar'),  d = c(1, 2, 3))

> df
# A tibble: 3 x 4
     a     b      c     d
  <chr> <chr>  <chr> <dbl>
1   foo     1      1     1
2     2   foo      2     2
3     3     3 foobar     3


df <- mutate_all(df, funs(replace(., .=='foo', NA)))

> df
# A tibble: 3 x 4
      a     b      c     d
  <chr> <chr>  <chr> <dbl>
1  <NA>     1      1     1
2     2  <NA>      2     2
3     3     3 foobar     3

使用 dplyr 的另一个选项是:

df <- na_if(df, 'foo') 

3
假设您不知道列名或者需要选择大量的列,is.character() 可能会有用。
df <- data.frame(
  id = 1:6,
  x = sample(c("a", "b", "foo"), 6, replace = T),
  y = sample(c("c", "d", "foo"), 6, replace = T),
  z = sample(c("e", "f", "foo"), 6, replace = T),
  stringsAsFactors = F
)
df
#   id   x   y   z
# 1  1   b   d   e
# 2  2   a foo foo
# 3  3   a   d foo
# 4  4   b foo foo
# 5  5 foo foo   e
# 6  6 foo foo   f

df %>% 
  mutate_if(is.character, list(~na_if(., "foo")))
#   id    x    y    z
# 1  1    b    d    e
# 2  2    a <NA> <NA>
# 3  3    a    d <NA>
# 4  4    b <NA> <NA>
# 5  5 <NA> <NA>    e
# 6  6 <NA> <NA>    f

0

解决问题的另一种替代方法如下:

for (i in 1:ncol(DF)){
  DF[which(DF[,i]==""),columnIndex]<-"ALL"
  FinalData[which(is.na(FinalData[,columnIndex])),columnIndex]<-"ALL"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接