2

我有一个包含 1911518 个值的数据集。我已经使用了 textscan 功能。但该函数仅返回 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
4

2 回答 2

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 ]+)' 单词,包括空格

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

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

于 2013-10-18T20:50:32.160 回答
1

Daniel R 的回答基本上是正确的。详细说明(我会将此作为评论发布,但我缺乏声誉),textscan在 MATLAB 中非常挑剔,只要遇到与您指定的格式不完全匹配的内容,它就会自动退出。

如果您有一个可能包含一些错误或不一致的数据文件,您的主要选择是以某种方式预处理文件以删除这些错误,或者(如丹尼尔建议的那样)逐行读取文件并解析随心所欲。前者的工作量可能与后者差不多,除非您打算手动完成并且没有太多错误需要修复,因此在大多数情况下,编写自己的解析器可能更容易。

您可能会做的唯一另一件事-如果唯一的错误是类型错误(例如,列应该是整数,但有时会出现浮点数),您仍然可以使用 textscan 并将格式说明符替换为更多通用的。例如,在该示例中,您可以将%d(integer)替换为%f(floating-point number)。由于所有整数都是浮点数,因此应该可以正常工作。在最极端的情况下,您可以将所有列作为字符串%stextscan

于 2013-10-18T22:30:30.970 回答