Я работаю с MATLAB в течение нескольких дней, и мне трудно импортировать CSV файл в матрицу.
Моя проблема в том, что мой CSV файл содержит почти только строки и некоторые целочисленные значения, поэтому csvread()
не работает. csvread()
поддерживает только целые значения.
Как я могу хранить свои строки в каком-то двумерном массиве, чтобы иметь свободный доступ к каждому элементу?
Вот пример CSV для моих нужд:
04;abc;def;ghj;klm;;;;;
;;;;;Test;text;0xFF;;
;;;;;asdfhsdf;dsafdsag;0x0F0F;;
Главное - пустые ячейки и тексты внутри ячеек. Как видите, структура может меняться.
Отредактировано, что вопрос был обновлен с помощью примерного входного файла...
В случае, когда вы знаете, сколько столбцов данных будет в вашем CSV файле, один простой вызов TEXTSCAN Amro предлагает будет вашим лучшим решением.
Однако, если вы не знаете априори, сколько столбцов находится в вашем файле, вы можете использовать более общий подход, как я сделал в следующей функции. Я сначала использовал функцию FGETL, чтобы прочитать каждую строку файла в массиве ячеек. Затем я использовал функцию TEXTSCAN для синтаксического анализа каждой строки в отдельных строках с использованием предопределенного разделителя полей и обработки целых полей как строк на данный момент ( они могут быть преобразованы в числовые значения позже). Вот результирующий код, помещенный в функцию read_mixed_csv
:
function lineArray = read_mixed_csv(fileName,delimiter)
fid = fopen(fileName,'r'); %# Open the file
lineArray = cell(100,1); %# Preallocate a cell array (ideally slightly
%# larger than is needed)
lineIndex = 1; %# Index of cell to place the next line in
nextLine = fgetl(fid); %# Read the first line from the file
while ~isequal(nextLine,-1) %# Loop while not at the end of the file
lineArray{lineIndex} = nextLine; %# Add the line to the cell array
lineIndex = lineIndex+1; %# Increment the line index
nextLine = fgetl(fid); %# Read the next line from the file
end
fclose(fid); %# Close the file
lineArray = lineArray(1:lineIndex-1); %# Remove empty cells, if needed
for iLine = 1:lineIndex-1 %# Loop over lines
lineData = textscan(lineArray{iLine},'%s',... %# Read strings
'Delimiter',delimiter);
lineData = lineData{1}; %# Remove cell encapsulation
if strcmp(lineArray{iLine}(end),delimiter) %# Account for when the line
lineData{end+1} = ''; %# ends with a delimiter
end
lineArray(iLine,1:numel(lineData)) = lineData; %# Overwrite line data
end
end
Запуск этой функции из содержимого файла образца из вопроса дает следующий результат:
>> data = read_mixed_csv('myfile.csv',';')
data =
Columns 1 through 7
'04' 'abc' 'def' 'ghj' 'klm' '' ''
'' '' '' '' '' 'Test' 'text'
'' '' '' '' '' 'asdfhsdf' 'dsafdsag'
Columns 8 through 10
'' '' ''
'0xFF' '' ''
'0x0F0F' '' ''
В результате получается массив размером 3 на 10 с одним полем на ячейку, где отсутствующие поля представлены пустой строкой ''
. Теперь вы можете получить доступ к каждой ячейке или комбинации ячеек, чтобы форматировать их по своему усмотрению. Например, если вы хотите изменить поля в первом столбце от строк до целочисленных значений, вы можете использовать функцию STR2DOUBLE следующим образом
>> data(:,1) = cellfun(@(s) {str2double(s)},data(:,1))
data =
Columns 1 through 7
[ 4] 'abc' 'def' 'ghj' 'klm' '' ''
[NaN] '' '' '' '' 'Test' 'text'
[NaN] '' '' '' '' 'asdfhsdf' 'dsafdsag'
Columns 8 through 10
'' '' ''
'0xFF' '' ''
'0x0F0F' '' ''
Обратите внимание, что пустые поля приводят к значениям NaN.
lineArray = lineArray(1:lineIndex-1);
по ind = all(cellfun(@isempty,lineArray),2);
lineArray = lineArray(~ind);
Учитывая образец, который вы опубликовали, этот простой код должен выполнять следующее задание:
fid = fopen('file.csv','r');
C = textscan(fid, repmat('%s',1,10), 'delimiter',';', 'CollectOutput',true);
C = C{1};
fclose(fid);
Затем вы можете форматировать столбцы в соответствии с их типом. Например, если первый столбец является целым числом, мы можем отформатировать его как таковой:
C(:,1) = num2cell( str2double(C(:,1)) )
Аналогично, если вы хотите преобразовать 8-й столбец из шестнадцатеричного числа в десятичный, вы можете использовать HEX2DEC:
C(:,8) = cellfun(@hex2dec, strrep(C(:,8),'0x',''), 'UniformOutput',false);
Результирующий массив ячеек выглядит следующим образом:
C =
[ 4] 'abc' 'def' 'ghj' 'klm' '' '' [] '' ''
[NaN] '' '' '' '' 'Test' 'text' [ 255] '' ''
[NaN] '' '' '' '' 'asdfhsdf' 'dsafdsag' [3855] '' ''
В R2013b или более поздней версии вы можете использовать таблицу:
>> table = readtable('myfile.txt','Delimiter',';','ReadVariableNames',false)
>> table =
Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10
____ _____ _____ _____ _____ __________ __________ ________ ____ _____
4 'abc' 'def' 'ghj' 'klm' '' '' '' NaN NaN
NaN '' '' '' '' 'Test' 'text' '0xFF' NaN NaN
NaN '' '' '' '' 'asdfhsdf' 'dsafdsag' '0x0F0F' NaN NaN
Вот подробнее.
Использовать xlsread, он работает так же хорошо. CSV файлы, как и файлы .xls. Укажите, что вы хотите три выхода:
[num char raw] = xlsread('your_filename.csv')
и он даст вам массив, содержащий только числовые данные (num), массив, содержащий только данные символа (char) и массив, который содержит все типы данных в том же формате, что и .csv layout (raw).
Вы пытались использовать функцию CSVIMPORT, найденную в обмене файлами? Я сам не пробовал, но он утверждает, что обрабатывает все комбинации текста и цифр.
http://www.mathworks.com/matlabcentral/fileexchange/23573-csvimport
В зависимости от формата файла importdatastrong > может работать.
Вы можете хранить строки в массиве ячеек. Введите "doc cell" для получения дополнительной информации.
Я рекомендую посмотреть массив массивов данных.
Массив массива данных - это тип данных, который поставляется со статистическим инструментом. Он специально предназначен для хранения гемогенных данных в одном контейнере.
Демо-страница Statistics Toolbox содержит пару vidoes, которые показывают некоторые функции массива набора данных. Первый - "Введение в массивы набора данных". Второй - "Введение в союз".
Если ваш входной файл имеет фиксированное количество столбцов, разделенных запятыми, и вы знаете, в каких столбцах это строки, лучше всего использовать функцию
textscan()
Обратите внимание, что вы можете указать формат, в котором вы читаете максимальное количество символов в строке или до тех пор, пока не будет найден разделитель (запятая).
% Assuming that the dataset is ";"-delimited and each line ends with ";"
fid = fopen('sampledata.csv');
tline = fgetl(fid);
u=sprintf('%c',tline); c=length(u);
id=findstr(u,';'); n=length(id);
data=cell(1,n);
for I=1:n
if I==1
data{1,I}=u(1:id(I)-1);
else
data{1,I}=u(id(I-1)+1:id(I)-1);
end
end
ct=1;
while ischar(tline)
ct=ct+1;
tline = fgetl(fid);
u=sprintf('%c',tline);
id=findstr(u,';');
if~isempty(id)
for I=1:n
if I==1
data{ct,I}=u(1:id(I)-1);
else
data{ct,I}=u(id(I-1)+1:id(I)-1);
end
end
end
end
fclose(fid);
'
или"
, содержат ли они запятые внутри кавычек, также являются целочисленными значениями в кавычках, есть ли любые экранированные разделители, такие как"this is \"an example\""
т. д.)