【问题标题】:Compare all rows depending on several conditions and return value根据几个条件比较所有行并返回值
【发布时间】:2013-08-27 08:38:57
【问题描述】:

我想比较不同行中的不同单元格,如果满足条件则返回一个值。

假设如下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 水平)我不知道更好的解决方案。我试过adplycombn,没有结果。

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

感谢您的帮助和赞扬。

【问题讨论】:

  • 你想达到什么目的?如果您的扩展代码解决问题的效率非常低,那么要求人们浏览您的扩展代码是不合理的。
  • 嗨@geotheory。感谢您的反馈。我明白。我想“我会展示我试图掌握这个想法的代码”。我试图通过使用两行 R-ish 中的示例来解释我想要什么。
  • 您的示例输入数据很好。也许只是给出一个输出数据格式的例子,我们可以建议使用方法

标签: r for-loop row


【解决方案1】:

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

首先,创建一个包含所有行索引组合的 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

【讨论】:

  • 弗洛德尔。谢谢你。我已经循环使用了你的建议,因为 transform 没有得到我想要的输出。
  • 谢谢@flodel。我已经循环使用了你的建议,因为 transform 没有得到我想要的输出。
【解决方案2】:

感谢@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

【讨论】:

    【解决方案3】:

    我已经设法使用此方法重现了您想要的输出:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      相关资源
      最近更新 更多