R:按行替换两个特定值之间的NA值

时间:2016-02-01 15:43:48

标签: r

我正在努力让我的数据准备好以后进行序列分析;要做到这一点,我需要在值1和2之间插入值1。 因此,对于每一行,1和2之间的所有NA都等于1。我在下面列出了一个示例表;在我的实际数据中,每一行都是一个独特的个体,每列都是一个时间段。 1代表录取,2代表节目放电。我试图将“录取”和“放电”之间的时间段设置为等于1表示已注册该程序,然后将剩余的NA设置为0表示不在程序中。每行/每个人可以有多个录取。

我一直在尝试使用apply,我可以自己更改值,但是我不能在值1和2之间替换NA。任何指导都会非常感激!

mdat <- matrix(c(1,NA,NA,NA,2,NA,NA,1,NA,2,  NA,NA,1,2,NA,NA,NA,1,NA,2), nrow = 2, ncol=10, byrow=TRUE,
           dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3", "C.4", "C.5", "C.6", "C.7", "C.8", "C.9", "C.10")))

|      | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8| c9 | c10 |
----------------------------------------------------------
|row 1 | 1  | NA | NA | NA | 2  | NA | NA | 1 | NA | 2   |
|row 2 | NA | NA | 1  | 2  | NA | NA | NA | 1 | NA | 2   |

期望的结果;

|      | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8| c9 | c10 |
----------------------------------------------------------
|row 1 | 1  | 1  | 1  | 1  | 2  | NA | NA | 1 | 1  | 2   |
|row 2 | NA | NA | 1  | 2  | NA | NA | NA | 1 | 1  | 2   |

3 个答案:

答案 0 :(得分:4)

如果我正确理解了您的需求,您可以先将NA替换为0,然后按周期搜索2的比较结果,以填充&#34;间隙&#34;使用1(然后转换结果以保留以前的格式):

mdat[is.na(mdat)] <- 0
mdat <- t(apply(mdat, 1, function(x) {x[cumsum(x==2) < cumsum(x==1)] <- 1; x}))
mdat
#     C.1 C.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9 C.10
#row1   1   1   1   1   2   0   0   1   1    2
#row2   0   0   1   2   0   0   0   1   1    2

答案 1 :(得分:2)

1)我们可以通过使用zoo包中的na.locf来填充NA,然后替换对应于1的mdat元素,从而得到一个相对紧凑的解决方案。填写版本1:

library(zoo)

replace(mdat, t(na.locf(t(mdat))) == 1, 1)

,并提供:

     C.1 C.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9 C.10
row1   1   1   1   1   2  NA  NA   1   1    2
row2  NA  NA   1   2  NA  NA  NA   1   1    2

2)或者使用na.locf并将mdat中NA为NA的传播的2替换为NA。我们使用dplyr管道(尽管如果需要可以将其删除):

library(dplyr)
library(zoo)

mdat %>% t %>% na.locf %>% t %>% replace(. == 2 & is.na(mdat), NA)

答案 2 :(得分:0)

编辑:完全不同的答案。我并不完全清楚OP想要什么,但是这段代码虽然很慢,但会在NA 1之后立即替换所有1。我的帖子只是为了让有空闲时间和microbenchmark副本的人都可以看到na.locf做得多好。

foo <- c(1,NA,2,NA,1,2,1,NA,NA,NA,2,NA,NA)
foo
length(foo)
for(jj in 2:length(foo) ) {
if ( (!is.na(foo[jj-1]) && foo[jj-1]==1) & is.na(foo[jj])) foo[jj]=1
}
foo
#then replace remaining `NA` with zero if desired