R语言 替换数据框中的所有特定值

z0qdvdin  于 2023-01-18  发布在  其他
关注(0)|答案(8)|浏览(235)

有了一个数据框,我该如何替换所有行和列上的所有特定值呢?例如,我想用NA替换所有空记录(不输入位置):

df <- data.frame(list(A=c("", "xyz", "jkl"), B=c(12, "", 100)))

    A   B
1      12
2  xyz    
3  jkl 100

预期结果:

A   B
1  NA   12
2  xyz  NA  
3  jkl  100
yshpjwxd

yshpjwxd1#

就像这样:

> df[df==""]<-NA
> df
     A    B
1 <NA>   12
2  xyz <NA>
3  jkl  100
63lcw9qa

63lcw9qa2#

由于PikkuKatja和glallen要求一个更一般的解决方案,我还不能发表评论,我将写一个答案。你可以合并语句如下:

> df[df=="" | df==12] <- NA
> df
     A    B
1  <NA> <NA>
2  xyz  <NA>
3  jkl  100

对于因子,zxzak的代码已经生成了因子:

> df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)))
> str(df)
'data.frame':   3 obs. of  2 variables:
 $ A: Factor w/ 3 levels "","jkl","xyz": 1 3 2
 $ B: Factor w/ 3 levels "","100","12": 3 1 2

如果遇到麻烦,我建议暂时放弃因子。

df[] <- lapply(df, as.character)
cygmwpex

cygmwpex3#

以下是一些dplyr选项:

library(dplyr)

# all columns:
df %>% 
  mutate_all(~na_if(., ''))

# specific column types:
df %>% 
  mutate_if(is.factor, ~na_if(., ''))

# specific columns:  
df %>% 
  mutate_at(vars(A, B), ~na_if(., ''))

# or:
df %>% 
  mutate(A = replace(A, A == '', NA))

# replace can be used if you want something other than NA:
df %>% 
  mutate(A = as.character(A)) %>% 
  mutate(A = replace(A, A == '', 'used to be empty'))
fcy6dtqo

fcy6dtqo4#

我们可以用data.table来快速得到它,首先创建没有因子的df,

df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)), stringsAsFactors=F)

现在您可以使用

setDT(df)
for (jj in 1:ncol(df)) set(df, i = which(df[[jj]]==""), j = jj, v = NA)

你可以把它转换回 Dataframe

setDF(df)

如果你只想使用数据.frame并保留因子,那就比较困难了,你需要使用

levels(df$value)[levels(df$value)==""] <- NA

其中value是每个列的名称。您需要将其插入到循环中。

wfauudbj

wfauudbj5#

如果要替换数据框中的多个值,则循环遍历所有列可能会有所帮助。
假设您要替换""100

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
hyrbngr7

hyrbngr76#

对于要替换的多个值和因子,似乎缺少一个解决方案,因此我将添加一个。
考虑具有各种类的 Dataframe dat

dat
#    character integer       Date factor               POSIX
# 1                  4 2022-07-10      B 2022-07-10 20:08:10
# 2                  1 2022-07-11    FOO 2022-07-10 21:08:10
# 3                 -2 2022-07-12        2022-07-10 22:08:10
# 4                  2 2022-07-13      B 2022-07-10 23:08:10
# 5          a       3 2022-07-14        2022-07-11 00:08:10
# 6          c       1 2022-07-15        2022-07-11 01:08:10
# 7          a      -1 2022-07-16    FOO 2022-07-11 02:08:10
# 8          a      -1 2022-07-17      A 2022-07-11 03:08:10
# 9                  4 2022-07-18    FOO 2022-07-11 04:08:10
# 10         c       0 2022-07-19    FOO 2022-07-11 05:08:10
# 11         b      -2 2022-07-20      B 2022-07-11 06:08:10
# 12         c      -2 2022-07-21      A 2022-07-11 07:08:10

我们可以把所有我们想要转换成NA的东西放在一个列表to_na上,

To_NA <- list('', -1, -2, 'c', 'FOO', as.Date('2022-07-17'), as.POSIXct('2022-07-11 00:08:10'))

并在基于replace的小函数make_na中使用它。if相应的变量is.factor我们可能想要对刚被删除的值进行droplevels

make_na <- \(x, z) {x <- replace(x, x %in% z, NA); if (is.factor(x)) droplevels(x) else x}

我们可以把它应用到一个向量上,

make_na(dat$character, To_NA)
# [1] NA  NA  NA  NA  "a" NA  "a" "a" NA  NA  "b" NA

或者使用lapply在列上循环。

dat[] <- lapply(dat, make_na, To_NA)

给予

dat
#    character integer       Date factor               POSIX
# 1       <NA>       4 2022-07-10      B 2022-07-10 20:08:10
# 2       <NA>       1 2022-07-11   <NA> 2022-07-10 21:08:10
# 3       <NA>      NA 2022-07-12   <NA> 2022-07-10 22:08:10
# 4       <NA>       2 2022-07-13      B 2022-07-10 23:08:10
# 5          a       3 2022-07-14   <NA>                <NA>
# 6       <NA>       1 2022-07-15   <NA> 2022-07-11 01:08:10
# 7          a      NA 2022-07-16   <NA> 2022-07-11 02:08:10
# 8          a      NA       <NA>      A 2022-07-11 03:08:10
# 9       <NA>       4 2022-07-18   <NA> 2022-07-11 04:08:10
# 10      <NA>       0 2022-07-19   <NA> 2022-07-11 05:08:10
# 11         b      NA 2022-07-20      B 2022-07-11 06:08:10
# 12      <NA>      NA 2022-07-21      A 2022-07-11 07:08:10

其中:

str(dat)
# 'data.frame': 12 obs. of  5 variables:
#  $ character: chr  NA NA NA NA ...
#  $ integer  : int  4 1 NA 2 3 1 NA NA 4 0 ...
#  $ Date     : Date, format: "2022-07-10" "2022-07-11" "2022-07-12" ...
#  $ factor   : Factor w/ 2 levels "A","B": 2 NA NA 2 NA NA NA 1 NA NA ...
#  $ POSIX    : POSIXct, format: "2022-07-10 20:08:10" "2022-07-10 21:08:10" "2022-07-10 22:08:10" ...
  • 数据:*
dat <- structure(list(character = c("", "", "", "", "a", "c", "a", "a", 
"", "c", "b", "c"), integer = c(4L, 1L, -2L, 2L, 3L, 1L, -1L, 
-1L, 4L, 0L, -2L, -2L), Date = structure(c(19183, 19184, 19185, 
19186, 19187, 19188, 19189, 19190, 19191, 19192, 19193, 19194
), class = "Date"), factor = structure(c(3L, 4L, 1L, 3L, 1L, 
1L, 4L, 2L, 4L, 4L, 3L, 2L), levels = c("", "A", "B", "FOO"), class = "factor"), 
    POSIX = structure(c(1657476490L, 1657480090L, 1657483690L, 
    1657487290L, 1657490890L, 1657494490L, 1657498090L, 1657501690L, 
    1657505290L, 1657508890L, 1657512490L, 1657516090L), class = c("POSIXct", 
    "POSIXt"), tzone = "")), class = "data.frame", row.names = c(NA, 
-12L))
wj8zmpe1

wj8zmpe17#

另一种选择是使用naniar包中的replace_with_na_all(),它允许您替换整个 Dataframe 中满足条件的所有值。

library(naniar)
library(dplyr)
    
df %>% 
  replace_with_na_all(condition = ~.x == "")
    • 产出**
A     B    
  <chr> <chr>
1 NA    12   
2 xyz   NA   
3 jkl   100

这种方法的好处是,如果你有一些单元格也包含空格,那么我们可以在conditions参数中同时提供这两个参数,尽管最好先删除空格,然后再使用上面的函数(例如,将mutate(across(everything(), ~ trimws(.x)))添加到管道中)。

df <- data.frame(list(A=c("", "xyz", "  "), B=c(12, "   ", 100)))

df %>%
  replace_with_na_all(condition = ~.x %in% c("", "  ", "   "))

#  A     B    
#  <chr> <chr>
#1 NA    12   
#2 xyz   NA   
#3 NA    100
blmhpbnm

blmhpbnm8#

另一个选项是使用sapply。下面是一个可重现的示例:

df <- data.frame(list(A=c("", "xyz", "jkl"), B=c(12, "", 100)))
df[sapply(df, \(x) x == "")] <- NA
df
#>      A    B
#> 1 <NA>   12
#> 2  xyz <NA>
#> 3  jkl  100

创建于2023年1月15日,使用reprex v2.0.2

    • 请注意**:对于R 4.1.0和更高版本,您可以使用\(x)而不是function(x)

相关问题