假设我有data.table一些列:
a <- data.table(id=1:1000, x=runif(100), y=runif(100), z=runif(100))
Run Code Online (Sandbox Code Playgroud)
我要删除的行,其中x,y或者z是低于中位数:
a <- a[ x > median(x) & y > median(y) & z > median(z) ]
Run Code Online (Sandbox Code Playgroud)
(旁边:上面的电话是median3次还是3000次?)
我做的是
my.cols <- c("x","y","z")
my.meds <- sapply(my.cols, function(n) median(a[[n]]))
a <- a[ Reduce(`&`,Map(function(i) a[[my.cols[i]]] > my.meds[i], 1:length(my.cols))) ]
Run Code Online (Sandbox Code Playgroud)
这是我能做的最好的吗?
当您发现自己遍历列时,通常长格式可以更容易.所以只是为了在这种情况下显示该选项,尽管它并不好.
以下内容并不快,因为它使用[on .SD.但无论如何,这是逻辑,因为当我们进行优化时.SD[...].
> a
id x y z
1: 60 0.006884017 0.9159115 0.876148
2: 160 0.006884017 0.9159115 0.876148
3: 260 0.006884017 0.9159115 0.876148
4: 360 0.006884017 0.9159115 0.876148
5: 460 0.006884017 0.9159115 0.876148
---
996: 504 0.990417986 0.7167666 0.751991
997: 604 0.990417986 0.7167666 0.751991
998: 704 0.990417986 0.7167666 0.751991
999: 804 0.990417986 0.7167666 0.751991
1000: 904 0.990417986 0.7167666 0.751991
> require(reshape2) # but data.table v1.8.11 has a fast melt built-in
> DT = as.data.table(melt(a, "id")) # copies here => bad
> DT
id variable value
1: 60 x 0.006884017
2: 160 x 0.006884017
3: 260 x 0.006884017
4: 360 x 0.006884017
5: 460 x 0.006884017
---
2996: 504 z 0.751991033
2997: 604 z 0.751991033
2998: 704 z 0.751991033
2999: 804 z 0.751991033
3000: 904 z 0.751991033
Run Code Online (Sandbox Code Playgroud)
现在数据是长格式的(首先它可以是长格式吗?),下面的步骤更容易:
> DT[, below:=value<median(value), by=variable]
> DT
id variable value below
1: 60 x 0.006884017 TRUE
2: 160 x 0.006884017 TRUE
3: 260 x 0.006884017 TRUE
4: 360 x 0.006884017 TRUE
5: 460 x 0.006884017 TRUE
---
2996: 504 z 0.751991033 FALSE
2997: 604 z 0.751991033 FALSE
2998: 704 z 0.751991033 FALSE
2999: 804 z 0.751991033 FALSE
3000: 904 z 0.751991033 FALSE
> DT[below==TRUE, .SD[.N==3], by=id]
id variable value below
1: 88 x 0.01873885 TRUE
2: 88 y 0.05834677 TRUE
3: 88 z 0.08973225 TRUE
4: 188 x 0.01873885 TRUE
5: 188 y 0.05834677 TRUE
---
356: 848 y 0.39433186 TRUE
357: 848 z 0.14152092 TRUE
358: 948 x 0.48932049 TRUE
359: 948 y 0.39433186 TRUE
360: 948 z 0.14152092 TRUE
Run Code Online (Sandbox Code Playgroud)
dcast如果它需要宽,那就回来了.但我试着把事情做好,就像数据库一样.
可能有更直接的方法来做到这一点,也许是一种避免.SD[...]速度的方法.
旁白:我想到setkey(a,x)了上半场.这适用于一列.但是第二个需要y<median(y)在median(y)所有的位置a,所以你不能只是在上半部分由y设置,然后再设置一半,并且因为这个原因再次为z设置一半.但是,如果这样的事情是可能的,那将是非常专业的,median这只是我假设的问题中的一个说明性例子.
一种选择是构造您想要的字符串eval/parse:
EVAL = function(...)eval(parse(text=paste0(...))) # standard helper function
a[ EVAL(my.cols, ">median(", my.cols, ")", collapse=" & ") ]
Run Code Online (Sandbox Code Playgroud)