根据首次注册和最近值转换NA值

use*_*366 12 r na

我已经提出了类似的问题,但现在我想限制NA的新值.

我有一些这样的数据:

Date 1   Date 2    Date 3    Date 4    Date 5   Date 6
A  NA       0.1       0.2       NA        0.3    0.2
B  0.1      NA        NA        0.3       0.2    0.1
C  NA       NA        NA        NA        0.3    NA
D  0.1      0.2       0.3       NA        0.1    NA
E  NA       NA        0.1       0.2       0.1    0.3
Run Code Online (Sandbox Code Playgroud)

我想根据注册值的第一个日期更改数据的NA值.因此,例如对于A,第一次注册是日期2.然后我希望在注册之前A中的NA的值是0,并且在第一次注册之后,NA的值变为最接近的值的平均值(日期的平均值3)和5).

如果最后一个值是NA,则将其转换为最后一个注册值(如在C和D中).在E的情况下,所有NA值将变为0.

得到这样的东西:

Date 1   Date 2    Date 3    Date 4    Date 5   Date 6 
A  0       0.1       0.2        0.25      0.3    0.2
B  0.1     0.2       0.2        0.3       0.2    0.1
C  0       0         0          0         0.3    0.3
D  0.1     0.2       0.3        0.2       0.1    0.1
E  0       0         0.1        0.2       0.1    0.3
Run Code Online (Sandbox Code Playgroud)

你能帮助我吗?我不知道如何在R中做到这一点.

mar*_*kus 9

下面是一个使用方式na.approxzoo包装和apply使用MARGIN = 1(所以这可能是不是很有效,但得到的完成工作).

library(zoo)
df1 <- as.data.frame(t(apply(dat, 1, na.approx, method = "constant", f = .5, na.rm = FALSE)))
Run Code Online (Sandbox Code Playgroud)

这导致了

df1
#   V1  V2  V3   V4  V5
#A  NA 0.1 0.2 0.25 0.3
#B 0.1 0.2 0.2 0.30 0.2
#C  NA  NA  NA   NA 0.3
#E  NA  NA 0.1 0.20 0.1
Run Code Online (Sandbox Code Playgroud)

替换NAs并重命名列.

df1[is.na(df1)] <- 0
names(df1) <- names(dat)
df1
#  Date_1 Date_2 Date_3 Date_4 Date_5
#A    0.0    0.1    0.2   0.25    0.3
#B    0.1    0.2    0.2   0.30    0.2
#C    0.0    0.0    0.0   0.00    0.3
#E    0.0    0.0    0.1   0.20    0.1
Run Code Online (Sandbox Code Playgroud)

说明

给出一个矢量

x <- c(0.1, NA, NA, 0.3, 0.2)
na.approx(x)
Run Code Online (Sandbox Code Playgroud)

返回x线性插值

#[1] 0.1000000 0.1666667 0.2333333 0.3000000 0.2000000
Run Code Online (Sandbox Code Playgroud)

但OP要求常数值,所以我们需要的参数method = "constant"approx功能.

na.approx(x, method = "constant") 
# [1] 0.1 0.1 0.1 0.3 0.2
Run Code Online (Sandbox Code Playgroud)

但这仍然不是OP要求的,因为当你想要最接近的非NA值的均值时,它会向前推进最后一个观察.因此我们需要论证f(也来自approx)

na.approx(x, method = "constant", f = .5)
# [1] 0.1 0.2 0.2 0.3 0.2 # looks good
Run Code Online (Sandbox Code Playgroud)

?approx

f:for method ="constant"0到1之间的数字,表示左连续和右连续步长函数之间的折衷.如果y0和y1是该点左侧和右侧的值,则如果f == 0,则值为y0;如果f == 1,则值为y1;对于中间值,y0*(1-f)+ y1*f.这样,对于f == 0,结果是右连续的,对于f == 1,结果是左连续的,即使对于非有限y值也是如此.

最后,如果我们不想NA在我们需要的每一行的开头和结尾替换s na.rm = FALSE.

?na.approx

na.rm:合乎逻辑的.如果(样条)插值的结果仍然导致NA,是否应该删除它们?

数据

dat <- structure(list(Date_1 = c(NA, 0.1, NA, NA), Date_2 = c(0.1, NA, 
NA, NA), Date_3 = c(0.2, NA, NA, 0.1), Date_4 = c(NA, 0.3, NA, 
0.2), Date_5 = c(0.3, 0.2, 0.3, 0.1)), .Names = c("Date_1", "Date_2", 
"Date_3", "Date_4", "Date_5"), class = "data.frame", row.names = c("A", 
"B", "C", "E"))
Run Code Online (Sandbox Code Playgroud)

编辑

如果NA最后一列中有s,我们可以NA在申请之前用最后的非s 替换它们,na.approx如上所示.

dat$Date_6[is.na(dat$Date_6)] <- dat[cbind(1:nrow(dat),
                                           max.col(!is.na(dat), ties.method = "last"))][is.na(dat$Date_6)]
Run Code Online (Sandbox Code Playgroud)

  • @Sotos补充了一些解释.最好 (3认同)
  • @Sotos`f`可以是介于"0"(默认)和"1"之间的数字."0"表示结束的最后一次观察,"1"将被向后观察,因为其间的任何数字都将导致"y0*(1-f)+ y1*f",参见`?approx` (3认同)