2016-08-11 128 views
1

閾值量的支持,可以說我有一個data.table它看起來像這樣計算基於R中data.table

customer TranAmount 
1: 146506 1290.49 
2: 146506 2699.00 
3: 146506 2720.00 
4: 146506 2700.00 
5: 146506  6.35 
6: 146506 2700.00 
7: 146506 2705.00 
8: 146506 2691.00 
9: 146506  500.00 
10: 146506  500.95 
11: 146506  52.00 

現在我要計算每個量support,通過support我的意思是,如果我選擇 一筆交易,並且存在處於該交易閾值內的交易,則該交易的support等於該限額內的交易數量。

例如,在上述數據,對於TranAmount 2700.00,如果我們考慮的1%的閾值(上述2700.00或低於2700.00),那麼有該範圍內的6個交易,所以support爲TranAmount 2700.00是6

我已經寫了這個功能,但它的速度很慢,當然不是在data.table的方式,但它做的工作,我相信有更好的方法來實現這一點,但我不能想到任何。

get_support <- function(dt,val_tolerance=0.01) { 
    support_dt <- dt[,.(customer,TranAmount)][order(TranAmount)] 
    support_dt[,support:= 0] 

    for(i in 1:nrow(support_dt)) { 
     start <- support_dt[i,TranAmount] 
     current_support <- support_dt[i,support] 
     amount_limit <- c((start - start*val_tolerance),(start + start*val_tolerance)) 
     for (j in 1:nrow(support_dt)){ 
     amount <- support_dt[j,TranAmount] 
     if(between(amount,amount_limit[1],amount_limit[2]) ==TRUE){ 
      current_support <- current_support+1 
     }else{ 
      current_support <- current_support 
     } 
     } 
     #print(current_support) 
     support_dt[i,support:=current_support] 
    } 
    print(support_dt) 
} 

請建議更好的方法來實現相同。

回答

4

隨着1.9.7或更高版本,使用非相等連接條件:

vals = c(2700, 500) 

DT[.(dn = vals*0.99, up = vals*1.01), on=.(TranAmount >= dn, TranAmount <= up), 
    .N 
, by=.EACHI] 

# TranAmount TranAmount N 
# 1:  2673  2727 6 
# 2:  495  505 2 

結果中的列名是不是很直觀,但那些可能會改變。

目前(2016年8月),您需要爲此爲install the devel version

2

我得到了警告,但顯然的邏輯是合理的:

dt[ , support := ave(TranAmount, TranAmount, 
          FUN= function(x) sum(abs(x -dt$TranAmount) < 0.01*x)) ] 
#--------------------------------- 
Warning messages: 
1: In x - dt$TranAmount : 
    longer object length is not a multiple of shorter object length 
2: In abs(x - dt$TranAmount) < 0.01 * x : 
    longer object length is not a multiple of shorter object length 
> dt 
    customer TranAmount support 
1: 146506 1290.49  1 
2: 146506 2699.00  6 
3: 146506 2720.00  5 
4: 146506 2700.00  6 
5: 146506  6.35  1 
6: 146506 2700.00  6 
7: 146506 2705.00  6 
8: 146506 2691.00  5 
9: 146506  500.00  2 
10: 146506  500.95  2 
11: 146506  52.00  1 
2

這裏是一個哈克data.table解決方案,它的工作原理(有可能是一個更清潔,雖然方式)

tvals <- df$TranAmount 
pct <- 0.01 

dfDT[, id := .I][,support := sum(TranAmount*(1-pct) <= tvals & tvals <= TranAmount*(1+pct)), by = list(id)][,id:=NULL] 

編輯:一備用data.table方法

dfDT[, support := sum(TranAmount*(1-pct) <= tvals & tvals <= TranAmount*(1+pct)), by = rownames(dfDT)] 

,這裏是一個dplyr溶液

df %>% 
    group_by(rn=row_number()) %>% 
    mutate(support = sum(TranAmount*(1-pct) <= tvals & tvals <= TranAmount*(1+pct))) %>% 
    ungroup %>% 
    select(-rn) 

## customer TranAmount support 
##  <int>  <dbl> <int> 
## 1 146506 1290.49  1 
## 2 146506 2699.00  6 
## 3 146506 2720.00  5 
## 4 146506 2700.00  6 
## 5 146506  6.35  1 
## 6 146506 2700.00  6 
## 7 146506 2705.00  6 
## 8 146506 2691.00  5 
## 9 146506  500.00  2 
## 10 146506  500.95  2 
## 11 146506  52.00  1 

筆記,dfdata.frame)和dfDTdata.table)包含相同的數據。

+0

這就是真的哈克:d – Bg1850

0

下面是一個相對簡單的方式data.table

x[, support := x[abs(TranAmount- .SD[,TranAmount]) < 0.01*.SD[,TranAmount] , .N], 
    by=1:NROW(x)] 

# customer TranAmount support 
# 1: 146506 1290.49  1 
# 2: 146506 2699.00  6 
# 3: 146506 2720.00  5 
# 4: 146506 2700.00  6 
# 5: 146506 6.35  1 
# 6: 146506 2700.00  6 
# 7: 146506 2705.00  6 
# 8: 146506 2691.00  5 
# 9: 146506 500.00  2 
#10: 146506 500.95  2 
#11: 146506 52.00  1 

數據:

x = data.table(customer=rep(146506,11), 
       TranAmount=c(1290.49, 2699.00, 2720.00, 2700.00, 6.35, 2700.00, 
          2705.00, 2691.00, 500.00, 500.95, 52.00))