R:用 NA 随机替换值

问题描述 投票:0回答:2

我正在使用 R 编程语言。我尝试选择数据集中 10% 的元素(不包括第一列中的元素)并将其替换为 NA。我尝试使用以下代码来做到这一点:

 library(longitudinalData)
 data(artificialLongData)

second_dataset = artificialLongData
second_dataset[sample(nrow(second_dataset),0.1*nrow(second_dataset ))]<- NA

这会产生以下错误:

Error in `[<-.data.frame`(`*tmp*`, sample(nrow(second_dataset), 0.1 *  : 
  new columns would leave holes after existing columns

有人可以告诉我如何解决这个问题吗?

谢谢!

注意:最终结果应该如下所示:

  id    t0    t1    t2    t3    t4    t5    t6    t7    t8    t9   t10
1 s1  NA  NA -1.85 -2.05  1.01  1.56  NA  0.52 -0.06 -1.09  0.44
2 s2 -4.88 -2.95 -2.38  3.73 -2.77  1.72 -0.99 -0.70  NA  2.38 -0.72
3 s3  NA -0.86  NA -2.04 -1.18  4.89 NA  0.50  4.90 -0.52  NA
r data-manipulation
2个回答
1
投票

您可以在

replace
lapply
随机元素。

set.seed(42)
r1 <- as.data.frame(lapply(dat, \(x) replace(x, sample(length(x), .1*length(x)), NA)))

r1
#    X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
# 1  NA  7 NA 10  3 11  4  4 NA   7
# 2   6  6  8  8  4 11 NA  8 10   9
# 3   1 12  4  5 12  3 10  3 11   1
# 4   3 10  6  2 11 NA  3 11  2  11
# 5   8 NA 10 12  5  7  2  9  4  10
# 6  12  4  9 12  9  2  7  9  8   8
# 7   7  5  9  4  2 12 12  3  4   4
# 8  12  5  3  1  6  1  4  7  6  NA
# 9   4  6 12 NA  5  8  4  4  6   7
# 10  3  2 11  3 NA  5  4 NA  2   4

mean(is.na(r1))
# [1] 0.1

但是,这会将每列中的 0.1 个值替换为

NA
。如果我们希望每个单元格都以 0.1 的概率替换为
NA
,我们可以在两个
apply
上使用
MARGINS=1:2

set.seed(42)
p <- .1
r2 <- as.data.frame(apply(dat, 1:2, \(x) sample(c(x, NA), 1, prob=c((1 - p), p))))

r2
#    X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
# 1  NA  7 NA 10  3 11  4  4 12   7
# 2  NA  6  8  8  4 11 NA  8 10   9
# 3   1 NA NA  5 12  3 10  3 11   1
# 4   3 10 NA  2 NA  9  3 11  2  NA
# 5   8 12 10 12  5  7  2  9  4  NA
# 6  12 NA  9 12 NA  2  7  9  8   8
# 7   7 NA  9  4  2 12 12  3  4   4
# 8  12  5 NA  1  6  1  4  7  6  12
# 9   4  6 12 NA NA  8  4  4  6   7
# 10  3  2 11  3  3  5  4  8  2   4
mean(is.na(r2))
# [1] 0.16

如果可以强制数据

as.matrix
你可以将其视为向量

set.seed(42)
m <- as.matrix(dat)
m[sample(seq_along(m), .1*length(m))] <- NA

m
#       X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
#  [1,]  6  7  1 10  3 11  4 NA 12   7
#  [2,]  6  6  8  8  4 11 10  8 10   9
#  [3,]  1 12  4  5 12  3 10  3 11   1
#  [4,]  3 10 NA  2 11  9  3 NA  2  11
#  [5,]  8 12 NA 12  5  7 NA  9  4  10
#  [6,] 12  4  9 12  9  2  7  9  8   8
#  [7,]  7  5  9  4 NA 12 12  3  4   4
#  [8,] 12 NA  3  1  6  1  4  7  6  12
#  [9,]  4  6 12  3 NA  8  4  4 NA   7
# [10,]  3  2 11  3  3  5  4  8  2  NA

mean(is.na(m))
# [1] 0.1

并强制返回

"data.frame"

dat_na <- as.data.frame(m) |> type.convert(as.is=TRUE)

type.convert
负责恢复像
"numeric"
"character"
这样的类,因为矩阵只能有一种模式。请注意,您可能会在此过程中丢失属性。


数据:

dat <- structure(list(X1 = c(6L, 6L, 1L, 3L, 8L, 12L, 7L, 12L, 4L, 3L
), X2 = c(7L, 6L, 12L, 10L, 12L, 4L, 5L, 5L, 6L, 2L), X3 = c(1L, 
8L, 4L, 6L, 10L, 9L, 9L, 3L, 12L, 11L), X4 = c(10L, 8L, 5L, 2L, 
12L, 12L, 4L, 1L, 3L, 3L), X5 = c(3L, 4L, 12L, 11L, 5L, 9L, 2L, 
6L, 5L, 3L), X6 = c(11L, 11L, 3L, 9L, 7L, 2L, 12L, 1L, 8L, 5L
), X7 = c(4L, 10L, 10L, 3L, 2L, 7L, 12L, 4L, 4L, 4L), X8 = c(4L, 
8L, 3L, 11L, 9L, 9L, 3L, 7L, 4L, 8L), X9 = c(12L, 10L, 11L, 2L, 
4L, 8L, 4L, 6L, 6L, 2L), X10 = c(7L, 9L, 1L, 11L, 10L, 8L, 4L, 
12L, 7L, 4L)), class = "data.frame", row.names = c(NA, -10L))

0
投票

使用

Tidyverse

library(tidyverse)
second_dataset <- artificialLongData  %>%
  mutate(across(-id,~ifelse(runif(length(.))>0.1,., NA)))

在除

id
之外的每一列,它以指定的概率创建
TRUE
FALSE
的向量。保留数据集中的每个
TRUE
元素,每个
FALSE
元素都替换为
NA

仅修改一列,例如

t1
,我们会使用:

artificialLongData %>%
  mutate(t1,t1=ifelse(runif(length(t1))>0.1,t1, NA))

across()
将该函数应用于所有指定的列。
-id
表示除
id
之外的所有列。

© www.soinside.com 2019 - 2024. All rights reserved.