根据R中的元素邻接关系指定元素值

时间:2015-08-03 19:30:55

标签: r element assign

我有一个{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分配给0到达给定行中的1。例如,在第2行中,产品是&#34; Med&#34;,因此我希望在&#34; Sm&#34;中分配1到0。列。

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

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

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

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 

2 个答案:

答案 0 :(得分:4)

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

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

逻辑构造覆盖矩阵:

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

或构建矩阵位置索引以更改和更改&#39; 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("[<-")找到所有三种索引方法的帮助。

答案 1 :(得分:1)

这将做你想要的。

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