有什么办法可以根据另一列的值来替换缺失的值,使之与列名相匹配?

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

我有一个数据集。

    a day day.1.time day.2.time day.3.time day.4.time day.5.time
1  NA   2          4          5          7         10          4
2  NA   5          4          1          1          6         NA
3  NA   3          7          9          6          7          4
4  NA   3          6          8          8          4          5
5  NA   3          5          2          4          5          6
6  NA   3         87          3          2          1         78
7  NA   1         NA          7          5          9         54
8  NA   5          6          6          3          2          3
9  NA   2          5         10          9          8          3
10 NA   3          9          4         10          3          3

我想用 day 列的值来匹配 day.x.time 替换列中缺失的值 a. 例如,在第一行中,第一个值在 day 列是2,那么我们应该使用 day.2.time 用值5代替列中的第一个值 a.

如果 day.x.time 值缺失,我们应该用-1天或+1天来代替列中缺失的值。a. 例如,在第二行, day 列显示为5,所以我们应该使用在 day.5.time 列,但它也是一个缺失的值。在这种情况下,我们应该使用在 day.4.time 替换列中缺失的值 a.

您可以使用 dat = data.frame(a = rep(NA,10), day = c(2,5,3,3,3,3,1,5,2,3), day.1.time = c(4,4,7,6,5,87,NA,6,5,9), day.2.time = sample(10), day.3.time = sample(10), day.4.time = sample(10), day.5.time = c(4,NA,4,5,6,78,54,3,3,3)) 来生成样本数据。

我已经尝试了 grep(paste0("^day."dat$day,".time$", names(dat)) 但我的代码并不是每一行都匹配,所以希望得到任何帮助。

r replace missing-data
1个回答
1
投票

这里有一个方法。

第一部分很容易匹配 day 栏与相应的 day.x.time 列。 我们可以使用矩阵子集来实现。

cols <- grep('day\\.\\d+\\.time', names(dat))
dat$a <- dat[cols][cbind(1:nrow(dat), dat$day)]
dat
#    a day day.1.time day.2.time day.3.time day.4.time day.5.time
#1   3   2          4          3          3          3          4
#2  NA   5          4          4         10          2         NA
#3   1   3          7          8          1          8          4
#4   4   3          6          6          4          5          5
#5   6   3          5         10          6          7          6
#6   8   3         87          5          8          9         78
#7  NA   1         NA          1          7         10         54
#8   3   5          6          7          9          1          3
#9   2   2          5          2          5          6          3
#10  2   3          9          9          2          4          3

填充值在 day.x.time 栏目是 NA 我们可以选择该行中最接近的非NA值。

inds <- which(is.na(dat$a))
dat$a[inds] <- mapply(function(x, y) 
         na.omit(unlist(dat[x, cols[order(abs(y- seq_along(cols)))]])[1:4])[1],
              inds, dat$day[inds])

dat
#   a day day.1.time day.2.time day.3.time day.4.time day.5.time
#1  3   2          4          3          3          3          4
#2  2   5          4          4         10          2         NA
#3  1   3          7          8          1          8          4
#4  4   3          6          6          4          5          5
#5  6   3          5         10          6          7          6
#6  8   3         87          5          8          9         78
#7  1   1         NA          1          7         10         54
#8  3   5          6          7          9          1          3
#9  2   2          5          2          5          6          3
#10 2   3          9          9          2          4          3

1
投票

使用 sapply 在行上循环,并通过以下方式进行子集。day[i] + 2 栏目。

res <- transform(dat, a=sapply(1:nrow(dat), function(i) dat[i, dat$day[i] + 2]))
res
#     a day day.1.time day.2.time day.3.time day.4.time day.5.time
# 1   5   2          4          5          7         10          4
# 2  NA   5          4          1          1          6         NA
# 3   6   3          7          9          6          7          4
# 4   8   3          6          8          8          4          5
# 5   4   3          5          2          4          5          6
# 6   2   3         87          3          2          1         78
# 7  NA   1         NA          7          5          9         54
# 8   3   5          6          6          3          2          3
# 9  10   2          5         10          9          8          3
# 10 10   3          9          4         10          3          3

编辑

+-2天就需要一个决策规则,该怎么选,如果是 dayNA但没有一个 day - 1day + 1NA 并且两者的数值相同。

这里有一个解决方案,从 day 向后,并采取第一个非NA. 如果是第一天,就像行里的情况一样。7,我们得到 NA.

res <- transform(dat, a=sapply(1:nrow(dat), function(i) {
  days <- dat[i, -(1:2)]
  day.value <- days[dat$day[i]]
  if (is.na(day.value)) {
    day.value <- tail(na.omit(unlist(days[1:dat$day[i]])), 1)
    if (length(day.value) == 0) day.value <- NA
  }
  return(day.value)
}))
res
#     a day day.1.time day.2.time day.3.time day.4.time day.5.time
# 1  10   2          4         10          1          2          4
# 2  10   5          4          1          3         10         NA
# 3   2   3          7          7          2          7          4
# 4   6   3          6          2          6          6          5
# 5  10   3          5          9         10          5          6
# 6   8   3         87          6          8          4         78
# 7  NA   1         NA          3          7          1         54
# 8   3   5          6          4          4          9          3
# 9   8   2          5          8          5          8          3
# 10  9   3          9          5          9          3          3
© www.soinside.com 2019 - 2024. All rights reserved.