用相同类型的 NA 填充列的函数

A function to fill in a column with NA of the same type

我有一个包含许多不同类型列的数据框。我想用相应 class.

的 NA 替换每一列

例如:

df = data_frame(x = c(1,2,3), y = c("a", "b", "c"))

df[, 1:2] <- NA

生成一个包含两个逻辑列的数据框,而不是数字和字符。 我知道我可以告诉 R:

df[,1] = as.numeric(NA)
df[,2] = as.character(NA)

但是我如何在一个循环中针对所有可能类型的 NA 的所有列一起执行此操作?

你可以使用这个 "trick" :

df[1:nrow(df),1] <- NA
df[1:nrow(df),2] <- NA

[1:nrow(df),] 基本上告诉 R 替换 列中的所有值 NA 并且以这种方式强制逻辑 NA在替换其他值之前更改为列的原始类型。

此外,如果您有很多列要替换并且 data_frame 有很多行,我建议存储行索引并重新使用它们:

rowIdxs <- 1:nrow(df)
df[rowIdxs ,1] <- NA
df[rowIdxs ,2] <- NA
df[rowIdxs ,3] <- NA
...

正如 @RonakShah 巧妙地建议的那样,您还可以使用:

df[TRUE, 1] <- NA
df[TRUE, 2] <- NA
...

正如 @Cath 所指出的,当您 select 多列时,这两种方法仍然有效,例如:

df[TRUE, 1:3] <- NA
# or
df[1:nrow(df), 1:3] <- NA

使用 dplyr 中的 bind_cols() 您还可以:

df <- data_frame(x = c(1,2,3), y = c("a", "b", "c"))
classes <- sapply(df, class)
df[,1:2] <- NA

bind_cols(lapply(colnames(x), function(x){eval(parse(text=paste0("as.", classes[names(classes[x])], "(", df[,x],")")))}))

     V1 V2   
  <dbl> <chr>
1    NA NA   
2    NA NA   
3    NA NA 

请注意,这将更改列名。

适用于所有列的另一种解决方案可以是指定非NA并替换为NA,即

df[!is.na(df)] <- NA

这给出了,

# A tibble: 3 x 2
      x    y    
  <dbl> <chr>
1    NA <NA> 
2    NA <NA> 
3    NA <NA> 

使用 dplyr::na_if:

library(dplyr)

df %>% 
  mutate(x = na_if(x, x),
         y = na_if(y, y))

# # A tibble: 3 x 2
#       x y    
#   <dbl> <chr>
# 1    NA NA   
# 2    NA NA   
# 3    NA NA   

如果我们只想将列的子集突变为 NA,则:

# dataframe with extra column that stay unchanged
df = data_frame(x = c(1,2,3), y = c("a", "b", "c"), z = c(4:6))

df %>% 
  mutate_at(vars(x, y), funs(na_if(.,.)))

# # A tibble: 3 x 3
#       x y         z
#   <dbl> <chr> <int>
# 1    NA NA        4
# 2    NA NA        5
# 3    NA NA        6

同时更改所有列同时保留变量的另一种方法 类:

df[] <- lapply(df, function(x) {type <- class(x); x <- NA; class(x) <- type; x})

df
# A tibble: 3 x 2
#      x y    
#  <dbl> <chr>
#1    NA <NA> 
#2    NA <NA> 
#3    NA <NA> 

正如@digEmAll 在评论中指出的那样,还有另一种类似但更短的方法:

df[] <- lapply(df, function(x) as(NA,class(x)))

另一种方法使用dplyr

df <- tibble(x = c(1,2,3), y = c("a", "b", "c")) 
df
#> # A tibble: 3 x 2
#>       x y    
#>   <dbl> <chr>
#> 1     1 a    
#> 2     2 b    
#> 3     3 c

df %>% 
  mutate(across(everything(), ~as(NA, class(.x))))
#> # A tibble: 3 x 2
#>       x y    
#>   <dbl> <chr>
#> 1    NA <NA> 
#> 2    NA <NA> 
#> 3    NA <NA>