处理大型CSV文件的文件夹

时间:2017-02-16 06:54:10

标签: python vba matlab csv ms-access

我有一个大型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行)。无论我在哪里可以将xy对与任何CSV文件中的ab对匹配,我都会将带有CSV文件标题的a,b,c,d,e行保存到其他地方,最好是Excel文件,但我愿意接受各种想法

我可以使用Matlab,Python 2.7,MS Access(将CSV文件转换为数据库文件似乎是一个好主意,如果我不必为每个文件执行此操作 - 是否有批处理版本)或MS Excel。我从来没有做过VBA的任何事情,但是如果你有一些VBA解决方案来解决这个问题,我也愿意接听。

如果我不够清楚你是否需要更多的澄清,请告诉我。

3 个答案:

答案 0 :(得分: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变量是一个表,你可以在任何你想要的地方写它:注意每次你读(ds)它移动readie分配的行数,这个参数可以是行或文件

>> 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)

答案 1 :(得分:1)

如果有人需要答案,我会用MATLAB处理它。

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

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

其余的只是find(ismember)负责。

ReadSize还有批量查找功能(批量大小在datastore分配);然而,它默认为20000,我猜这也是限制。这对我来说太慢了所以我使用了readall并且它仍然很快。

答案 2 :(得分:0)

这可能是偏离主题的,但我认为你应该考虑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中。