将下一个值替换为“1”

3

我有一个包含1565行和132列的矩阵。所有的观测值都是“0”或“1”。现在我想保持所有的观测值不变,只做一次修改,即每当出现“1”时,同一行中紧接着的值应该变成“1”。请看下面的示例:

>df
 0    0    1    0    0
NA    0    1    1    0
 0    1    0    0    NA

What I want is :

 0    0    1    1    0
NA    0    1    1    1
 0    1    1    0    NA

我很感谢你的帮助。
Saba
4个回答

3

您可以像在向量中一样利用矩阵中的向量化。给定一个矩阵xx[, -1][x[, -ncol(x)] == 1] <- 1可以完成您想要的操作。以下是示例和说明:

# Create sample matrix
set.seed(100)
x <- sample(c(0, 1, NA), 100, replace = TRUE)
x <- matrix(x, ncol = 10)

# Examine before replacement
x
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#>  [1,]    0    1    1    1    0    0    1    1    1    NA
#>  [2,]    0   NA   NA   NA   NA    0    1    0    1     0
#>  [3,]    1    0    1    1   NA    0   NA    1   NA     1
#>  [4,]    0    1   NA   NA   NA    0   NA   NA   NA     1
#>  [5,]    1   NA    1   NA    1    1    1    1    0    NA
#>  [6,]    1   NA    0   NA    1    0    1    1    1     1
#>  [7,]   NA    0   NA    0   NA    0    1   NA   NA     1
#>  [8,]    1    1   NA    1   NA    0    1   NA    0     0
#>  [9,]    1    1    1   NA    0    1    0   NA    0     0
#> [10,]    0   NA    0    0    0    0   NA    0   NA    NA

# Replace any cell right-of-1 with 1
x[, -1][x[, -ncol(x)] == 1] <- 1

# Examine after replacement
x
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#>  [1,]    0    1    1    1    1    0    1    1    1     1
#>  [2,]    0   NA   NA   NA   NA    0    1    1    1     1
#>  [3,]    1    1    1    1    1    0   NA    1    1     1
#>  [4,]    0    1    1   NA   NA    0   NA   NA   NA     1
#>  [5,]    1    1    1    1    1    1    1    1    1    NA
#>  [6,]    1    1    0   NA    1    1    1    1    1     1
#>  [7,]   NA    0   NA    0   NA    0    1    1   NA     1
#>  [8,]    1    1    1    1    1    0    1    1    0     0
#>  [9,]    1    1    1    1    0    1    1   NA    0     0
#> [10,]    0   NA    0    0    0    0   NA    0   NA    NA

以下是关于x[, -1][x[, -ncol(x)] == 1] <- 1如何工作的解释:
逻辑是将两个矩阵叠加在一起:
1. x [,-1]是原始矩阵去掉第一列。这是所有可以更改的数据。第一列永远不会更改,因为左边没有任何东西。
2. x [,-ncol(x)] 是原始矩阵去掉最后一列。这是所有可以发出更改信号的数据。最后一列永远不会发出更改信号,因为它右边没有任何东西。
这两个矩阵具有相同的维度,因此如果叠加在一起,将使可以发出更改信号的单元格(矩阵2)与可能更改的单元格(矩阵1)对齐。
通过调用x [,-1] [x [,-ncol(x)] == 1] ,我们要求返回第一个矩阵中的所有单元格(所有可能更改的单元格),其中第二个矩阵(所有发出信号的单元格)等于1。 <- 1将这些单元格的值设置为1。

非常感谢。它解决了问题,你的解释让人容易理解。再次感谢。 - Saba

2

一种选项是使用whicharr.ind=TRUE来获取行/列索引,将列索引加1,对值进行子集操作并将其更改为1。

i1 <- which(df==1, arr.ind=TRUE)
i1[,2] <- i1[,2]+1
df[i1] <- 1
df
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    0    1    1    0
#[2,]   NA    0    1    1    1
#[3,]    0    1    1    0   NA

如果有与1相邻的NA元素,并且希望将其保留为NA,则可以使用以下代码进行修改。
df[i1] <- replace(df[i1], !is.na(df[i1]), 1)

数据

df <- structure(c(0L, NA, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 1L, 0L, 0L, 
 0L, NA), .Dim = c(3L, 5L), .Dimnames = list(NULL, NULL))

非常感谢。这真的很容易理解并获得准确的结果。但是,如果下一个单元格中有NA,则不应将此NA替换为1。我能否对上述代码进行修改以获得所需的结果? - Saba
@Saba 可能是可以的,但在你的原始帖子中没有提到这个条件。 - akrun
是的。对不起。 - Saba
1
非常感谢,这真的很有帮助。 :-) - Saba

1
使用 dplyr 包中的一些辅助函数,结合 apply 函数,您可以将矩阵向右移动 1 个单位并与原始矩阵进行逻辑或运算(|),因为 1 | (1,0,NA) = 1,这会将 1 后面的值转换为 1;使用 coalesce 函数将移动后矩阵中的所有 NA 转换为 0,以避免将 0 转换为 NA
library(dplyr)
t(apply(mat, 1, function(r) as.integer(r | lag(coalesce(r, 0L), default = 0))))

#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    0    1    1    0
#[2,]   NA    0    1    1    1
#[3,]    0    1    1    0   NA

或者您可以使用基本的R:

t(apply(mat, 1, function(r) as.integer(r | c(0, replace(r[-length(r)], 
                                                        is.na(r[-length(r)]), 0)))))

#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    0    1    1    0
#[2,]   NA    0    1    1    1
#[3,]    0    1    1    0   NA

0

假设之前的列到列修改不算作正面信号。

set.seed(1)
nr    = 1565
nc    = 132
input = matrix(sample(c(0,1),nr*nc,replace=TRUE),nrow = nr,ncol=nc)
makeNext1 = function(){
  out = input
  for(ixCol in c(1:(nc-1))){
    ix = which(input[,ixCol] == 1)
    if(length(ix) > 0)
      out[ix,ixCol + 1] = 1
  }
  out
}
result = makeNext1()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接