2016-01-28 41 views
1

我在R中使用data.table包,並且希望對列執行操作。具體而言,我想強制所有值都是(0,1)。使用R中的data.table將列限制到特定範圍

讓我們只用一個簡單的例子在這裏工作:

data = data.table(x = rnorm(10)) 

我的數據被存儲爲data.table所以我想,我可以做這樣的事情:

data[, newx := max(min(x, 1), 0)] 

但聚合函數(minmax)計算矢量最小值/最大值。

好了,所以我做出改變的添加​​聲明:

data[, newx := max(min(x, 1), 0), by=.I] 

但這也不管用!

使用data.table完成此類任務的正確方法是什麼?

+1

by by by = seq_along(x)' – jangorecki

回答

3

您可以創建一個虛擬的指數,它下降時不再需要它,就像這樣:

data[,Idx := .I][, newx := max(min(x, 1), 0), by = "Idx"][, Idx := NULL][] 

#    x  newx 
# 1: 1.12585452 1.0000000 
# 2: 0.82343338 0.8234334 
# 3: -1.02227889 0.0000000 
# 4: 1.42761362 1.0000000 
# 5: 0.77371518 0.7737152 
# 6: -0.22261010 0.0000000 
# 7: -0.64862015 0.0000000 
# 8: -0.45663845 0.0000000 
# 9: -0.96332902 0.0000000 
# 10: -0.04396755 0.0000000 
+1

什麼是鍊金術!?非常感謝你!但爲什麼這不適用於'by = .I'? – user12202013

+1

嗯,你可能需要深入研究'data.table'源代碼來確認,但我認爲,因爲存在'by'子句(其中'by!= .I'),它維護一個索引序列每個組,它只是沒有能力被用作分組變量本身。從幫助文件中,'.I是一個等於seq_len(nrow(x))的整數向量。分組時,它適用於組中的每個項目,它是x中的行位置。這對j中的子集很有用。例如DT [,.I [which.max(somecol)],by = grp]。' – nrussell

+0

看不到需要創建'Idx'; 'data [,newx:= max(min(x,1),0),by = seq_along(x)]'似乎工作原理相同(正如@jangorecki指出的那樣) – MichaelChirico

2

您也可以嘗試簡單ifelse

data[, newX:= ifelse(x >1,1,x)][, newX:= ifelse(x < 0, 0,x)] 
+0

這裏只需要一個'ifelse': 'ifelse(x%在%c(0,1),x,x> 0)之間''。此外,['ifelse'很慢](http://stackoverflow.com/questions/16275149/does-ifelse-really-calculate-both-of-its-vectors-every-time-is-it-slow);最好只使用三行代碼:'data [,newX:= x];數據[x <0,newX:= 0];數據[x> 1,newX:= 1]' – MichaelChirico

1

簡單和快速的將只需將其分段定義即可:

set.seed(13084) 
data = data.table(x = rnorm(10)) 
> data[ , newx := (xg1 <- x > 1) + x * (!xg1 & x > 0)][] 
      x  newx 
1: 0.7842597 0.7842597 
2: -0.3935582 0.0000000 
3: -2.3379063 0.0000000 
4: -1.7428335 0.0000000 
5: 0.1678035 0.1678035 
6: -0.9558911 0.0000000 
7: -1.5592778 0.0000000 
8: 0.9358569 0.9358569 
9: 0.7778178 0.7778178 
10: 1.0937594 1.0000000 
相關問題