0

示例数据

A<-c(1,4,5,6,2,3,4,5,6,7,8,7)
B<-c(4,6,7,8,2,2,2,3,8,8,7,8)
DF<-data.frame(A,B)

我想做的是根据B列的值对A列应用一个校正因子。规则是这样的

If B less than 4  <- Multiply A by 1
If B equal to  4 and less than 6  <- Multiply A by 2
If B equal or greater than 6 <-  Multiply by 4

我想我可以写一个“if”语句(我很高兴看到一个很好的例子),但我也有兴趣使用方括号索引来加快速度。

最终结果看起来像这样

A  B
2  4
16 6
20 7
24 8

4

3 回答 3

2

用这个:

within(DF, A <- ifelse(B>=6, 4, ifelse(B<4, 1, 2)) * A)

或者这个(由@agstudy 更正):

within(DF, {A[B>=6] <- A[B>=6]*4; A[B>=4 & B<6] <- A[B>=4 & B<6]*2})

基准测试:

DF <- data.frame(A=rpois(1e4, 5), B=rpois(1e4, 5))
a <- function(DF) within(DF, A <- ifelse(B>=6, 4, ifelse(B<4, 1, 2)) * A)
b <- function(DF) within(DF, {A[B>=6] <- A[B>=6]*4; A[B>=4 & B<6] <- A[B>=4 & B<6]*2})

identical(a(DF), b(DF))
#[1] TRUE

microbenchmark(a(DF), b(DF), times=1000)
#Unit: milliseconds
#  expr      min        lq   median        uq      max neval
# a(DF) 8.603778 10.253799 11.07999 11.923116 53.91140  1000
# b(DF) 3.763470  3.889065  5.34851  5.480294 39.72503  1000
于 2013-06-26T22:43:19.273 回答
1

类似于@Ferdinand 解决方案,但使用transform

transform(DF, newcol = ifelse(B<4,  A,
                                   ifelse(B>=6,4*A,2*A)))
      A B newcol
1  1 4      2
2  4 6     16
3  5 7     20
4  6 8     24
5  2 2      2
6  3 2      3
7  4 2      4
8  5 3      5
9  6 8     24
10 7 8     28
11 8 7     32
12 7 8     28
于 2013-06-26T22:45:58.463 回答
1

我更喜欢将findInterval其用作此类操作的一组因素的索引。具有多个调用的嵌套测试条件和结果向量的扩散ifelse冒犯了我的效率敏感性:

 DF$A <- DF$A * c(1,2,4)[findInterval(DF$B, c(-Inf,4,6,Inf) ) ]
 DF
    A B
1   2 4
2  16 6
3  20 7
4  24 8
snipped ....

基准:

DF <- data.frame(A=rpois(1e4, 5), B=rpois(1e4, 5))
a <- function(DF) within(DF, A <- ifelse(B>=6, 4, ifelse(B<4, 1, 2)) * A)
b <- function(DF) within(DF, {A[B>=6] <- A[B>=6]*4; A[B>=4 & B<6] <- A[B>=4 & B<6]*2})
ccc <- function(DF) within(DF, {A * c(1,2,4)[findInterval(B, c(-Inf,4,6,Inf) ) ]})
microbenchmark(a(DF), b(DF), ccc(DF), times=1000)
#-----------
Unit: microseconds
    expr      min        lq    median        uq      max neval
   a(DF) 7616.107 7843.6320 8105.0340 8322.5620 93549.85  1000
   b(DF) 2638.507 2789.7330 2813.8540 3072.0785 92389.57  1000
 ccc(DF)  604.555  662.5335  676.0645  698.8665 85375.14  1000

注意:如果我编写自己的函数,我不会这样做within,但考虑到对早期工作的公平性,我会将其设为 apples <-> apples。

于 2013-06-27T00:33:03.093 回答