2013-07-15 3 views
4

У меня есть большой файл CSV (должна быть около 1 миллиона строк) с опцией данными со следующей структурой (содержание изменяется):MATLAB: Используя TextScan и преобразование массива ячеек в матрице

secid, date, days, delta, impl_volatility, impl_strike, impl_premium, dispersion, cp_flag, ticker, index_flag, industry_group 
100000, 02/05/1986, 60, -80, 0.270556, 74.2511, 5.2415, 0.021514, C, ASC, 0, 481 
100000, 03/05/1986, 30, -40, 0.251556, 74.2571, 6.2415, 0.025524, P, ASC, 0, 481 

Я успешно импортирован тестовый файл, используя следующие:

ftest = fopen('test.csv'); 
C = textscan(ftest,'%f %s %f %f %f %f %f %f %s %s %f %f','Headerlines',1,'Delimiter',','); 
fclose(ftest); 

Однако, C представляет собой массив ячеек, и это делает его труднее обрабатывать содержимое файла в MATLAB. Было бы проще иметь его как «обычный» массив (простите меня за то, что я не знаю правильной номенклатуры, я только начал работать с Matlab).

Если выход I C, я получаю:

Columns 1 through 6 
[2x1 double] {2x1 cell} [2x1 double] [2x1 double] [2x1 double] [2x1 double] 
Columns 7 through 12 
[2x1 double] [2x1 double] {2x1 cell} {2x1 cell} [2x1 double] [2x1 double] 

Так внутри массива ячеек, который является C, есть массивы и клеточные массивы - массивы для чисел и сотовых массивов для строк. Если я попытаюсь проверить элемент (1,2), я должен использовать C {1} (2), но если я хочу проверить элемент (2,2), я должен использовать C {2} {2}. В идеале я хотел бы получить доступ как к C (1,2), так и к C (2,2). Вопрос в том, как мне это сделать?

Я искал решения и нашел cells2mat, но он работает только в том случае, если все содержимое является числовым (я думаю). Я нашел это решение: Convert cell array of cell arrays to matrix of matrices, но horzcat извлекает ошибку, которая, как я полагаю, может возникнуть из-за той же проблемы.

Заранее благодарю вас за ваше время.

+1

массив ячеек - массив, который может хранить значения разных типов. Здесь у вас есть массив ячеек, в котором хранятся оба столбца чисел и строк. [Этот вопрос] (http://stackoverflow.com/questions/13540418/convert-cell-array-of-cell-arrays-to-matrix-of-matrices) предполагает, что все, что у вас есть, это числовые значения, поэтому массив ячеек действительно избыточно, и его можно преобразовать в матрицу, которую намного легче манипулировать. Но что вы ожидаете получить, когда у вас есть струны? –

ответ

5

Поскольку у вас есть массив, содержащий как числовые, так и символьные данные, то, что вы хотите, невозможно (и, поверьте, это было бы непрактичным тоже).

Ссылка на отдельные номера в числовом массиве отличается от ссылки на целые строки. Это просто не ускользает от этого, и не должно быть: вы относитесь к цветам иначе, чем относитесь к людям (надеюсь, так или иначе).

В MATLAB строка представляет собой обычный массив с той разницей, что каждая запись массива не представляет число, а символ. Реферирование отдельных символов идет так же, как ссылки на номера в массивах:

>> a = 'my string' 
>> a(4) 
ans = 
s 
>> a+0 % cast to double to show the "true character" of strings 
ans = 
    109 121 32 115 116 114 105 110 103 

Однако textscan предполагает (справедливо), что вы не хотите делать что, а вы хотите, чтобы извлечь целые строки из файл. И целые строки следует ссылаться по-разному, чтобы указать, что вы имеете в виду целые строки, а не отдельные символы.

Я думаю, что вы сможете найти все это немного более понятным, если разделить результаты textscan вверх в обычный числовой массив и массив ячеек строк, например, так:

% load the data 
ftest = fopen('test.csv'); 
C = textscan(ftest,... 
    '%f %s %f %f %f %f %f %f %s %s %f %f',...  
    'collectoutput', true,... 
    'Delimiter',',\n'); 
fclose(ftest); 

% split into numeric and char arrays 
numeric = [C{[1 3 5]}] 
alpha = [C{[2 4]}] 

REFERENCING данные в numeric затем следует тем же правилам, как и любой обычный массив, и ссылки на строки в alpha затем следует нормальные клетки ссылок правила (как в alpha{2,1}, чтобы получить '03/05/1986')

EDIT на основе нет вашего комментарии, вы хотите сделать преобразование, как это:

% Read the data 
fid = fopen('test.csv', 'r'); 
C = textscan(fid,... 
    '%f %s %f %f %f %f %f %f %s %s %f %f',... 
    'Headerlines', 1,... 
    'Delimiter',','); 
fclose(fid); 

% Delete 10th element ('ASC') 
C(10) = []; 

% Mass-convert dates to datenums 
C{2} = datenum(C{2}, 'dd/mm/yyyy'); 

% Map 'P' to 1 and 'C' to 2 
map('PC') = [1 2]; 
C{9} = map([C{9}{:}]).'; 

% Convert whole array to numeric array 
C = [C{:}]; 
+0

Благодарим вас за ответ @Rody. Я понимаю эту проблему. Я рассматриваю возможность преобразования даты и cp_flag в числах и игнорирование поля тикера. Можете ли вы посоветовать мне, если это эффективный способ сделать это? 'ftest = fopen ('testfile2.csv'); C = textscan (ftest, '% f% s% f% f% f% f% f% f% s% s% f% f', 'Headerlines', 1, 'Delimiter', ','); fclose (ftest); для i = 1: размер (C {9}) C {2} {i} = дата (C {2} {i}, 'dd/mm/yyyy'); , если C {9} {i} == 'P' C {9} {i} = 1; elseif C {9} {i} == 'C' C {9} {i} = 2; конец конец C {2} = cell2mat (C {2}); C {9} = cell2mat (C {9}); C = [C {[1 2 3 4 5 6 7 8 9 11 12]}] ' – sasstudent

+0

@japa: Несмотря на то, что ваш подход не является неправильным, я редактировал версию, которая короче, быстрее и более MATLABy :) –

+0

Большое спасибо @Rody, это очень быстро. Он обрабатывает файл 1052480 строк примерно через 10 секунд. Большое спасибо! – sasstudent

0

У меня был тот же вопрос ... Я бы предпочел, чтобы иметь массив ячеек с 2-D для легкого доступа и использования встроенного в MATLAB сортировка функции.

Вот еще одно решение, которое может сработать для вас (так TMW делает это в своем автоматическом сгенерированном коде в инструменте импорта). Он превращает числовые массивы в массивы ячеек, чтобы вы могли объединить их в двумерную матрицу.

C([1,3,4,5,6,7,8,11,12]) = cellfun(@(x) num2cell(x), C([1,3,4,5,6,7,8,11,12]),'UniformOutput', false); 

C = [C{1:end}];