4

次の形式の情報を含むテキストファイルがあります。

Name1 34 25 36 46
Name1 23 53 15 86
Name1 25 25 87 35
Name2 76 22 44 55
Name2 88 88 88 88
Name3 11 11 11 11
Name3 55 66 88 88
Name3 88 88 88 88
Name3 00 00 00 00

さまざまな「名前」があり、それぞれの名前を配列スロットに配置する必要があります。次に、各行に関連付けられた日付をその特定のスポットに割り当てる別の方法が必要になります。たとえば、最初のName1には配列{0}が含まれている可能性がありますが、34、24、36、および46を何らかの方法で関連付ける必要もあります。また、異なる名前を互いに区別する必要があります。これを行うための最良の方法は何ですか?2x2アレイは解決策ではないようです。

私がこれまでに持っているのは、これに沿ったものです。

%# read the whole file to a temporary cell array
fid = fopen(filename,'rt');
tmp = textscan(fid,'%s','Delimiter','\n');
fclose(fid);

%# remove the lines starting with headerline
tmp = tmp{1};
idx = cellfun(@(x) strcmp(x(1:10),'headerline'), tmp);
tmp(idx) = [];

%# split and concatenate the rest
result = regexp(tmp,' ','split');
result = cat(1,result{:});

%# delete temporary array (if you want)
clear tmp

礼儀:Matlabでtxtファイルを読む

誰かが情報を整理するための最良の方法を教えてもらえますか?おかげで、助けていただければ幸いです。

4

2 に答える 2

5

コードから判断すると、使ってみませんか

fid = fopen(filename,'rt');
tmp = textscan(fid, '%s %d %d %d %d', 'Headerlines', 10);
fclose(fid);

textscanデフォルトでは、区切り文字としてスペースと改行を使用します。newlineを区切り文字として明示的に指定すると、区切り文字としてのスペースと移植性が失われます(Windows\r\nは単一の改行として使用することがよくありますが、Unixから派生したOSはを使用します\n)。したがって、データを考慮して、それを省略してください。

次に、フープをジャンプして10個のヘッダー行を削除textscanしますが、そのための優れた組み込みオプションがすでにあります。したがって、これらの手順は必要ありません。regexp区切り文字としてスペースを使用してパススルーで分割することで続行しますが、textscanすでにスペースで分割されているため、これも必要ありません。

したがって、上記の3行を使用すると、次のようになります。

tmp = 
    {9x1 cell}    [9x1 int32]    [9x1 int32]    [9x1 int32]    [9x1 int32]

次に、データをより便利に保存します。私は2つの方法を考えることができます:

  1. セル配列
  2. 構造

どちらの場合も、最初に一意の名前を見つける必要があります。

[names, inds] = unique(tmp{1});

セル配列の使用

これにより、名前でソートされたデータのセル配列が得られます。

data = [tmp{2:end}];
results = arrayfun(@(x) data(strcmp(tmp{1},x),:), ...
            names, 'uniformoutput', false);

resultsこれで、次のようにインデックスを作成できます。

results{3}(1,4)   %# for the 4th '11' for 'Name3' 

Matlabは1ベースであるため、4番目ではなく3番目の要素を示しa(3)いることに注意してください。a

コマンドの内訳:

  1. 関数arrayfunは、入力配列の要素をループし、各要素に関数を適用し、通常の配列(可能な場合)またはセル配列(不可能な場合(エラー)および指定された場合)のいずれかに結果を収集します'uniformoutput', falseforeachこれは、 -construct に少し似ています。

  2. names最初のステップで見つかった一意の配列に等しい入力配列を使用する場合、トリックは各名前に適用する関数にあります。この関数は、最初にを使用して(すべての名前を含む配列)@(x) data(strcmp(tmp{1},x),:)で指定された名前のインデックスを検索します。次に、これらのインデックスを使用して、つまり他のすべてのアレイにインデックスを付けます。tmp{1}strcmpdata = [tmp{2:end}]

  3. 次に、個々の一意の名前の結果がcell-arrayに格納されresultsます。

構造の使用

さらに一歩進んで、セル配列resultsを使用して、より人間が読めるデータ構造にすることができます。前のすべての手順を適用した後、これを実行します。

for ii = 1:numel(names)
    output.(names{ii}) = results{ii}; end

これで、名前でデータを参照できます。

output.Name3(1,4)   %# to index the 4th '11' from 'Name3'

この構文your_struct.('someString')は、動的構造参照と呼ばれます。と呼ばれる構造体のフィールドを参照または作成します。your_strucsomeString

names{ii}これで、削除したいアンダースコアが含まれている場合は、次のように定義できます。

camelCase = @(x) regexprep(x, '_+(\w?)', '${upper($1)}')

また

camelCase = @(x) regexprep(x, ' +(\w?)', '${upper($1)}')

スペース用。次に、

for ii = 1:numel(names)
    output.( camelCase(names{ii}) ) = results{ii}; end

その最後のもののためのこれらの人への称賛。

于 2012-09-18T05:03:33.080 に答える
1

まず、Rodyが提案する方法(Rodyが指摘する場合は+1)を使用してデータを確実に読み取る必要があるため、Rodyのコード例のように、そこまで到達し、tmpという変数があると仮定します。

ここで、問題を正しく理解している場合は、サンプルデータセットの各行を他の行と区別できる必要があります(日付を使用しますか?)が、同時に、異なる名前を簡単に区別する必要があります。複数の行で同じである必要があります(これも、サンプルデータセットから取得しています)。

これにアプローチする1つの可能な方法(確かに1つの欠点があります)は、構造を使用することです。Rodyの回答で変数tmpを取得したと仮定し、そこから実行します。コードを使用します:

NameVec = unique(tmp{1, 1});
for i = 1:1:size(NameVec, 1)
    Index = ismember(tmp{1, 1}, NameVec{i, 1});
    Struct.(NameVec{i, 1}).Data = ...
       [tmp{1, 2}(Index), tmp{1, 3}(Index), tmp{1, 4}(Index), tmp{1, 5}(Index)];
end
Struct.NameVec = NameVec;

このコードは、構造内の最初のレベルがデータセット内の一意の名前ごとにフィールド名を持つ構造を作成します(構造のNameVec最初のレベルの変数もコードに含めたので、これを使用して後でループを使用してさまざまなフィールド)。次に、各フィールド(この例ではName1、Name2、およびName3)内に、その名前に関連付けられたデータを含むデータマトリックスを保存しました(個々の行は保持されます)。

このアプローチの欠点は、すべてのデータを1つの大きな配列に戻したい場合、Struct.NameVecの要素をループして、各一意の名前に関連付けられたデータマトリックスを取得する必要があることです。そして、MATLABではループが遅いです。つまり、実際には、データの使用方法によって異なります。

お役に立てれば!

ps、matlab構造に慣れていない場合は、次のコードを実行します。

tmp = cell(1, 5);
tmp{1, 1} = {'Name1'; 'Name1'; 'Name1'; 'Name2'; 'Name2'; 'Name3'; ...
'Name3'; 'Name3'; 'Name3';};
tmp{1, 2} = [34;23;25;76;88;11;55;88;00];
tmp{1, 3} = [25;53;25;22;88;11;66;88;00];
tmp{1, 4} = [36;15;87;44;88;11;88;88;00];
tmp{1, 5} = [46;86;35;55;88;11;88;88;00];

次に、上記で提供したコードをで実行しますtmpStruct次に、matlab変数エディターで呼び出された結果の構造を見てください。これにより、それらがどのように機能するかを感じることができます。

于 2012-09-18T09:08:36.817 に答える