R 基于第一次注册和最近值转换NA值

R 基于第一次注册和最近值转换NA值,r,na,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

我已经提出了一个类似的问题,但现在我只想限制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
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
我想根据值注册的第一天更改数据的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  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
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

你能帮我吗?我不知道如何在R中执行此操作。

这里有一种方法,使用
zoo
包中的
na.approx
apply
使用
MARGIN=1
(因此这可能不是很有效,但完成了任务)

替换
NA
s并重命名列

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
但是OP要求常量值,所以我们需要
approx
函数中的参数
method=“constant”

na.approx(x, method = "constant") 
# [1] 0.1 0.1 0.1 0.3 0.2
但这仍然不是OP所要求的,因为它将最后一次观察向前推进,而您需要最接近的非NA值的平均值。因此,我们需要参数
f
(也来自
近似值

从<代码>?大约<代码>

na.approx(x, method = "constant", f = .5)
# [1] 0.1 0.2 0.2 0.3 0.2 # looks good
f:for method=“constant”是一个介于0和1之间(包括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(x, method = "constant", f = .5)
# [1] 0.1 0.2 0.2 0.3 0.2 # looks good
na.rm:合乎逻辑。如果(样条曲线)插值的结果仍然导致NAs,是否应删除这些结果

数据

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"))

这是另一个可能的答案,使用
zoo
软件包中的
na.locf
。 编辑:
apply
实际上不是必需的;如果缺少此值,此解决方案将填充上次观察到的值

# create the dataframe
Date1 <- c(NA,.1,NA,NA)
Date2 <- c(.1, NA,NA,NA)
Date3 <- c(.2,NA,NA,.1)
Date4 <- c(NA,.3,NA,.2)
Date5 <- c(.3,.2,.3,.1)
Date6 <- c(.1,NA,NA,NA)
df <- as.data.frame(cbind(Date1,Date2,Date3,Date4,Date5,Date6))
rownames(df) <- c('A','B','C','D')

> df
  Date1 Date2 Date3 Date4 Date5 Date6
A    NA   0.1   0.2    NA   0.3   0.1
B   0.1    NA    NA   0.3   0.2    NA
C    NA    NA    NA    NA   0.3    NA
D    NA    NA   0.1   0.2   0.1    NA



# Load library
library(zoo)
df2 <- t(na.locf(t(df),na.rm = F)) # fill last observation carried forward
df3 <- t(na.locf(t(df),na.rm = F, fromLast = T)) # last obs carried backward

df4 <- (df2 + df3)/2 # mean of both dataframes

df4 <- t(na.locf(t(df4),na.rm = F)) # fill last observation carried forward
df4[is.na(df4)] <- 0 # NA values are 0

  Date1 Date2 Date3 Date4 Date5 Date6
A   0.0   0.1   0.2  0.25   0.3   0.1
B   0.1   0.2   0.2  0.30   0.2   0.2
C   0.0   0.0   0.0  0.00   0.3   0.3
D   0.0   0.0   0.1  0.20   0.1   0.1
#创建数据帧

Date1我发现下面的函数太复杂了,但它可以工作,所以就这样

fun <- function(x){
  if(anyNA(x)){
    inx <- which(!is.na(x))
    if(inx[1] > 1) x[seq_len(inx[1] - 1)] <- 0
    prev <- inx[1]
    for(i in inx[-1]){
      if(i - prev > 1){
        m <- mean(c(x[i], x[prev]))
        while(prev < i){
          x[prev] <- m
          prev <- prev + 1
        }
      }
      prev <- i
    }
  }
  x
}

res <- t(apply(df1, 1, fun))
res <- as.data.frame(res)
res
#  Date.1 Date.2 Date.3 Date.4 Date.5
#A    0.0    0.1   0.25   0.25    0.3
#B    0.2    0.2   0.20   0.30    0.2
#C    0.0    0.0   0.00   0.00    0.3
#E    0.0    0.0   0.10   0.20    0.1

fun这里有另一个选项,它是
zoo
中的base R+
rollmean
(对于窗口大小为
k=2的情况,显然很容易用base R重写)

然后

是0的向量,滚动表示以下两个非NA元素和最后一个非NA元素。然后我们需要做的就是替换
x的
is.na(x)
元素。我们将用指数
1+cumsum(!is.na(x))[is.na(x)]
处的
means
元素替换它们。这是更棘手的部分。这里

cumsum(!is.na(x))
# [1] 0 1 2 2 3 4
这意味着
x
的第一个元素看到了0个非NA元素,而最后一个元素到目前为止看到了4个非NA元素。然后

cumsum(!is.na(x))[is.na(x)]
# [1] 0 2
是关于我们要替换的
x
中的NA元素。请注意

1 + cumsum(!is.na(x))[is.na(x)]
# [1] 1 3

对应于我们要用于替换的
的元素。

很好!这是我所走的路线,但无法使
na.approx
正常工作。你能解释一下这些参数吗?(
method
f
)。仅供参考。
na.近似值
来自
zoo
软件包,而非基本值R@Sotos添加了一些解释。非常感谢!那么
f=.5
不是连续的吗?只是告诉它要中庸?i、 e.我们无法指定(
f=.6
)?@Sotos
f
可以是介于
0
(默认)和
1
之间的数字
0
表示上一次观察结转,
1
将是下一次观察结转,因为中间的任何数字都将导致
y0*(1-f)+y1*f
,请参见
?近似值
太好了!我有一个问题,如果数据在最后一列中有一个NA,我如何将最后一个NA转换为最后一个注册值?
t(apply(df, 1, function(x) {
  means <- c(0, rollmean(na.omit(x), 2), tail(na.omit(x), 1))
  replace(x, is.na(x), means[1 + cumsum(!is.na(x))[is.na(x)]])
}))
#   Date1 Date2 Date3 Date4 Date5 Date6
# A   0.0   0.1   0.2  0.25   0.3   0.2
# B   0.1   0.2   0.2  0.30   0.2   0.1
# C   0.0   0.0   0.0  0.00   0.3   0.3
# D   0.1   0.2   0.3  0.20   0.1   0.1
# E   0.0   0.0   0.1  0.20   0.1   0.3
#   Date1 Date2 Date3 Date4 Date5 Date6
# A    NA   0.1   0.2    NA   0.3   0.2
means
# [1] 0.00 0.15 0.25 0.25 0.20
cumsum(!is.na(x))
# [1] 0 1 2 2 3 4
cumsum(!is.na(x))[is.na(x)]
# [1] 0 2
1 + cumsum(!is.na(x))[is.na(x)]
# [1] 1 3