使用更快的方式在R中为不同id的列计算特征数量。

45 浏览
0 Comments

使用更快的方式在R中为不同id的列计算特征数量。

我正在尝试在R中处理一个大小为20GB的数据文件。我有16GB的RAM和i7处理器。我正在使用以下代码读取数据:

y<-read.table(file="sample.csv", header = TRUE, sep = ",", skip =0, nrows =50000000)

数据集'y'如下所示:

id    feature
21    234
21    290
21    234
21    7802
21    3467
21    234
22    235
22    235
22    1234
22    236
22    134
23    9133
23    223
23    245
23    223  
23    122
23    223 

所以上面是一个示例数据集,显示了一个特定id的不同特征。我想要计算另一个数据集x中的某个特征在y中的id中出现了多少次。

数据集x如下所示:

id    feature
   21      234
   22      235
   23      223

我想要的最终输出如下所示:

 id    feature_count
   21      3
   22      2
   23      3

正如我们所看到的,234在21中出现了3次,235在22中出现了2次,223在23中出现了2次。

为此,我尝试获取新id开始的位置:(例如对于上面的示例,第1个、第7个和第12个位置),然后使用for循环计算一个特征,如下所示:

获取不同id的位置

positions=0
positions[1]=1
j=2
for(i in 1:50000000){
    if(y$id[i]!=y$id[i+1]){
    positions[j]=i+1
    j=j+1
  }
}

由于数据量很大,循环需要很长时间。(对于5000万行,上述配置的电脑需要321秒,而我有3亿行)。

计算与给定特征匹配的特征数量。(x是上述指定的数据框,用于将特征与y中的特征进行匹配。匹配成功时,feature_count递增)

for(i in 1 :length(positions)){
  for(j in positions[i]:positions[i+1]){
    if(y$feature[j]==x$feature[i]){         
       feature_count[i]=feature_count[i]+1
    }
  }
}

是否有R函数可以在更快的时间内同时完成此任务?

此外,使用"positions[i]:positions[i+1]"递增for循环会出现错误,提示在for循环中有NA参数。请建议正确的做法。

0
0 Comments

问题的出现原因是需要统计不同id在列中的计数特征,但是当前的方法效率较低。解决方法是使用R语言中的apply函数结合table函数和sign函数实现更快的统计。

具体的解决方法如下:

apply(sign(table(y)), 1, sum)

首先,使用table函数统计y向量中各个元素出现的频次,得到一个包含频次信息的表格。然后,使用sign函数将表格中的非零元素转化为1,零元素仍为0。接着,使用apply函数对表格的每一行进行操作,使用sum函数对每一行进行求和,得到不同id在列中的计数特征。

通过这种方法,可以更快速地统计不同id在列中的计数特征,提高程序的效率。

0
0 Comments

在这篇文章中,问题的原因是作者想要以更快的方式计算具有不同id的列的特征数量。作者提到了使用"data.table"包中的".N"函数可以解决这个问题。

文章中给出了一个示例数据集,并展示了如何使用"data.table"来计算每个唯一特征的数量。如果只想计算每个id的第一个特征的数量,可以使用另一种方法。还提到了如何找到每个id中最常出现的特征。

作者在文章中也提到了使用"merge"和"aggregate"函数来解决这个问题。使用"data.table"的方法可以更快地完成这些操作。

在文章的最后,还有一些关于学习如何编写这些命令的资源,包括"data.table"包的官方文档和示例代码。

此外,也提到了在使用嵌套的for循环时可能会出现的错误,建议避免使用for循环来处理大型数据集,因为它可能会导致内存问题。建议使用"data.table"包中的函数来处理数据,因为它可以更有效地处理大型数据集。

总之,这篇文章介绍了一个关于在R中以更快的方式计算具有不同id的列的特征数量的问题,并提供了使用"data.table"包来解决这个问题的示例代码和方法。同时还提到了一些关于学习如何编写这些命令的资源和建议避免使用for循环处理大型数据集的问题。

0
0 Comments

在R中,有一个问题是需要对不同id的列进行计数。根据提供的代码,问题的出现原因是由于数据量较大(20GB),而内存容量较小(16GB),无法一次性读取整个文件并进行计数。因此,需要采取一种更快的方法来处理数据。

为了解决这个问题,可以使用data.table包,其中的fread函数非常快速。可以设置一个循环,循环读取文件的块并存储特征计数的总和。下面是一个适用于文件循环的函数的部分代码:

require(data.table)
LineNu <- as.numeric(gsub(" .+","",system2("wc",paste("-l",your.file,sep=" "),stdout=TRUE, stderr=TRUE)))
DT <- fread(your.file,nrows=50000000,sep=",",header=TRUE)
KEEP.DT <- DT[,list("feature"=sum(length(feature))),by=id]
rm(DT) ; gc()
Starts <- c(seq(50000000,LineNu,by=50000000),LineNu)
for (i in 2:(length(Starts)-1)) {
  cat(paste0("Filtering next 50000000 lines    ", i, " of ",length(Starts)-1, " \n"))
  DT <- fread(your.file,skip=Starts[i],nrows=ifelse(50000000*(i-1) < Starts[length(Starts)],50000000,(50000000*(i-1)) - Starts[length(Starts)]),sep=",",header=FALSE)
  DT[,list("feature"=sum(length(feature))),by=id]
  KEEP.DT <- rbind(KEEP.DT,DT)
  rm(DT) ; gc()
}

需要注意的是,由于某些id可能在不同的块中被读取,可能需要重新执行DT[sum(length)]这部分代码。

另外,使用data.table包的fread函数和by处理,应该不需要循环。fread函数已经非常快速,并且大部分的by操作也是如此。

最后,需要指出的是,20GB的CSV文件并不一定意味着在R内存中也是20GB。可以通过逐块读取数据并进行处理,以避免超出内存限制。

0