グループとメンバーのテーブルで、グループごとにメンバーの特定の割合を減らすにはどうすればよいでしょうか?

グループとメンバーのテーブルで、グループごとにメンバーの特定の割合を減らすにはどうすればよいでしょうか?

グループとメンバーの表を含む Excel スプレッドシートがあります。例:

A Jonathan
A Roger
A Donald
B John
B Lilya
C Richard
C Lorry

私がやりたいのは、グループあたりのメンバー数を、たとえば 60% 削減することです。どのメンバーが除外されるかは問題ではありません。たとえば、グループ B には 2 人のメンバーが含まれているので、1 人のメンバーを削除します (2*0.6=1.2 なので、切り捨てられる必要がありますが、0.5 を超える場合は切り上げます)。

Excelの数式で実行することは可能ですか?

答え1

@EngineerToast が示したようなピボット テーブルは、これを行うためのはるかに簡単な方法です。しかし、私はとんでもなく過剰に設計された優れたソリューションが大好きなので、VBA でそれを実行する 1 つの方法を次に示します。辞書を使用して複雑にしすぎたのではないかと思います。おそらく、他の簡単なカウントを使用して、すでに使用されている文字を配列に追加するだけでも実行できたでしょうが、これが現状です。

Public Sub ReduceMembers()
    Dim GroupColumn: GroupColumn = 1                        'Original column containing your Groups
    Dim MemberColumn: MemberColumn = 2                      'Original column containing your Members
    Dim ReductionAmount: ReductionAmount = 0.6              'Percentage as a decimal fraction
    Range("D1").Select                                      'Start cell for your new columns

    Dim LastRow: LastRow = GetLastRow(GroupColumn)
    Dim Dictionary, DictionaryKey, I
    Set Dictionary = CreateObject("Scripting.Dictionary")

    For I = 1 To LastRow
        Dim Value: Value = Cells(I, GroupColumn).Value
        If Dictionary.Exists(Value) Then
            Dictionary(Value) = Dictionary(Value) + 1
        Else
            Dictionary.Add Value, 1
        End If
    Next

    For Each DictionaryKey In Dictionary.Keys
        Dim MaxAmount: MaxAmount = Math.Round(Dictionary(DictionaryKey) * ReductionAmount, 0)
        Dim CurrentAmount: CurrentAmount = 0
        For I = 1 To LastRow
            If Cells(I, GroupColumn) = DictionaryKey Then
                If CurrentAmount >= MaxAmount Then
                    Exit For
                End If
                ActiveCell.Value = DictionaryKey
                ActiveCell.Offset(0, 1).Value = Cells(I, MemberColumn).Value
                ActiveCell.Offset(1, 0).Select

                CurrentAmount = CurrentAmount + 1
            End If
        Next
    Next

End Sub

Function GetLastRow(GroupColumn)
    Dim Count
    Count = 0
    Do
        Count = Count + 1
    Loop Until IsEmpty(Cells(Count, GroupColumn).Value)
    GetLastRow = Count - 1
End Function

ここに画像の説明を入力してください

答え2

1 回限りのアクションの場合は、ピボット テーブルを使用してこれを行うことができます。頻繁に実行する必要がある場合、この方法は扱いにくくなる可能性があります。

最終スクリーンショット

まず、列見出しを追加します。私はGroupと を使用しましたName。リスト内の任意のセルを選択し、[挿入] リボン (左端のボタン) の [ピボット テーブル] をクリックします。

ステップ2

それすべきピボットテーブルを適用する範囲を自動的に推測します。「OK」をクリックするだけで、ピボットテーブルが新しいシートに追加されます。次に、フィールドを追加しGroupNameフィールドリストから行リストにドラッグしてテーブルの行部分に追加します。何か値の部分に追加しないと、上位パーセントをフィルタリングできません。

ステップ3

ピボット テーブル内の名前の 1 つを右クリックし、[フィルター] > [上位 10 件...] をクリックします。

ステップ4

フィルターを必要に応じて設定し、「OK」をクリックします。

ステップ5

元のデータに似た外観にするには、テーブルを右クリックし、[ピボット テーブル オプション] に移動して [表示] タブで [クラシック ピボット テーブル レイアウト] をオンにします。次に、ピボット テーブル内のグループの 1 つを右クリックし、[フィールド設定] をクリックします。[小計] を [なし] に設定し、[レイアウトと印刷] タブで [アイテム ラベルの繰り返し] をオンにします。

ステップ6

関連情報