因此,我们习惯于对每个R新用户说" apply没有矢量化,请查看Patrick Burns R Inferno Circle 4 ",其中说(我引用):
常见的反射是使用apply系列中的函数.这不是 矢量化,而是循环隐藏.apply函数在其定义中有一个for循环.lapply函数掩盖了循环,但执行时间往往大致等于显式for循环.
实际上,快速查看apply源代码会显示循环:
grep("for", capture.output(getAnywhere("apply")), value = TRUE)
## [1] " for (i in 1L:d2) {" " else for (i in 1L:d2) {"
Run Code Online (Sandbox Code Playgroud)
好到目前为止,但看看lapply或vapply实际上揭示了一个完全不同的图片:
lapply
## function (X, FUN, ...)
## {
## FUN <- match.fun(FUN)
## if (!is.vector(X) || is.object(X))
## X <- as.list(X)
## .Internal(lapply(X, FUN))
## }
## <bytecode: 0x000000000284b618>
## <environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
所以显然没有R for环隐藏在那里,而是他们调用内部C编写的函数.
此外,让我们以 …
我希望(1)通过一个变量()分组数据State,(2)在每个组内找到另一个变量(Employees)的最小值行,以及(3)提取整行.
(1)和(2)是简单的单行,我觉得(3)也应该是,但我不能得到它.
这是一个示例数据集:
> data
State Company Employees
1 AK A 82
2 AK B 104
3 AK C 37
4 AK D 24
5 RI E 19
6 RI F 118
7 RI G 88
8 RI H 42
data <- structure(list(State = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L), .Label = c("AK", "RI"), class = "factor"), Company = structure(1:8, .Label = c("A",
"B", "C", "D", "E", "F", "G", "H"), class = "factor"), Employees …Run Code Online (Sandbox Code Playgroud) 假设我有一个包含一些棒球运动员的数据表:
library(plyr)
library(data.table)
bdt <- as.data.table(baseball)
Run Code Online (Sandbox Code Playgroud)
对于每个玩家(由id给出),我想找到与他们玩最多游戏的年份相对应的行.这在plyr中很简单:
ddply(baseball, "id", subset, g == max(g))
Run Code Online (Sandbox Code Playgroud)
data.table的等效代码是什么?
我试过了:
setkey(bdt, "id")
bdt[g == max(g)] # only one row
bdt[g == max(g), by = id] # Error: 'by' or 'keyby' is supplied but not j
bdt[, .SD[g == max(g)]] # only one row
Run Code Online (Sandbox Code Playgroud)
这有效:
bdt[, .SD[g == max(g)], by = id]
Run Code Online (Sandbox Code Playgroud)
但它比plyr快30%,这表明它可能不是惯用语.
我写了一个(相当幼稚的)函数来随机选择两个指定日期之间的日期/时间
# set start and end dates to sample between
day.start <- "2012/01/01"
day.end <- "2012/12/31"
# define a random date/time selection function
rand.day.time <- function(day.start,day.end,size) {
dayseq <- seq.Date(as.Date(day.start),as.Date(day.end),by="day")
dayselect <- sample(dayseq,size,replace=TRUE)
hourselect <- sample(1:24,size,replace=TRUE)
minselect <- sample(0:59,size,replace=TRUE)
as.POSIXlt(paste(dayselect, hourselect,":",minselect,sep="") )
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
> rand.day.time(day.start,day.end,size=3)
[1] "2012-02-07 21:42:00" "2012-09-02 07:27:00" "2012-06-15 01:13:00"
Run Code Online (Sandbox Code Playgroud)
但随着样本量的增加,这似乎在大幅放缓.
# some benchmarking
> system.time(rand.day.time(day.start,day.end,size=100000))
user system elapsed
4.68 0.03 4.70
> system.time(rand.day.time(day.start,day.end,size=200000))
user system elapsed
9.42 0.06 9.49
Run Code Online (Sandbox Code Playgroud)
有人能够以更有效的方式建议如何做这样的事情吗?
我对使用.SD和不太清楚by.
例如,做下面的代码片段意思是:"改变所有的列DT到的因素,除了A与B?" 它还在data.table手册中说:" .SD指data.table每个组的子集(不包括分组列)" - 所以列A和B排除?
DT = DT[ ,lapply(.SD, as.factor), by=.(A,B)]
Run Code Online (Sandbox Code Playgroud)
但是,我也读过,by当你进行聚合时,这意味着在SQL中使用'group by'.例如,如果我想colsum在除了所有列之外总结(比如在SQL中)A并且B我仍然使用类似的东西吗?或者在这种情况下,下面的代码是否意味着在列A和B?中取总和和值组?(A,B在SQL中使用sum和group by )
DT[,lapply(.SD,sum),by=.(A,B)]
Run Code Online (Sandbox Code Playgroud)
然后我如何做colsum除了A和之外的所有列的简单B?
我在不同的s 和不同的s 中观察users ,并且可能会多次看到它们,如下所示:timesituation
df <- data.table(time = c(1,1,1,2,2),
user = c(1,1,2,1,2),
situation = c(1,1,1,2,2),
observation = c(1,2,1,1,1))
Run Code Online (Sandbox Code Playgroud)
我想做的是使用 来计算每个时间段内user-s的数量。预期输出:situationdata.table
result <- data.table(time = c(1,2),
user_situations = c(2,2))
Run Code Online (Sandbox Code Playgroud)
我知道我可以以连锁方式做到这一点:
unique(df[, .(time, user, situation)])[, .(user_situations = .N), .(time)]
Run Code Online (Sandbox Code Playgroud)
但想知道是否有一种简单的方法可以一次性完成此操作。