条件求和(R)

时间:2010-12-06 07:57:39

标签: r conditional sum

我正在尝试创建条件和,以便计算平均值。这个想法是函数(或apply语句)检查某个值是否为真(例如x> 0),然后将x的所有值加到大于零的位置。最后一步是将此总和除以大于零的实例数。搜索条件总和(ming)并没有给我提供有用的信息。

这是数据的一部分:

> tmpData
   Instrument TradeResult.Currency.
1         JPM                    -3
2         JPM                   264
3         JPM                   284
4         JPM                    69
5         JPM                   283
11        KFT                    -8
12        KFT                   -48
13        KFT                   125
14        KFT                  -150
15        KFT                  -206
16        KFT                   107

我尝试过的功能中,以下是最有希望的:

avgProfit <- function(x) {
    ifelse(x > 0,
    sum(x) / length(which(x > 0)),
    return(0))
    }

但是,此函数的输出为0:

> with(tmpData, tapply(TradeResult.Currency., Instrument, avgProfit))
JPM KFT 
  0   0     
> avgProfit(tmpData$TradeResult.Currency.)
[1] 0
> x
 [1] 1 1 2 1 2 3 3 3 4 4

(JPM的值应为225(总计900除以4个大于零的实例)和KFT的116个

即使我在函数中计算x的总和(如果我理解正确,应该是data.frame中各个值的总和),变量'x'的输出让我感到困惑。我找不到这些1,2,3和4的来源。

如何计算条件和?此外,我是否需要使用一个函数,或者我是否使它太复杂(可能有一个内置的R函数,我忽略了它?)

任何想法都非常受欢迎,

此致

6 个答案:

答案 0 :(得分:9)

可能很容易先丢弃未使用的行然后聚合它们:

aggregate(TradeResult.Currency.~Instrument,
  mean,
  data=subset(tmpData,TradeResult.Currency.>0))

答案 1 :(得分:5)

你几乎就在那里,我认为ifelse是错误的方向,因为你想要平均值,而不是元素明智的比较。

您需要考虑是否可能遇到缺失值,以便正确处理。

tmpData <- read.table(textConnection("  Instrument TradeResult.Currency.
1         JPM                    -3
2         JPM                   264
3         JPM                   284
4         JPM                    69
5         JPM                   283
11        KFT                    -8
12        KFT                   -48
13        KFT                   125
14        KFT                  -150
15        KFT                  -206
16        KFT                   107"))



with(tmpData, tapply(TradeResult.Currency., Instrument, function(x) mean(x[x > 0])))

JPM KFT 225 116

答案 2 :(得分:4)

最近有很多这些数据聚合/条件分析问题。看到使用的不同方法总是很有趣。我想我会使用plyr添加一种方法。我喜欢plyr函数,因为它们为所有函数提供标准语法,并允许您指定输入和输出的结构。在这里,我们将使用ddply,因为我们传递的是data.frame,并希望data.frame在另一侧退出。我们使用summarise函数计算值为正的每个工具的平均值。

library(plyr)
ddply(tmpData, .(instrument), summarise, avgProfit = mean(TCurr[TCurr > 0]))

为了跟进@Joris的性能比较,ddply似乎也表现得好,如果不比其他方法更好:

> tmpData <- data.frame(
+      instrument = rep(c("JPM","KFT"),each=10e6),
+      TCurr = runif(20e6,-10,100)
+  )
> 
>  system.time(
+ ddply(tmpData, .(instrument), summarise, avgProfit = mean(TCurr[TCurr > 0]))
+  )
   user  system elapsed 
   4.43    0.89    5.32 
>  
>  avgProfit <- function(x) { mean(x[x>0])}
>  
>  system.time(
+ with(tmpData,tapply(TCurr,instrument,avgProfit))
+ )
   user  system elapsed 
   7.88    0.47    8.36 
>  
> system.time(
+ aggregate(TCurr~instrument,mean,data=subset(tmpData,TCurr>0))
+ )
   user  system elapsed 
  28.29    2.35   30.65 

答案 3 :(得分:2)

聚合是最简单的方法,但我不同意“更干净,因为你不必编写自定义函数”。定义一些明确的功能时,可读性会提高。特别是如果您在脚本中需要平均几次。

聚合比你的自定义函数快一点,因为你忘记了索引。你想这样做:

avgProfit <- function(x){
  mean(x[x>0])
}

由于缺乏开销,这比聚合更快:

> tmpData <- data.frame(
+     instrument = rep(c("JPM","KFT"),each=10000),
+     TCurr = runif(20000,-10,100)
+ )

> system.time(
+   with(tmpData,tapply(TCurr,instrument,avgProfit)))
   user  system elapsed 
   0.02    0.00    0.02 

> system.time(
+   aggregate(TCurr~instrument,mean,data=subset(tmpData,TCurr>0)))
   user  system elapsed 
   0.09    0.00    0.10 

在大多数情况下,你可以忽略这种差异。在巨大的数据集(n> 100,000)上,你会开始感受到它,特别是如果你需要为一整套变量做这件事。

编辑:刚刚看到mdsummer在输出之间整齐地隐藏了完全相同的解决方案:-)。我将此作为时间参考。

答案 4 :(得分:1)

对此有一种非常简单快速的data.table方法:

library(data.table)

setDT(dt)[, .(avg = mean(TradeResult.Currency.[which(TradeResult.Currency.>0 )])), by= Instrument]

#    Instrument avg
# 1:        JPM 225
# 2:        KFT 116

<强>基准: 使用@Joris和@ Chase的性能比较,此解决方案几乎比ddply方法快五倍,比aggregate方法快40倍。

tmpData <- data.frame(
        instrument = rep(c("JPM","KFT"),each=10e6),
        TCurr = runif(20e6,-10,100))

system.time( ddply(tmpData, .(instrument), summarise, avgProfit = mean(TCurr[TCurr > 0]))  )
# user  system elapsed 
# 1.41    0.62    2.03 

system.time( setDT(tmpData)[, .(avg = mean(TCurr[which(TCurr>0 )])), by= instrument]  )
# user  system elapsed 
# 0.36    0.18    0.43

system.time( aggregate(TCurr~instrument, mean, data=subset(tmpData,TCurr>0)) )
#  user  system elapsed 
# 16.07    1.81   17.20 

答案 5 :(得分:-1)

我可能只是从迭代风格中解决这个问题。有一个名为'accumulator'或其他的局部变量,循环遍历列表中的所有元素,并且有一个if块类似

if (x[index] > 0)
    accumulator = accumulator + x[index]

并在完成后返回累加器的值。

相关问题