使用data.table中的函数非常慢

wiz*_*ziw 1 optimization r data.table

显然我做得不对.这种方法有效,但很难实用.请记住,我正在使用的示例数据运行得很快,但如果您要在400k行+的DT上尝试此操作,那么您将等待一段时间.

我最初这样做是因为我可以将日期转换为财政周(周五到周四)的名字.我希望能够查看DT中的每个日期,测试它落入哪个范围,然后返回周名称.它就像一个魅力!但是,就像我说的那样,非常缓慢.

然后我认为这对于我可能需要做的任何逐行调整都是一种很好的技术,但除非我能以某种方式对其进行优化,否则我可能需要重新考虑事情......

因此,让我们使用mtcars数据集,假设我们想要查看每行中的cyl,然后将该数字转换为它的单词.

cyl.word <- function(c) {
  r <- "Huh?"
  if(c==4) {r <- "Four"}
  if(c==6) {r <- "Six"}
  if(c==8) {r <- "Eight"}
  return(r)
}
Run Code Online (Sandbox Code Playgroud)

像你期望的那样工作,如果你键入cyl.word(4)你得到"四".大.让我们在DT上应用它......

cars <- data.table(mtcars)

cars[, Word:=cyl.word(cars$cyl[.I]), by=cyl]
head(cars)

    mpg cyl disp  hp drat    wt  qsec vs am gear carb  Word
1: 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4   Six
2: 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4   Six
3: 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  Four
4: 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1   Six
5: 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 Eight
6: 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1   Six
Run Code Online (Sandbox Code Playgroud)

我认为减速显然是由[.I]引起的,但如果没有它,它似乎抓住整个cyl的向量并且只使用第一个用于函数,它们都返回"六":

cars[, Word:=cyl.word(cars$cyl), by=cyl]
head(cars)

    mpg cyl disp  hp drat    wt  qsec vs am gear carb Word
1: 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  Six
2: 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  Six
3: 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  Six
4: 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1  Six
5: 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2  Six
6: 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1  Six
Run Code Online (Sandbox Code Playgroud)

它还给了我这个错误信息:

Warning messages:
1: In if (c == 4) { :
  the condition has length > 1 and only the first element will be used
2: In if (c == 6) { :
  the condition has length > 1 and only the first element will be used
3: In if (c == 8) { :
  the condition has length > 1 and only the first element will be used
Run Code Online (Sandbox Code Playgroud)

这就是为什么我使用.I变量告诉函数看哪个迭代...

Jos*_*ien 6

使用矢量化函数match()可以大大加快计算速度:

library(data.table)
cars <- data.table(mtcars)

cyl.word <- function(x) {
    c("Four", "Six", "Eight", "Huh?")[match(x, c(4,6,8), nomatch=4)]
}
cars[, Word:=cyl.word(cyl)]

head(cars)
#     mpg cyl disp  hp drat    wt  qsec vs am gear carb  Word
# 1: 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4   Six
# 2: 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4   Six
# 3: 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  Four
# 4: 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1   Six
# 5: 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 Eight
# 6: 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1   Six
Run Code Online (Sandbox Code Playgroud)