循环在R中占用太多时间?

时间:2018-04-11 05:58:50

标签: r

背景:

查看公司在市场资本化方面同步移动的次数,例如,对于公司A和公司B,他们一起移动3次,当公司A和B显示的值不同于NA时,我想将其分开(这里,10)。我使用了一个逻辑公式,当它们具有相同的字母时为TRUE,当它们没有相同的字母时为FALSE,当A或B中有一个NA值时为NA。

问题是:

我使用的代码适用于小型套装,最多50家公司,然后需要花费太多时间,我希望能够为100家公司提供服务。 324.000.000数据点

输入(小子集):Dataframe" dat"

           CompA CompB CompC CompD 
    1         A    F <NA>    A
    2         A    F <NA>    F
    3         F    E <NA>    A
    4         A    A <NA>    A
    5         F    A <NA>    F
    6         A    D <NA>    D
    7         F    F <NA>    B
    8         A    A <NA>    F
    9         F    E <NA>    F
    10       <NA>  C <NA>    A
    11        E    F <NA>    E

使用的代码:

  v <- NULL
  i <- 1
  j <- 1

  for(i in 1:length(dat)-1){

  j <- i+1
    while(j <= length(dat)-1){
  str(dat)

       qone <- data.frame(qone = 
         (as.character(dat[,i+1])==as.character(dat[,j+1])))

     count1 <- length(which(qone == TRUE))/(length(which(qone == 
  TRUE))+length(which(qone == FALSE)))

    v <- append(v, count1)
   v <- data.frame(v)

   j <- j+1
   }}

最终输出:

        x1     x2     x3    x4     x5    x6
    1   0.3    NA     0.5   NA    0.27   NA

第二个最终输出: 1 Nb TRUE 2 Nb FALSE

         x1     x2     x3    x4     x5    x6
    1     3    0       5     0      3     0
    2     7    0       6     0      8     0

1 个答案:

答案 0 :(得分:1)

在R中使用循环通常效率低下。由于您在嵌套循环中增加了数据框,因此它会严重减慢速度

尝试以下方法:

.as-console-wrapper { top: 0; max-height: 100% !important; }

我尝试创建一个包含~200,000行和~80列的虚拟数据框并运行上面的代码,在普通笔记本电脑上花了近一分钟。

有关所用功能的更多信息:

第一个library(data.table) #Create the dummy data companyData <- fread("~/test_data.csv",sep = "\t",na.strings = "<NA>") #Two apply function to cross-over other columns over each column v <- lapply(companyData, function(leftcomp) { lapply(companyData, function(rightcomp) { mean(leftcomp == rightcomp, na.rm = T) })}) #Unlist data to get n*n vector which has all the values results <- unlist(v) #Some logic to collect the required elements only. l <- length(companyData) a <- 1:(l*l) b <- rep(seq(1,l*l,by = l+1),times = rep(l,times = l)) log_vec <- a > b # # > log_vec # [1] FALSE TRUE TRUE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE final_result <- results[log_vec] # > final_result # CompA.CompB CompA.CompC CompA.CompD CompB.CompC CompB.CompD CompC.CompD # 0.3000000 NaN 0.5000000 NaN 0.2727273 NaN 占据lapply的每一列,并传递给第二个companyData。此列再次与lapply的每列进行比较。

companyData mean(leftcomp == rightcomp, na.rm = T)在公司串联的地方给出了leftcomp == rightcomp的逻辑向量。当任何列为TRUE时,它会返回NA

现在,在忽略NA之后,此逻辑向量的mean将给出我们的比率。这是有效的,因为NA基本上为1,而TRUE在R中为0。

例如:

FALSE

>log_vec [1] TRUE FALSE FALSE FALSE NA TRUE 返回2/5 = 0.4。

现在,您想要选择唯一的元素(CompA vs CompB但不是CompB vs CompA)。

为此,

如果mean(log_vec,na.rm = T)是您正在查看的公司数量(例如,4),则l会创建上述所有计算a <- 1:(l*l)的索引。

lapply

> a [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 是一个向量,如下所示:

b

此向量的> b [1] 1 1 1 1 6 6 6 6 11 11 11 11 16 16 16 16 log_vec <- a > b > log_vec [1] FALSE TRUE TRUE TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE 表示您需要选择的元素。

希望,现在更清楚了。