根据 R 中的元素邻接分配元素值

Assign an element value based on element adjacencies in R

我有一个包含 {0,1} 的数据框,指示产品是小型、中型还是大型。

dat <- data.frame(Sm = c(1,0,0), Med = c(0,1,0), Lg = c(0,0,1))

  Sm Med Lg
1  1   0  0
2  0   1  0
3  0   0  1

我希望将 1 分配给给定行中 1 之前的 0。例如,在第 2 行中,产品是 "Med",因此我希望将 1 分配给 "Sm" 列中的 0。

分配大小是一个考虑因素,所以我正在寻找一种不使用 for 循环的矢量化方法。最终解决方案应输出以下内容:

  Sm Med Lg
1  1   0  0
2  1   1  0
3  1   1  1

我尝试了以下代码的几种变体,但我能得到的最接近的是一个参差不齐的数组,它正确分配所有 1,同时删除具有合法 0 的元素。

apply(dat, 1, function(x) {
    x[1:which.max(x)] <- 1
})

[1] 1 1 1

及以下,接近但没有所需的尾随 0

apply(dat, 1, function(x) {
    temp <- x[1:which.max(x)]
    unlist(lapply(temp, function(y) {
        y <- 1
    }))
})

[[1]]
Sm 
1 
[[2]]
Sm Med 
1   1 
[[3]]
Sm Med  Lg 
1   1   1 

首先,转换为矩阵并使用max.col得到每行1的索引:

mat <- as.matrix(dat)
mc  <- max.col(mat)

逻辑构造覆盖矩阵:

mat = +(col(mat) <= mc)

或者构造一个矩阵位置的索引来改变和改变'em:

逻辑索引

mat[col(mat) < mc] <- 1L
# or
mat[which(col(mat) < mc)] <- 1L

矩阵索引

idx <- do.call( rbind, lapply( seq_along(mc), function(i) 
    if (i==1L) NULL 
    else       cbind(i,seq_len(mc[i]-1))
))

mat[idx] <- 1L

向量索引

nr  <- nrow(mat)
idx <- unlist( lapply( seq_along(mc), function(i) 
  if (mc[i]==1L) NULL 
  else           seq(from = i, by = nr, length.out = mc[i]-1L) 
))

mat[idx] <- 1L

可以在 help("[<-").

找到所有三种索引方法的帮助

这会做你想做的事。

dat[which(dat$Med==1),]$Sm = 1
dat[which(dat$Lg==1),]$Med = 1
dat[which(dat$Lg==1),]$Sm = 1