2011-01-20 41 views
35

Tôi đang làm việc với MATLAB trong vài ngày và tôi đang gặp khó khăn khi nhập tệp CSV vào ma trận.Nhập tệp CSV với các loại dữ liệu hỗn hợp

Vấn đề của tôi là tệp CSV của tôi chỉ chứa hầu hết các chuỗi và một số giá trị số nguyên, do đó csvread() không hoạt động. csvread() chỉ được cùng với giá trị số nguyên.

Làm cách nào để lưu trữ các chuỗi của tôi trong một số loại mảng 2 chiều để có quyền truy cập miễn phí vào từng phần tử?

Dưới đây là một CSV mẫu cho nhu cầu của tôi:

04;abc;def;ghj;klm;;;;; 
;;;;;Test;text;0xFF;; 
;;;;;asdfhsdf;dsafdsag;0x0F0F;; 

Điều quan trọng là những ô trống và các văn bản trong các tế bào. Như bạn thấy, cấu trúc có thể khác nhau.

+3

Hãy xem qua textcan> http://www.mathworks.com/help/techdoc/ref/textscan.html – zellus

+2

bạn nên đăng một vài hàng từ tệp CSV của mình để chúng tôi có ý tưởng về cách tệp có cấu trúc (là các chuỗi được trích dẫn bằng ''' hoặc '" ', chúng có chứa các dấu phẩy bên trong các trích dẫn hay không, là các giá trị số nguyên được trích dẫn, có bất kỳ dấu phân cách thoát nào chẳng hạn như' "đây là \" một ví dụ \ "" ' vv ...) – Amro

+0

Xong :) Tôi hy vọng nó sẽ giúp một chút – poeschlorn

Trả lời

51

Edited bây giờ mà các câu hỏi đã được cập nhật với một tập tin đầu vào mẫu ...

Đối với trường hợp khi bạn biết có bao nhiêu cột dữ liệu sẽ có trong tập tin CSV của bạn, đơn giản gọi đến TEXTSCAN như Amro suggests sẽ là giải pháp tốt nhất của bạn.

Tuy nhiên, nếu bạn không biết một số trước là có bao nhiêu cột trong tệp của mình, bạn có thể sử dụng cách tiếp cận tổng quát hơn như tôi đã làm trong hàm sau. Lần đầu tiên tôi sử dụng hàm FGETL để đọc từng dòng của tệp vào một mảng ô. Sau đó, tôi đã sử dụng hàm TEXTSCAN để phân tích từng dòng thành các chuỗi riêng biệt bằng dấu phân tách trường được xác định trước và xử lý các trường số nguyên như chuỗi hiện tại (chúng có thể được chuyển đổi thành giá trị số sau).Dưới đây là mã kết quả, được đặt trong một hàm 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 

Chạy chức năng này trên nội dung tập tin mẫu từ các câu hỏi đưa ra kết quả này:

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

Kết quả là một 3-by-10 mảng ô với một trường cho mỗi ô trong đó các trường bị thiếu được biểu thị bằng chuỗi trống ''. Bây giờ bạn có thể truy cập mỗi ô hoặc kết hợp các ô để định dạng chúng theo ý muốn. Ví dụ, nếu bạn muốn thay đổi các trường trong cột đầu tiên từ dây để nguyên giá trị, bạn có thể sử dụng chức năng STR2DOUBLE như sau:

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

Lưu ý rằng các kết quả lĩnh vực có sản phẩm nào trong NaN giá trị.

+1

Xem thêm giải pháp của @ AndyCampbell dưới đây để biết thêm các bản phát hành gần đây của Matlab: http: // stackoverflow.com/a/19642332/232610 – Jonas

+0

Đẹp nhất. Textscan không thích đầu vào rỗng mặc dù. Nếu tệp csv được quét có hàng trống, quy trình sẽ không thành công. Tôi khuyên bạn thay thế 'lineArray = lineArray (1: lineIndex-1);' bởi 'ind = all (cellfun (@ isempty, lineArray), 2); ' ' lineArray = lineArray (~ ind); ' – Alex

+0

Bạn cũng có thể sử dụng' strsplit() 'với tham số' CollapseDelimiters' được đặt thành 'false' để mã hóa từng dòng của tệp csv. Matlab, theo mặc định, thu gọn các dấu phân tách liên tiếp. Đặt thành false, kết quả là: '{'' '' '' '' '' 'Kiểm tra' 'văn bản' '0xFF' '' ''}' cho lệnh 'strsplit (' ;;;;; Test; văn bản; 0xFF ;; ','; ',' CollapseDelimiters ', sai) ' –

4

Tùy thuộc vào định dạng tệp của bạn, importdata có thể hoạt động.

Bạn có thể lưu trữ Chuỗi trong một mảng ô. Nhập "ô tài liệu" để biết thêm thông tin.

+0

Một mảng ô là những gì OP cần OP thậm chí có thể lưu trữ dữ liệu số nguyên trong đó – Marm0t

+0

Hi William, "ô" có vẻ là một cấu trúc dữ liệu rất tốt Điều duy nhất tôi không nhận được là "importdata", bởi vì nó không đọc trong các ô trống (từ CSV của tôi) ở đầu của một dòng ... Tôi chỉ nhận được một "[1x89 char]" được nhập khẩu – poeschlorn

2

Tôi khuyên bạn nên xem mảng tập dữ liệu.

Mảng dữ liệu là loại dữ liệu đi kèm với Công cụ thống kê. Nó được thiết kế đặc biệt để lưu trữ dữ liệu lưỡng tính trong một thùng chứa duy nhất.

Trang demo của Thanh công cụ thống kê chứa một vài vidoes hiển thị một số tính năng mảng tập dữ liệu. Đầu tiên có tiêu đề "Giới thiệu về mảng dữ liệu". Thứ hai có tiêu đề "Giới thiệu về tham gia".

http://www.mathworks.com/products/statistics/demos.html

+0

Cảm ơn bạn đã nswer, các ví dụ trông rất hữu ích, nhưng trong trường hợp của tôi tôi không cài đặt Toolbox Thống kê:/ – poeschlorn

+0

Xem câu trả lời của tôi bên dưới, nếu bạn có R2013b giải pháp này sẽ làm điều này với một bảng. –

1

Nếu tập tin đầu vào của bạn có một số tiền cố định các cột được phân cách bởi dấu phẩy và bạn biết trong đó cột là chuỗi nó có thể là tốt nhất để sử dụng chức năng

textscan() 

Lưu ý rằng bạn có thể chỉ định một định dạng mà bạn đọc tối đa số ký tự trong chuỗi hoặc cho đến khi dấu phân cách (dấu phẩy) được tìm thấy.

20

Với mẫu mà bạn đăng tải, mã đơn giản này nên thực hiện công việc:

fid = fopen('file.csv','r'); 
C = textscan(fid, repmat('%s',1,10), 'delimiter',';', 'CollectOutput',true); 
C = C{1}; 
fclose(fid); 

Sau đó, bạn có thể định dạng các cột theo kiểu của chúng. Ví dụ, nếu cột đầu tiên là tất cả các số nguyên, chúng ta có thể định dạng nó như vậy:

C(:,1) = num2cell(str2double(C(:,1))) 

Tương tự, nếu bạn muốn chuyển đổi cột thứ 8 từ hex để thập phân, bạn có thể sử dụng HEX2DEC:

C(:,8) = cellfun(@hex2dec, strrep(C(:,8),'0x',''), 'UniformOutput',false); 

Kết quả là mảng di động trông như sau:

C = 
    [ 4] 'abc' 'def' 'ghj' 'klm' ''   ''    [] '' '' 
    [NaN] ''  ''  ''  ''  'Test'  'text'  [ 255] '' '' 
    [NaN] ''  ''  ''  ''  'asdfhsdf' 'dsafdsag' [3855] '' '' 
0
% 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); 
6

Sử dụng xlsread, nó hoạt động giống như trên file .csv như nó thực hiện trên các tệp .xls. Chỉ định rằng bạn muốn có ba kết quả đầu ra:

[num char raw] = xlsread('your_filename.csv') 

và nó sẽ cung cấp cho bạn một mảng chỉ chứa dữ liệu số (char) và mảng chứa tất cả các loại dữ liệu trong cùng định dạng với bố cục .csv (nguyên).

14

Trong R2013b hay muộn bạn có thể sử dụng một bảng:

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

Đây là more info.

Các vấn đề liên quan