无法使用TextScan在Matlab中一次导入所有值

时间:2013-10-18 20:05:26

标签: matlab csv import textscan

我有一个1911518值的数据集。我使用了文本扫描功能。但该函数仅返回1424458个值。我再次创建了一个新变量来获取剩余的值,但这次它给了我大约9000个值。有谁知道这是什么原因?

n=9
N=1911518

file_id=fopen('CRSP.csv');

C=textscan(file_id,'%s',n,'delimiter', ','); %To get the headers
C_text=textscan(file_id,'%s %s %s %d %d %d %d %f %f',N, 'delimiter' , ','); 

%Returns 1424458

C_text1=textscan(file_id,'%s %s %s %d %d %d %d %f %f',N, 'delimiter' , ','); 

%Returns only 9000 values    

fclose(file_id);

样本数据

DATE,COMNAM,TICKER,PERMNO,PERMCO,SHROUT,VOL,RET,sprtrn

01/02/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 23700,  0.000000,  0.007793
01/03/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 20800,  0.020000,  0.000950
01/04/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 65300, -0.026144, -0.005826
01/05/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 340600, 0.000000, -0.001587
01/08/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 3400,   0.000000,  0.002821
01/09/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 27200, -0.006711, -0.014568
01/10/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 25400, -0.033784, -0.018000
01/11/1996, ACME CLEVELAND CORP NEW, AMT, 10057, 20020, 6313, 14000,  0.000000,  0.007034

2 个答案:

答案 0 :(得分:2)

我认为数据中存在一些错误,或者格式模式与数据不匹配。尝试提取这些行:

file_id=fopen('CRSP.csv');
for idx=1:1424456
    fgetl(file_id); %dump data
end
for idx=1:10
    fprintf('%s\n',fgetl(file_id));
end

如果出现错误,则应该是第2行或第3行。有什么特别的吗?也许COMNAM有一些特殊的角色?

要读取文件,我会使用以下代码逐行阅读:

file_id=fopen('CRSP.csv');
line=fgetl(file_id);
data={};
int ix=1;
while(ischar(line))
    [parsed,sindex,eindex] = regexpi(line,'(\d\d/\d\d/\d\d\d\d)\s*, ([\w ]+), ([\w ]+), ([\d]+), ([\d]+), ([\d]+), ([\d]+), ([\d \.]+), ([\d \.]+)','tokens')
    if ~isempty(sindex)&&numel(sindex)==1&&(sindex==1)&&(eindex==numel(x))
        data{end+1}=parsed{1};
    else
        fprintf('Unable to parse line %d with content: %S',ix,line);
    end
    line=fgetl(file_id);
    ix=ix+1;
end

正则表达式的简短摘要:

'(...)'之间的所有内容都是返回的“令牌”

'([\ d。] +)'数字,空格和“。”

'([\ d。] +)'数字和空格

'([\ w] +)'Word,包括空格

'(\ d \ d / \ d \ d / \ d \ d \ d \ d)'日期

这个表达有点“懒惰”。它不仅接受“0.000”作为数字而且接受“0.0 00”。或其他一些组合,但它应足以检测所有错误。如果没有,表达必须改进。

答案 1 :(得分:1)

Daniel R的回答基本上是正确的。详细说明(我会将其作为评论发布,但我缺乏声誉),MATLAB中的textscan非常挑剔,只要它碰到的东西不能与您指定的格式完全匹配,它就基本上会失效。

如果您的数据文件可能包含某些错误或不一致,那么您的主要选项是以某种方式预处理文件以删除这些错误,或者(如Daniel建议的那样)自行读取文件。然后按照你想要的方式解析它。前者可能与后者的工作量大致相同,除非您打算手动完成并且修复的错误不多,因此在大多数情况下编写自己的解析器可能更容易。

你可能做的唯一其他事情 - 如果唯一的错误是类型的错误(例如,一个列应该是一个整数,但有时一个浮点数滑入),你仍然可以使用textscan并替换格式具有更通用的说明符。例如,在该示例中,您可以将%d(整数)替换为%f(浮点数)。由于所有整数都是浮点数,因此应该可以正常工作。在最极端的情况下,您可以在所有列中读取字符串(%s),但是无论如何您都需要解析它们,如果没有textscan,您可能会更好。