for循环的更快替代品

时间:2018-04-23 10:57:58

标签: r performance for-loop model.matrix

我有以下问题:

我的数据框看起来如下,即使它更大(20GB):

Letters <- c("A","B","C")
Numbers <- c(1,0,1)
Numbers <- as.integer(Numbers)

Data.Frame <- data.frame(Letters,Numbers)

现在我想为字母创建一个虚拟变量并编写以下for循环:

for(level in unique(Data.Frame$Letters)){Data.Frame[paste("", level, sep = "")]
<- ifelse(Data.Frame$Letters == level, 1, 0)}

因为我的数据帧太大,但执行时间很长。我尝试的另一种可能的解决方案是:

factors <- model.matrix(~Letters-1, data=Data.Frame)
cbind(Data.Frame, factors)

结果是一样的,但是当我在更大的数据框架上使用它时,它需要更长的时间。

是否有任何可能的替代方案,这将导致相同的解决方案并且计算速度更快?

非常感谢您提前!

3 个答案:

答案 0 :(得分:1)

如果你有足够的内存,你可以试试这个:

n <- 18e6
set.seed(31)
d <- data.frame(Letters = as.factor(sample.int(1.3e4, n, replace = T)),
                Numbers = sample.int(30, n, replace = T))
require(data.table)
dt <- as.data.table(d)
x2 <- as.integer(dt$Letters)
ilist <- unique(x2)[1:20] # for test 20 cols
for (i in ilist) {
  set(dt, j = as.character(i), value = (x2 == i) + 0L)
}

否则,您应该按照其他用户的建议使用稀疏矩阵:

require(Matrix)
dd <- sparse.model.matrix(~ Letters - 1, data = d)
dd[1:5, 1:5]
# 5 x 5 sparse Matrix of class "dgCMatrix"
#   Letters1 Letters2 Letters3 Letters4 Letters5
# 1        .        .        .        .        .
# 2        .        .        .        .        .
# 3        .        .        .        .        .
# 4        .        .        .        .        .
# 5        .        .        .        .        .

答案 1 :(得分:1)

您可以使用dcast.data.table包中的data.table

dt <- data.table(Letters,Numbers)
dcast.data.table(dt, Letters+Numbers~Letters,fun.aggregate=length)

   Letters Numbers A B C
1:       A       1 1 0 0
2:       B       0 0 1 0
3:       C       1 0 0 1

答案 2 :(得分:-1)

data.table可能更快?

怎么样?
Letters <- c("A","B","C","C")
Numbers <- c(1,0,1,2)
Numbers <- as.integer(Numbers)
Data.Frame <- data.frame(Letters,Numbers)
library(data.table)
DT <- as.data.table(Data.Frame)
Letters <- unique(DT$Letters)
for(l in Letters){
  DT[, (l):=as.integer(Letters==l)]
}


> DT
   Letters Numbers A B C
1:       A       1 1 0 0
2:       B       0 0 1 0
3:       C       1 0 0 1
4:       C       2 0 0 1