2016-01-28 95 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 
相关问题