Pembuatan MATLAB dari struct-vector

Mengingat beberapa data - misalnya (dalam kasus saya) - seperti tabel berikut

Name  |pos_x|pos_y|pos_z
------------------------
Point1|   .1|   .1|   .2
Point2|  0.0|  0.0|   .1
Middle|   .1|   .2|   .1
Point3|  0.0|    1|  0.0

dan mungkin setelah mengimpor data tersebut dari excel semua nilai disimpan dalam array sel (sebut saja celldata).
Untuk tujuan pengujian sel ini dapat dibuat dengan baris

celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

Untuk contoh ini selnya berukuran 4x4.

Saat ini saya sedang membuat struktur dengan baris berikut

point.name=char(celldata(:,1));
point.posxyz=cell2mat(celldata(:,2:4));

Ini menghasilkan point size 1x1 Class struct. Saya mencari cara efisien untuk menghasilkannya sebagai point size 4x1 Class struct - jadi satu elemen untuk setiap baris pada tabel di atas - semuanya dengan struktur dalam yang sama: nama dan koordinat.
Saya sudah mencoba cell2struct, tapi itu hanya dapat dibuka sepanjang satu dimensi tanpa mengelompokkan beberapa kolom bersama - sejauh yang saya coba.
Selanjutnya, ini bukan duplikat dari Alokasikan terlebih dahulu struktur sel di matlab seperti dalam kasus ini di sini, saya memiliki banyak kolom berbeda - atau bahkan mungkin jumlah kolom yang dinamis.


person Bastian Ebeling    schedule 29.04.2013    source sumber
comment
apakah menurut Anda dataset akan membantu?   -  person fpe    schedule 29.04.2013
comment
Saya pikir akan baik-baik saja untuk mengulang elemen: for punkt=point,disp([punkt.name ':' num2str(norm(punkt.posxyz))]),end sebagai contoh. Terutama kita tidak perlu memeriksa berapa banyak elemen yang ada. Apakah Anda tahu sesuatu yang lebih baik?   -  person Bastian Ebeling    schedule 29.04.2013


Jawaban (2)


cellData = {'Name', 'pos_x', 'pos_y'; 'Harry', 34, 2; 'Bernard', 5, 11}

Kemudian

for col = 1:size(cellData ,2)
    fieldName = cellData{1, col};
    c = cellData (2:end, col);
    [point(1:length(c)).(fieldName)] = c{:};
end

Sekarang

point(1)

ans = 

     Name: 'Harry'
    pos_x: 34
    pos_y: 2

point(2)

ans = 

     Name: 'Bernard'
    pos_x: 5
    pos_y: 11

EDIT:

Jika Anda ingin hanya memiliki 2 kolom yaitu Name dan posxyz maka:

 [M, N] = size(celldata);
 names = celldata(:,1);
 [point(1:M).Name] = names{:};
 xyz = mat2cell(cell2mat(celldata(:,2:end)), ones(M,1), N - 1);
 [point(1:M).posxyz] = xyz{:};

sekarang untuk celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

point(1)

ans = 

          Name: 'Point1'
        posxyz: [0.1000 0.1000 0.2000]

point(2)

ans = 

      Name: 'Point2'
    posxyz: [0 0 0.1000]
person Dan    schedule 29.04.2013
comment
Terima kasih @Dan atas ide ini, tapi saya benar-benar tidak suka harus menetapkan nama (misalnya) satu per satu. Silakan pikirkan tentang tabel dengan ratusan baris atau lebih. Ide lebih lanjut? - person Bastian Ebeling; 29.04.2013
comment
Menambahkan tentu saja bisa dilakukan seperti yang dilakukan dalam rmfield.m - tapi menurut saya ini bisa dilakukan lebih cepat, atau? - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling ratusan baris atau ratusan kolom? - person Dan; 29.04.2013
comment
Hai Dan, dalam komentar saya, saya menyebutkan ratusan baris. Namun (seperti pada editan terakhir saya, yang mungkin belum pernah Anda lihat) mungkin juga terdapat banyak kolom. - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling Ya, garis jelas tidak menjadi masalah, cukup ganti 4 dengan length(C), untuk kolom, menurut saya taruhan terbaik Anda adalah perulangan for sederhana, jadi jika col adalah variabel perulangan dan C = celldata{:, col} maka [point(1:length(C), col).(C{1})] = C{2:end} - person Dan; 29.04.2013
comment
Dalam pemrograman saya, saya selalu berusaha mencegah penggunaan for loop. Dalam baris saya di atas tidak diperlukan perulangan atau pengecekan panjang. Contoh terakhir Anda untuk kolom tidak berfungsi dalam R2013a. - person Bastian Ebeling; 29.04.2013
comment
mari kita melanjutkan diskusi ini di chat - person Bastian Ebeling; 29.04.2013

Coba gunakan struct dengan array sel sebagai input:

C = cellfun(@(x,y,z)[x y z], celldata(:,2), celldata(:,3), celldata(:,4), 'Uniform', 0);
point = struct('name', celldata(:, 1), 'posxyz', C);

Perhatikan bahwa untuk bidang posxyz saya telah membuat array sel baru dengan mengatenasi sel celldata.

Jika nanti Anda ingin menambahkan kolom lain, Anda dapat menggunakan deal dan daftar yang dipisahkan koma. Contoh berikut menyimpan nilai dari kolom keempat celldata di kolom baru, yang disebut pos_z:

[point(:).pos_z] = deal(celldata{:, 4});
person Eitan T    schedule 29.04.2013
comment
Terima kasih, ini ide yang sangat bagus. Dalam kasus saya ada lebih banyak kolom - dan agar mudah dibaca saya ingin menambahkan setiap kolom (atau sepasang kolom seperti di xyz) dalam satu baris kode sumber. Apakah Anda tahu cara menambahkan bidang ke struktur titik yang Anda buat? - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling Tentu saja. Anda harus menggunakan deal dan daftar yang dipisahkan koma. Lihat jawaban yang direvisi. - person Eitan T; 29.04.2013