根据几个条件和返回值比较所有行

时间:2013-08-27 08:38:58

标签: r for-loop row

我想比较不同行中的不同单元格,并在条件满足时返回值。

假设以下s_i =

        [,1]      [,2]      [,3]
[1,] 0.43020494 0.7183179 0.4201009
[2,] 0.08625491 0.3007912 0.8768459
[3,] 0.80012649 0.8448729 0.7131344

我想比较所有的行(对),所以第1,2行; 1,3; 2,3; 2,1; 3,1和3,2行 输出dgpos包含组合的行号和返回的值。

我想比较行。为第一或第1和第2行组合的第一个

1,  if  2b≥1b
0, if 1a≥2c
(1a-2c )/ ((2b-2c) –(1b-1a), otherwise

其中a,b和c是s_i

的列

第1行和第2行的R-ish

If   (s_i[2,2]>= s_i[1,2])
 dgpos[rowindex,3]=1

If   (s_i[1,1]>= s_i[2,3])
dgpos[rowindex,3]=0

else (otherwise)

dgpos[rowindex,3] =(s_i[1,1]- s_i[2,3])/((s_i[2,2]-s_i[2,3])-(s_i[1,2]-s_i[1,1]))

我想要的输出包含dgpos[,3]

中返回的组合和值
    [,1] [,2] [,3]
[1,]    1    2    0.5168453
[2,]    1    3    1
[3,]    2    3    1
[4,]    2    1    1
[5,]    3    1    0
[6,]    3    2    0.1235813

我有这个:

s_i=matrix(runif(9),3)

dgpos=matrix(0,(dim(s_i)[2]*(dim(s_i)[2]-1)),3)

rowindex=1



for (i in 1:nrow(s_i)) {
  for (j in 1:nrow(s_i)) {
    if (i!=j)

      c1=s_i[i,]
    c2=s_i[j+1,]

    dgpos[rowindex,1]=i
    dgpos[rowindex,2]=j+1

    if (c2[2] >= c1[2])
      dgpos[rowindex,3]=1

    dgpos[rowindex,3] = ifelse ((c1[1]=c2[3]), 0 , c1[1]-c2[3]/((c2[2]-c2[3])-(c1[2]-c1[1])))

    rowindex=rowindex+1  
  }
 }

我知道循环不是首选,但此刻(我的r-ish级别)我不知道更好的解决方案。我使用adply尝试了combn,没有结果。

MQ:如何比较不同行中的不同单元格并根据几个条件返回值?

感谢您的帮助和赞扬。

3 个答案:

答案 0 :(得分:0)

我不保证这正是您想要的逻辑(您的示例和代码之间存在不一致),但这是对您的算法进行矢量化的正确方法:

首先,创建所有行索引组合的data.frame:

n <- nrow(s_i)
dgpos <- rev(expand.grid(row2 = seq_len(n), row1 = seq_len(n)))
dgpos <- subset(dgpos, row1 != row2)
dgpos
#   row1 row2
# 2    1    2
# 3    1    3
# 4    2    1
# 6    2    3
# 7    3    1
# 8    3    2

然后,在一个向量化调用中计算结果,嵌套ifelse

dgpos <- transform(dgpos, out = { c1 <- s_i[row1, ]
                                  c2 <- s_i[row2, ]
                                  ifelse(c2[,2] >= c1[,2], 1,
                                  ifelse(c1[,1] >= c2[,3], 0,
                                  (c1[,1]-c2[,3]) / ((c2[,2]-c2[,3]) - (c1[,2]-c1[,1])))) })
dgpos
#   row1 row2 out
# 2    1    2   0
# 3    1    3   0
# 4    2    1   0
# 6    2    3   0
# 7    3    1   0
# 8    3    2   0

答案 1 :(得分:0)

这要归功于@flodel。毫无疑问,这不是最优雅的解决方案

dgpos = rev(expand.grid(row2 = seq_len(nrow(s_i)), row1 = seq_len(nrow(s_i))))
dgpos =  subset(dgpos, row1 != row2)

for (i in 1:nrow(dgpos)) {

  c1 = s_i[dgpos$row1[i], ]
  c2 = s_i[dgpos$row2[i], ]

  dgpos$out[i] = ifelse(c2[2] >= c1[2], 1,
           ifelse(c1[1] >= c2[3], 0,
                  (c1[1]-c2[3]) / ((c2[2]-c2[3]) - (c1[2]-c1[1])))) }

dgpos

   # row1 row2       out
   # 2    1    2 0.5168453
   # 3    1    3         1
   # 4    2    1         1
   # 6    2    3         1
   # 7    3    1         0
   # 8    3    2 0.1235813

答案 2 :(得分:0)

我设法使用以下方法重现您想要的输出:

f <- function(i, j, s){
    ifelse(s[j,2]>=s[i,2], 1, ifelse(s[i,1]>=s[j,3], 0,
        (s[i,1]-s[j,3])/((s[j,2]-s[j,3])-(s[i,2]-s[i,1]))))
}

s_i <- rbind(
c(0.43020494, 0.7183179, 0.4201009),
c(0.08625491, 0.3007912, 0.8768459),
c(0.80012649, 0.8448729, 0.7131344))

y <- combn(nrow(s_i), 2)

dgpos <- t(cbind(y, y[2:1,]))

cbind(dgpos, f(dgpos[,1], dgpos[,2], s_i))

结果:

     [,1] [,2]      [,3]
[1,]    1    2 0.5168453
[2,]    1    3 1.0000000
[3,]    2    3 1.0000000
[4,]    2    1 1.0000000
[5,]    3    1 0.0000000
[6,]    3    2 0.1235813