2016-02-05 68 views
1

给定一个数据帧象下面这样:条件矢量

set.seed(123) 
df1 <- data.frame(V1=sample(c(0,1,2),100,replace=TRUE), 
    V2=sample(c(2,3,4),100,replace=TRUE), 
    V3=sample(c(4,5,6),100,replace=TRUE), 
    V4=sample(c(6,7,8),100,replace=TRUE), 
    V5=sample(c(6,7,8),100,replace=TRUE)) 

我要总结的每一行,从第一列开始具有值> = 2,并用具有值> 6列结束,否则总和直到行的末尾。

我将如何做到这一点的矢量时尚?

更新:这不是任何家庭作业。我只想要更多可以学习和学习的向量化代码的例子。我不得不像上面那样做一些事情,但是无法弄清楚这个特定任务的apply语法,并使用for循环。

+0

我不明白,这两个密切票,但也许这关系到你最后一句这要求外部资源(我删除)。我也怀疑这个问题从根本上说不是一个向量化提供很多希望的任务。你真的应该描述潜在的任务(至少如果它不只是CS硬件问题)。 –

回答

0

我相信有更优雅的方式但蛮力方法,您可以编写一个函数,并把它传递给应用。

首先,定义您的示例数据

df <- data.frame(V1=sample(c(0,1,2),100,replace=TRUE), 
       V2=sample(c(2,3,4),100,replace=TRUE), 
       V3=sample(c(4,5,6),100,replace=TRUE), 
       V4=sample(c(6,7,8),100,replace=TRUE), 
       V5=sample(c(6,7,8),100,replace=TRUE)) 

编写将定义条件语句的功能。使用它返回矢量中条件的位置。第一次使用“开始”时拉动了第一次出现的情况的位置,因此括号使用[1]。由于最终职位有多种可能的结果,我使用if语句来实现它。如果没有满足“结束”条件> 6的值,则将变量分配给矢量的最后一个位置,否则该位置满足条件。然后,根据要使用求和进行评估的开始和结束值,只需对矢量进行子集即可。

sum.col <- function(x) { 
    start <- which(x >= 2)[1] 
    end <- which(x > 6) 
    if(length(end) == 0) { 
     end <- length(x) 
    } else { 
     end <- end[length(end)] 
    } 
    return(sum(x[start:end])) 
} 

现在我们可以通过应用函数来处理每行的向量化。

apply(df, FUN=sum.col, MARGIN = 1) 
+1

'apply'函数不是矢量化的。这只是一个伪装的“循环”。 –

3

这是出现了最R类似的方法,但我不认为这是“矢量”在长期中的R含义:

apply(df1, 1, function(x) sum(x[which(x>=2)[1]: min(which(x>6)[1], 5, na.rm=TRUE)])) 
#--------- 
    [1] 15 22 16 19 17 17 23 21 14 13 18 13 16 23 15 18 16 21 16 19 17 23 21 18 
[25] 21 24 15 20 15 18 17 24 19 18 19 15 18 17 15 17 14 21 13 19 15 15 15 15 
[49] 21 19 21 15 17 18 14 17 15 16 22 16 23 22 17 21 17 16 23 23 16 14 18 13 
[73] 18 15 17 17 17 20 20 16 17 16 16 16 14 16 20 23 23 24 14 18 16 17 22 23 
[97] 23 19 20 17 
+0

对不起。我在测试中使用了一个较小的示例,因此我将在示例提供的测试中添加输出。 –

+0

我没有保证第二列始终是'> = 2',但我想这个例子是真的。也许这只是一个CS硬件问题,我们应该注意到这一点和终止条件。 –

+0

是的,这是一个比我的更好的一般答案 - 如果条件或抽样变化,你的问题很容易解决,我的不是那么多。 – jeremycg

2

由于你的采样结构,我们可以矢量化很容易。

我们知道,只有第一列可以大于2更小,并且因此排除了,而且V2,V3和V4必须包括在内,因为它们或者是低于6,或第一非六列。塔V5被排除,仅当列V4高于6.

所以:

(df1$V1 == 2) * df1$V1 + df1$V2 + df1$V3 + df1$V4 + df1$V5 * !(df1$V4 > 6) 

    [1] 15 22 16 19 17 17 23 21 14 13 18 13 16 23 15 18 16 21 16 19 17 23 21 18 21 24 15 20 15 18 17 24 19 18 
[35] 19 15 18 17 15 17 14 21 13 19 15 15 15 15 21 19 21 15 17 18 14 17 15 16 22 16 23 22 17 21 17 16 23 23 
[69] 16 14 18 13 18 15 17 17 17 20 20 16 17 16 16 16 14 16 20 23 23 24 14 18 16 17 22 23 23 19 20 17 

是您的矢量计算。这显然比这里的其他答案少一般,但适合你的问题。

1

使用apply将是最明智的解决办法。然而,由于我们似乎对谁可以回答这个问题,而不使用基于R-循环竞争,我冒昧地提出这个

m<-as.matrix(df1) 
start<-max.col(m>=2,ties="first") 
end<-max.col(`[<-`(m>6,,ncol(m),TRUE),ties="first") 
i<-t(matrix(1:ncol(m),nrow=ncol(m),ncol=nrow(m))) 
rowSums(m*(i>=start & i<=end)) 

输出是一样的theseanswres