1

私は以下のようなテーブルを持っています: (これは私のテーブルからの数行です)

T = table({'A';'A';'A';'B';'B';'B';'C';'C';'C';'C'}, {'x';'y';'z';'x';'w';'t';'z';'x';'t';'o'},[5;1;2;2;4;2;2;5;4;1], ...
      'VariableNames', {'memberId', 'productId','Rating'});

T:

A  x  5
A  y  1
Z  z  2
B  x  2
B  w  4
B  t  2
C  z  2
C  x  5
C  t  4
C  o  1
C  u  3
D  r  1
D  t  2
D  w  5
.
.
.
.

ユーザー A を取得してから、前のテーブル (テーブル T) のようなテーブルを作成し、そのテーブルに入るにはすべての行がユーザー A に関連付けられている必要があります。この時点で、テーブルには次の行があります。

A  x  5
A  y  1
A  z  2

次に、このユーザーに関連する製品、つまり x,y,z を考えます。then x、次に y および z を含むすべての行がテーブルに追加されます。表のこの時点で、次の行があります。

A  x  5
A  y  1
A  z  2
B  x  2
C  z  2
C  x  5

次に、他のユーザーが検討対象としてテーブルに追加されました。つまり、 B,C です。次に、同じことが最初のユーザーに対して行われました (A) は、このユーザーに対して行われます (それぞれ B、次に C)。これは、必要な数の行がテーブルに追加されるようにするためです。ここでは、たとえば、8 行が必要です。つまり、最終結果は次のようになります。

A  x  5
A  y  1
A  z  2
B  x  2
C  z  2
C  x  5
B  w  4
B  t  2

つまり、作業が完了すると、2 番目のテーブル行の要求された数の行がインポートされます。

この点で私を助けてくれる体があれば、私は感謝しています。

4

1 に答える 1

1

あなたが求めることを行う方法は次のとおりです(ただし、質問で明確に定義されていない場合もあります)。

% I added user 'D' for the scenario of an unconnected node
T = table({'A';'A';'A';'B';'B';'B';'C';'C';'C';'C';'D';'D';'D';'D'},...
    {'x';'y';'z';'x';'w';'t';'z';'x';'t';'o';'q';'p';'f';'v'},...
    [5;1;2;2;4;2;2;5;4;1;4;5;2;1], ...
    'VariableNames', {'memberId', 'productId','Rating'});
% initial preparations:
rows_limit = 8;
first_user = 'B'; % this is just for readability
newT = table(cell(rows_limit,1),cell(rows_limit,1),zeros(rows_limit,1),...
    'VariableNames',{'memberId', 'productId','Rating'});
% We need an index vector so we won't add the same row twice:
added = false(height(T),1);
row_count = 1;
users_list = {first_user};

% now we start adding rows to newT until it's full: 
while row_count<rows_limit
    while numel(users_list)>=1
        % get all the user's rows
        next_to_add = strcmp(T.memberId,users_list{1}) & ~added;
        % if this user has any rows to be added:
        if sum(next_to_add)>0
            % if there's enough empty rows in newT add them to it:
            if  sum(next_to_add) <= rows_limit-row_count+1
                newT(row_count:row_count+sum(next_to_add)-1,:) = T(next_to_add,:)
                % and update the index vector:
                added = added | strcmp(T.memberId,users_list{1});
            else
                % otherwise - fill the empty rows and quit the loop:
                if row_count <= rows_limit
                    end_to_add = find(next_to_add,rows_limit-row_count+1);
                    newT(row_count:rows_limit,:) = T(end_to_add,:)
                end
                row_count = rows_limit+1; % to exit the outer loop
                break
            end
            row_count = row_count+sum(next_to_add);

            % Add related products:
            % ====================
            % save the first new user to be addaed by related products:
            last_user_row = row_count;
            % get all the products we already added to newT:
            products = unique(newT.productId(1:row_count-1),'stable');
            % although we want only the last user products, because we add all the
            % products the before, our index vector ('added') will eliminate them
            for p = 1:numel(products)
                % get all the product's rows
                next_to_add = strcmp(T.productId,products{p}) & ~added;
                % if there's enough empty rows in newT add them to it:
                if sum(next_to_add)>0
                    if sum(next_to_add) <= rows_limit-row_count+1
                        newT(row_count:row_count+sum(next_to_add)-1,:) = T(next_to_add,:);
                        % and update the index vector:
                        added = added | strcmp(T.productId,products{p});
                    else
                        % otherwise - fill the empty rows and quit the loop:
                        if row_count <= rows_limit
                            end_to_add = find(next_to_add,rows_limit-row_count+1);
                            newT(row_count:rows_limit,:) = T(end_to_add,:);
                        end
                        row_count = rows_limit+1; % to exit the outer loop
                        break
                    end
                end
                row_count = row_count+sum(next_to_add);
            end
        end
        % get the list of new users we just added, and concat to the users
        % left in the original list:
        users_list = [unique(newT.memberId(last_user_row:row_count-1),'stable');
            unique(T.memberId(~added),'stable')];
    end
end

与えるnewT

memberId    productId    Rating
________    _________    ______
'B'         'x'          2     
'B'         'w'          4     
'B'         't'          2     
'A'         'x'          5     
'C'         'x'          5     
'C'         't'          4     
'A'         'y'          1     
'A'         'z'          2     

この実装では、行はユーザーごと、製品ごとに追加されます。次に追加するユーザー/製品に で利用可能な行よりも多くの行がある場合は、必要なだけ行newTを追加します。rows_limitそしてループは終了します。

したがって、 arows_limit = 4;の場合、次のようになりますnewT

memberId    productId    Rating
________    _________    ______
'B'         'x'          2     
'B'         'w'          4     
'B'         't'          2     
'A'         'x'          5     

ユーザー間につながりがあり、各ユーザーの関連製品が新しいユーザーをリストに追加している限り、ループは新しいユーザーのリストに続きますnewT。ただし、他のすべてのノードがそのネットワークの一部であるとは限らないノードから開始する可能性があります。たとえば、上記のコードで使用した拡張例の接続を示す次のグラフ図を見てください。

users_net

ノードDは他のすべてのノードに接続されているわけではないため、関連のない新しいユーザーを で積極的に探さない限り、ノードTに到達することはありません。上記の実装は、この種のユーザーを探します。

于 2016-10-01T21:47:25.453 に答える