【问题标题】:Handling a Folder of Large CSV Files处理大型 CSV 文件的文件夹
【发布时间】:2017-07-05 03:34:29
【问题描述】:

我有一个大型 CSV 文件的大文件夹(文件夹中大约有 25,000 个文件,并且会进一步增加),也就是说,几乎所有文件的行数都超过 Excel 的行限制(限制是 100 万左右,我猜测)。所有这些 CSV 文件在每一行中都有 5 个元素,由逗号分隔,所有文件中的行数(信息)各不相同。

One CSV File:
a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
.
.
.
a3152685,b3152685,c3152685,d3152685,e3152685

My Reference File:
x1,y1
x2,y2
x3,y3
.
.
.
x397,y397

基本上,我只需要根据我的参考文件从每个 CSV 文件中访问其中一些行(大约 400 行)。无论我可以在任何 CSV 文件中将 xy 对与 ab 对匹配,我都会将带有 CSV 文件标题的 a、b、c、d、e 行保存到其他地方,最好是 Excel 文件,但我愿意接受想法.

我可以使用 Matlab, Python 2.7, MS Access或 MS Excel。我从来没有做过任何 VBA 的东西,但是如果你有解决这个问题的 VBA 方法,我也愿意听。

如果我不够清楚,如果您需要更多说明,请告诉我。

【问题讨论】:

  • 您可以使用 ADO 和 Excel 来引用文本文件。
  • 在 MATLAB 或 python 中这是微不足道的。打开文件,逐行读取直到满意,保存数据。

标签: python vba matlab csv ms-access


【解决方案1】:

你可以找到办公室的限制products here

Matlab 非常适合处理这种大文件和大量文件集。 2014 版对引入的 csv 数据存储进行了很多改进,现在也可以很好地处理 excel 文件。

看看这个教程:

http://blogs.mathworks.com/loren/2014/12/03/reading-big-data-into-matlab/

我有 3 个包含以下内容的 csv 文件(文件 [1-3].csv):

a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
a3,b3,c3,d3,e3
a4,b4,c4,d4,e4
a5,b5,c5,d5,e5
a6,b6,c6,d6,e6
a7,b7,c7,d7,e7
a8,b8,c8,d8,e8
a9,b9,c9,d9,e9
a10,b10,c10,d10,e10

以及用于列名称的文件 varnames:

A B C D E

让我们阅读文件:

>> datafile = 'csv-files/file1.csv';
>> headerfile = 'csv-files/varnames.txt'

>> fileID = fopen(headerfile);
>> varnames = textscan(fileID,'%s');
>> varnames = varnames{:};

ds = datastore(datafile,'ReadVariableNames',false);

>> ds.VariableNames = varnames


ds = 

  TabularTextDatastore with properties:

                      Files: {
                             '/home/anquegi/learn/matlab/stackoverflow/csv-files/file1.csv'
                             }
               FileEncoding: 'UTF-8'
          ReadVariableNames: false
              VariableNames: {'A', 'B', 'C' ... and 2 more}

  Text Format Properties:
             NumHeaderLines: 0
                  Delimiter: ','
               RowDelimiter: '\r\n'
             TreatAsMissing: ''
               MissingValue: NaN

  Advanced Text Format Properties:
            TextscanFormats: {'%q', '%q', '%q' ... and 2 more}
         ExponentCharacters: 'eEdD'
               CommentStyle: ''
                 Whitespace: ' \b\t'
    MultipleDelimitersAsOne: false

  Properties that control the table returned by preview, read, readall:
      SelectedVariableNames: {'A', 'B', 'C' ... and 2 more}
            SelectedFormats: {'%q', '%q', '%q' ... and 2 more}
                   ReadSize: 20000 rows


>> preview(ds)

ans = 

     A       B       C       D       E  
    ____    ____    ____    ____    ____

    'a1'    'b1'    'c1'    'd1'    'e1'
    'a2'    'b2'    'c2'    'd2'    'e2'
    'a3'    'b3'    'c3'    'd3'    'e3'
    'a4'    'b4'    'c4'    'd4'    'e4'
    'a5'    'b5'    'c5'    'd5'    'e5'
    'a6'    'b6'    'c6'    'd6'    'e6'
    'a7'    'b7'    'c7'    'd7'    'e7'
    'a8'    'b8'    'c8'    'd8'    'e8'

如果看我们取的参数ReadSize是ReadSize:20000行,那么matlab每次读取20000行就可以处理了。由于数据只有 10 行,我将其更改为 3:

>> ds.ReadSize=3

ds = 

  TabularTextDatastore with properties:

                      Files: {
                             '/home/anquegi/learn/matlab/stackoverflow/csv-files/file1.csv'
                             }
               FileEncoding: 'UTF-8'
          ReadVariableNames: false
              VariableNames: {'A', 'B', 'C' ... and 2 more}

  Text Format Properties:
             NumHeaderLines: 0
                  Delimiter: ','
               RowDelimiter: '\r\n'
             TreatAsMissing: ''
               MissingValue: NaN

  Advanced Text Format Properties:
            TextscanFormats: {'%q', '%q', '%q' ... and 2 more}
         ExponentCharacters: 'eEdD'
               CommentStyle: ''
                 Whitespace: ' \b\t'
    MultipleDelimitersAsOne: false

  Properties that control the table returned by preview, read, readall:
      SelectedVariableNames: {'A', 'B', 'C' ... and 2 more}
            SelectedFormats: {'%q', '%q', '%q' ... and 2 more}
                   ReadSize: 3 rows

>> reset(ds)
while hasdata(ds)
      T = read(ds);
      T.A
end

ans = 

    'a1'
    'a2'
    'a3'


ans = 

    'a4'
    'a5'
    'a6'


ans = 

    'a7'
    'a8'
    'a9'


ans = 

    'a10'

那么T变量是一个表,你可以写到你想写的地方:注意每次read(ds)它移动readsie分配的行数,这个参数可以是行,也可以是文件

>> reset(ds)
>> T = read(ds);
>> T

T = 

     A       B       C       D       E  
    ____    ____    ____    ____    ____

    'a1'    'b1'    'c1'    'd1'    'e1'
    'a2'    'b2'    'c2'    'd2'    'e2'
    'a3'    'b3'    'c3'    'd3'    'e3'

>> writetable(T,'mySpreadsheet','FileType','spreadsheet')
>> reset(ds)

【讨论】:

    【解决方案2】:

    这可能是题外话,但我认为您应该考虑 SQL Server 和 SSIS。您可以轻松地遍历文件夹中的所有文件,将所有文件加载到 SQL Server 中,然后将文件移出文件夹。下次将文件转储到您的文件夹中时,请在这些新文件上再次运行该过程。有关所有详细信息,请参阅下面的链接。

    https://www.mssqltips.com/sqlservertip/2874/loop-through-flat-files-in-sql-server-integration-services/

    或者,使用纯 SQL 来完成这项工作。

    --BULK INSERT MULTIPLE FILES From a Folder 
    
    --a table to loop thru filenames drop table ALLFILENAMES
    CREATE TABLE ALLFILENAMES(WHICHPATH VARCHAR(255),WHICHFILE varchar(255))
    
    --some variables
    declare @filename varchar(255),
            @path     varchar(255),
            @sql      varchar(8000),
            @cmd      varchar(1000)
    
    
    --get the list of files to process:
    SET @path = 'C:\Dump\'
    SET @cmd = 'dir ' + @path + '*.csv /b'
    INSERT INTO  ALLFILENAMES(WHICHFILE)
    EXEC Master..xp_cmdShell @cmd
    UPDATE ALLFILENAMES SET WHICHPATH = @path where WHICHPATH is null
    
    
    --cursor loop
    declare c1 cursor for SELECT WHICHPATH,WHICHFILE FROM ALLFILENAMES where WHICHFILE like '%.csv%'
    open c1
    fetch next from c1 into @path,@filename
    While @@fetch_status <> -1
      begin
      --bulk insert won't take a variable name, so make a sql and execute it instead:
       set @sql = 'BULK INSERT Temp FROM ''' + @path + @filename + ''' '
           + '     WITH ( 
                   FIELDTERMINATOR = '','', 
                   ROWTERMINATOR = ''\n'', 
                   FIRSTROW = 2 
                ) '
    print @sql
    exec (@sql)
    
      fetch next from c1 into @path,@filename
      end
    close c1
    deallocate c1
    
    
    --Extras
    
    --delete from ALLFILENAMES where WHICHFILE is NULL
    --select * from ALLFILENAMES
    --drop table ALLFILENAMES
    

    从这里开始:

    Import Multiple CSV Files to SQL Server from a Folder

    Access 不会处理这么多的日期,而且您已经知道,Excel 甚至不会接近。

    要考虑的另一件事是使用 R,它完全免费且速度非常快。

    我们经常遇到这样的情况:我们在多个文件中以不同的频率和不同的观察子集拥有数据,但我们希望尽可能完整和系统地将它们相互匹配。在 R 中,merge() 命令是将两个数据帧匹配在一起的好方法。

    只需将两个数据帧读入R

    mydata1 = read.csv(path1, header=T)
    mydata2 = read.csv(path2, header=T)
    

    然后,合并

    myfulldata = merge(mydata1, mydata2)
    

    只要 mydata1 和 mydata2 至少有一个具有相同名称的公共列(允许将 mydata1 中的观察结果与 mydata2 中的观察结果相匹配),这就像一个魅力。它也需要三行。

    如果我有 20 个文件,其中包含我想要匹配观察到观察的数据怎么办?假设它们都有一个允许合并的公共列,我仍然需要读取 20 个文件(20 行代码)并且 merge() 可以两两工作……所以我可以将 20 个数据帧与 19 个合并语句合并在一起像这样:

    mytempdata = merge(mydata1, mydata2)
    mytempdata = merge(mytempdata, mydata3)
    .
    .
    .
    mytempdata = merge(mytempdata, mydata20)
    

    这很乏味。您可能正在寻找一种更简单的方法。如果你是,我写了一个函数来解决你的问题,叫做 multmerge()。* 下面是定义函数的代码:

    multmerge = function(mypath){
    filenames=list.files(path=mypath, full.names=TRUE)
    datalist = lapply(filenames, function(x){read.csv(file=x,header=T)})
    Reduce(function(x,y) {merge(x,y)}, datalist)
    

    运行代码定义函数后,您就可以使用它了。该函数采用路径。此路径应该是一个文件夹的名称,该文件夹包含您要阅读和合并的所有文件,并且仅包含您要合并的那些文件。考虑到这一点,我有两个提示:

    在你使用这个功能之前,我的建议是在一个短目录下创建一个新文件夹(例如,这个文件夹的路径可以是“C://R//mergeme”)并保存你所有的文件想合并到那个文件夹中。 此外,请确保将进行匹配的列在每个文件中的格式相同(并且具有相同的名称)。 假设您将 20 个文件保存到位于“C://R//mergeme”的 mergeme 文件夹中,并且您想阅读并合并它们。要使用我的函数,请使用以下语法:

    mymergeddata = multmerge(“C://R//mergeme”)
    

    运行此命令后,您将拥有一个完全合并的数据框,其中所有变量都相互匹配。当然,匹配和合并数据的大部分细节归结为确保正确指定公共列,但鉴于此,此功能可以为您节省大量输入。

    将所有内容合并到 1 个数据框后,将其导出到文本文件或 CSV 文件,然后将其批量加载到 SQL Server 中。

    【讨论】:

      【解决方案3】:

      以防万一有人需要答案,我用 MATLAB 处理了它。

      MATLAB 中的数据存储功能正是我所寻找的。​​p>

      ds = datastore(MyReferenceFile);
      TableExtracted = readall(ds);
      

      那么剩下的就是find(ismember)负责了。

      还有datastore的批量查找功能(批量大小分配在ReadSize);但是,它默认为 20000,我想这也是限制。它太慢了,我不喜欢,所以我求助于readall,它仍然很快。

      【讨论】:

        猜你喜欢
        • 2015-02-20
        • 2015-10-10
        • 2016-06-17
        • 2018-02-23
        • 2014-08-12
        • 2014-09-24
        • 2016-01-12
        • 1970-01-01
        相关资源
        最近更新 更多