93

有很多关于替换 NA 值的帖子。我知道可以将下表/框架中的 NA 替换为以下内容:

x[is.na(x)]<-0

但是,如果我想将其限制为仅某些列怎么办?让我给你看一个例子。

首先,让我们从数据集开始。

set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
                b=sample(c(1,2,NA), 10, replace=T), 
                c=sample(c(1:5,NA), 10, replace=T))

这使:

    a  b  c
1   1 NA  2
2   2  2  2
3   2  1  1
4   2 NA  1
5  NA  1  2
6   2 NA  5
7   1  1  4
8   1  1 NA
9   2  1  5
10  2  1  1

好的,所以我只想将替换限制为“a”和“b”列。我的尝试是:

x[is.na(x), 1:2]<-0

和:

x[is.na(x[1:2])]<-0

哪个不起作用。

我的 data.table 尝试, wherey<-data.table(x)显然永远不会工作:

y[is.na(y[,list(a,b)]), ]

我想在 is.na 参数中传递列,但这显然行不通。

我想在 data.frame 和 data.table 中执行此操作。我的最终目标是将“a”和“b”中的 1:2 重新编码为 0:1,同时保持“c”的原样,因为它不是逻辑变量。我有一堆专栏,所以我不想一个一个地做。而且,我只想知道如何做到这一点。

你有什么建议吗?

4

11 回答 11

132

你可以做:

x[, 1:2][is.na(x[, 1:2])] <- 0

或更好(恕我直言),使用变量名:

x[c("a", "b")][is.na(x[c("a", "b")])] <- 0

在这两种情况下,1:2c("a", "b")都可以替换为预定义的向量。

于 2013-10-15T10:52:37.000 回答
39

在@Robert McDonald's tidyr::replace_na()answer的基础上,这里有一些用于控制替换 sdplyr列的选项:NA

library(tidyverse)

# by column type:
x %>%
  mutate_if(is.numeric, ~replace_na(., 0))

# select columns defined in vars(col1, col2, ...):
x %>%
  mutate_at(vars(a, b, c), ~replace_na(., 0))

# all columns:
x %>%
  mutate_all(~replace_na(., 0))
于 2019-03-22T02:23:01.323 回答
35

编辑 2020-06-15

data.table1.12.4(2019 年 10 月)以来,data.table获得了两个功能来促进这一点:nafillsetnafill.

nafill对列进行操作:

cols = c('a', 'b')
y[ , (cols) := lapply(.SD, nafill, fill=0), .SDcols = cols]

setnafill在表上操作(替换通过引用/就地发生)

setnafill(y, cols=cols, fill=0)
# print y to show the effect
y[]

这也将比其他选项更有效;有关更多信息,请参见时间序列插补?nafill的最后一个观测值结转 (LOCF) 和下一个观测值结转 (NOCB) 版本。NA


这将适用于您的data.table版本:

for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]

或者,正如 David Arenburg 在下面指出的那样,您可以使用set(附带好处 - 您可以在data.frame或上使用它data.table):

for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)
于 2013-10-15T15:07:25.313 回答
19

tidyr这在with中是微不足道的replace_na()。该函数似乎适用于 data.tables 以及 data.frames:

tidyr::replace_na(x, list(a=0, b=0))
于 2017-12-09T14:54:24.873 回答
3

不确定这是否更简洁,但此函数还将在 data.table 的选定列中查找并允许替换 NA(或您喜欢的任何值):

update.mat <- function(dt, cols, criteria) {
  require(data.table)
  x <- as.data.frame(which(criteria==TRUE, arr.ind = TRUE))
  y <- as.matrix(subset(x, x$col %in% which((names(dt) %in% cols), arr.ind = TRUE)))
  y
}

要应用它:

y[update.mat(y, c("a", "b"), is.na(y))] <- 0

该函数创建满足输入条件(在本例中为 is.na == TRUE)的选定列和行(单元格坐标)的矩阵。

于 2016-01-19T21:36:07.233 回答
1

从 data.table y 开始,您可以只写:在创建和运行此命令之前
y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]
不要忘记。library(data.table)y

于 2020-06-15T14:34:41.283 回答
0

对于特定的列,有一个替代方案sapply

DF <- data.frame(A = letters[1:5],
             B = letters[6:10],
             C = c(2, 5, NA, 8, NA))

DF_NEW <- sapply(seq(1, nrow(DF)),
                    function(i) ifelse(is.na(DF[i,3]) ==
                                       TRUE,
                                       0,
                                       DF[i,3]))

DF[,3] <- DF_NEW
DF
于 2016-09-24T20:52:34.330 回答
0

我们可以data.tabletidyr::repalce_na函数的方式解决它lapply

library(data.table)
library(tidyr)
setDT(df)
df[,c("a","b","c"):=lapply(.SD,function(x) replace_na(x,0)),.SDcols=c("a","b","c")]

这样,我们也可以解决用NA字符串粘贴列。首先,我们replace_na(x,""),然后我们可以使用stringr::str_c组合列!

于 2019-09-01T11:26:42.267 回答
0

{data.table} 和 {stringr} 非常方便

library(data.table)
library(stringr)

x[, lapply(.SD, function(xx) {str_replace_na(xx, 0)})]

供参考

于 2019-09-10T19:56:42.850 回答
-1

为了完整起见,基于@sbha 的回答,这里是 tidyverse 版本,该版本具有across()自 1.0 版以来在 dplyr 中可用的功能(它取代了*_at()变体等):

# random data
set.seed(1234)
x <- data.frame(a = sample(c(1, 2, NA), 10, replace = T),
                b = sample(c(1, 2, NA), 10, replace = T), 
                c = sample(c(1:5, NA), 10, replace = T))
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)
# with the magrittr pipe
x %>% mutate(across(1:2, ~ replace_na(.x, 0)))
#>    a b  c
#> 1  2 2  5
#> 2  2 2  2
#> 3  1 0  5
#> 4  0 2  2
#> 5  1 2 NA
#> 6  1 2  3
#> 7  2 2  4
#> 8  2 1  4
#> 9  0 0  3
#> 10 2 0  1
# with the native pipe (since R 4.1)
x |> mutate(across(1:2, ~ replace_na(.x, 0)))
#>    a b  c
#> 1  2 2  5
#> 2  2 2  2
#> 3  1 0  5
#> 4  0 2  2
#> 5  1 2 NA
#> 6  1 2  3
#> 7  2 2  4
#> 8  2 1  4
#> 9  0 0  3
#> 10 2 0  1

reprex 包于 2021-12-08 创建(v2.0.1)

于 2021-08-16T02:28:27.057 回答
-4

这对我来说很好

DataTable DT = new DataTable();

DT = DT.AsEnumerable().Select(R =>
{
      R["Campo1"] = valor;
      return (R);
}).ToArray().CopyToDataTable();
于 2016-07-27T22:41:16.817 回答