簡體   English   中英

如何使用任何R包(如ff或data.table)剪切大型csv文件?

[英]How can I cut large csv files using any R packages like ff or data.table?

我想剪切大型csv文件(文件大小超過RAM大小)並使用它們或將每個文件保存在磁盤中供以后使用。 對於大文件,哪個R包最適合這樣做?

我沒有嘗試過但在read.tableread.csv使用skipnrows參數值得一試。 這些來自?read.table

skip integer:開始讀取數據之前要跳過的數據文件的行數。

nrows integer:要讀入的最大行數。將忽略負值和其他無效值。

為了避免一些麻煩的問題,你需要做一些錯誤處理。 換句話說,當跳過值大於你的大csv中的行數時,我不知道什么是開心的。

ps我也不知道header=TRUE是否影響skip,你還必須檢查。

給@berkorbay的答案是可以的,我可以確認標題可以與skip一起使用。 但是,如果您的文件非常大,則會變得非常緩慢,因為在第一個之后的每個后續讀取必須跳過所有先前讀取的行。

我不得不做類似的事情,在浪費了相當多的時間之后,我在PERL中編寫了一個簡短的腳本,它將原始文件分成塊,你可以一個接一個地閱讀。 快得多。 我在這里附上了源代碼,翻譯了一些部分,以便明確意圖:

#!/usr/bin/perl
system("cls");
print("Fragment .csv file keeping header in each chunk\n") ;

print("\nEnter input file name  = ") ;
$entrada = <STDIN> ;
print("\nEnter maximum number of lines in each fragment = ") ;
$nlineas = <STDIN> ;
print("\nEnter output file name stem   = ") ;
$salida = <STDIN> ;
chop($salida) ;
open(IN,$entrada)    || die "Cannot open input file: $!\n" ;

$cabecera  = <IN> ;
$leidas    = 0  ;
$fragmento = 1  ;
$fichero   = $salida.$fragmento ;
open(OUT,">$fichero") || die "Cannot open output file: $!\n" ;
print OUT $cabecera ;
while(<IN>) {
    if ($leidas > $nlineas) {
    close(OUT) ;
    $fragmento++ ;
    $fichero   = $salida.$fragmento ;
    open(OUT,">$fichero") || die "Cannot open output file: $!\n" ;
    print OUT $cabecera ;
    $leidas = 0;
    }
    $leidas++ ;
    print OUT $_ ;
}
close(OUT) ;

只需保存任何名稱並執行即可。 如果你在不同的地方有PERL,可能必須改變第一行(如果你在Windows上,你必須調用腳本作為“perl name-of-script”)。

應該使用ff包的read.csv.ffdf和這樣的特定參數來讀取大文件:

library(ff)
a <- read.csv.ffdf(file="big.csv", header=TRUE, VERBOSE=TRUE, first.rows=1000000, next.rows=1000000, colClasses=NA)

將大文件讀入ff對象后,可以使用以下命令將ffobject子設置為數據幀:a [1000:1000000,]

和保存用於子集的代碼的其余部分破dataframes totalrows =暗淡的(a)[1] row.size = as.integer(object.size(A [1:10000,]))/ 10000 #IN字節

block.size = 200000000  #in bytes .IN Mbs 200 Mb

#rows.block is rows per block
rows.block = ceiling(block.size/row.size)

#nmaps is the number of chunks/maps of big dataframe(ff), nmaps = number of maps - 1
nmaps = floor(totalrows/rows.block)


for(i in (0:nmaps)){
  if(i==nmaps){
    df = a[(i*rows.block+1) : totalrows,]
  }
  else{
    df = a[(i*rows.block+1) : ((i+1)*rows.block),]
  }
  #process df or save it
  write.csv(df,paste0("M",i+1,".csv"))
  #remove df
  rm(df)
}

或者,您可以先使用dbWriteTable將文件讀入mysql,然后使用ETLUtils包中的read.dbi.ffdf函數將其讀回R.考慮下面的函數;

 read.csv.sql.ffdf <- function(file, name,overwrite = TRUE, header = TRUE, drv = MySQL(), dbname = "new", username = "root",host='localhost', password = "1234"){ conn = dbConnect(drv, user = username, password = password, host = host, dbname = dbname) dbWriteTable(conn, name, file, header = header, overwrite = overwrite) on.exit(dbRemoveTable(conn, name)) command = paste0("select * from ", name) ret = read.dbi.ffdf(command, dbConnect.args = list(drv =drv, dbname = dbname, username = username, password = password)) return(ret) } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM