将向量中的值与所有其他向量进行比较

时间:2016-02-16 14:03:59

标签: r

让我们假设以下数据集:

+---------------+-----------+---------------------+
| flightCarrier | saleTotal | daysBeforeDeparture |
+---------------+-----------+---------------------+
| KL            | 477.99    |                   0 |
| AF            | 457.99    |                   0 |
| SQ            | 556.31    |                   0 |
+---------------+-----------+---------------------+

我想做的是以下内容:

  1. 将列中的值与同一列中的所有其他值进行比较。
  2. saleTotal(1)是否小于saleTotal(2)和saleTotal(3)
  3. 的值
  4. 如果是,请拨多少钱? saleTotal(3)/ saleTotal(1)
  5. 工单

    • 477,99< 457,99(假)
    • 477,99< 556.31(真) - > (556.31 / 477.99)-1 = 1.16(增加16%)
    • 457.99< 477.99(真) - > .....
    • 457.99< 556.31(真) - > .....
    • 556.31< 477.99(假)
    • 556.31< 457.99(假)

    到目前为止我尝试了什么:

    cal <- apply(df_matrix[1:2,2], 1, function(x) {
      A <- x
      x <- x[-1]
      ifelse(x>A, 1, ifelse(x<A, 0, NA))
    })
    cal
    

    这没有成功并打印出“逻辑(0)”所以我猜没有结果。 我尝试了许多方法,使用lapply,mapply,但似乎所有人都比较静态数字而不是之前的行。

    我从申请中得到的是,每一个X都有一行“迭代”。这就是为什么我试图比较X&gt; A而A是具有所有saleTotal值的整个矢量。因此,迭代每一个。

    预期输出 业务输出:“价格比XY其他价格便宜”

    我想这是避免使用大型矩阵并尽可能降低内存的最佳方法 有没有办法直接“nrow()”结果而不是先创建矩阵/列表?

    +-----------+-------------+
    | saleTotal | cheaperThan |
    +-----------+-------------+
    | 477.99    |           1 |
    | 457.99    |           2 |
    | 556.31    |           0 |
    +-----------+-------------+
    

    知道怎么做吗?性能怎么样,我有100000多行?

    编辑:预期输出(单向)

2 个答案:

答案 0 :(得分:5)

您可以像这样使用?outer

outer(df$saleTotal, df$saleTotal, "/")
#          [,1]     [,2]      [,3]
#[1,] 1.0000000 1.043669 0.8592152
#[2,] 0.9581581 1.000000 0.8232640
#[3,] 1.1638528 1.214677 1.0000000

值大于1表示增加,小于1的值表示减少,矩阵的对角线全部为1,因为它将每个值与自身进行比较。

当然,您可以将其修改为仅显示大于1的值,例如使用:

res <- outer(df$saleTotal, df$saleTotal, "/")
res * as.integer(res > 1)
#         [,1]     [,2] [,3]
#[1,] 0.000000 1.043669    0
#[2,] 0.000000 0.000000    0
#[3,] 1.163853 1.214677    0

或者,如果你只想要一个逻辑矩阵:

res > 1
#      [,1]  [,2]  [,3]
#[1,] FALSE  TRUE FALSE
#[2,] FALSE FALSE FALSE
#[3,]  TRUE  TRUE FALSE

答案 1 :(得分:5)

请参阅最后关于效率的说明

根据您的预期输出,您可以迭代每个值并计算(TRUE值的总和)此值比其他所有值便宜多少时间,并将列表返回到&#39;对&#39;计数值:

sapply(data[,2],function(x) {
  list(x, sum(x < data[,2]))
})

以长格式提供:

     [,1]   [,2]   [,3]  
[1,] 477.99 457.99 556.31
[2,] 1      2      0     

如果您只想在现有数据集中添加一列,则应执行以下操作:

data$cheaperThan <- sapply(data[,2],function(x) sum(x < data[,2])) 

使用的数据:

> system.time(sapply(large,function(x) sum(x < large)))
utilisateur     système      écoulé 
       1.08        0.22        1.30 
> system.time(length(large) - findInterval(large,sort(large)))
utilisateur     système      écoulé 
       0.01        0.00        0.01 

@alexis_laz解决方案,如果确实真的更有效:

> set.seed(123)
> test <- runif(50000)*100
> identical(sapply(test,function(x) sum(x < test)), (length(test) - findInterval(test,sort(test))))
[1] TRUE
> system.time(sapply(test,function(x) sum(x < test)))
utilisateur     système      écoulé 
      13.64        1.24       14.96 
> system.time(length(test) - findInterval(test,sort(test)))
utilisateur     système      écoulé 
       0.01        0.00        0.02