最頻値について


よし  2008-02-06 04:18:20  No: 100228

Excel2000 VBAで試みているのですが、
最頻値を求める方法を教えて下さい。
現在、MODEという関数を使ってますが、項目が30個までしか求められません。
60個分の値に対して最頻値を求めることを考えています。ので、
現在は10個毎に区切って求めていますが。。。
また、セルからの読込みになってしまうので、内部の配列変数から最頻値を求めるようにもしてみたいです。

何かごちゃごちゃと書いてしまいましたが、
簡単に質問させていただきますと、最頻値を求める方法を教えて下さい。
よろしくお願いします。


紅閃光  URL  2008-02-07 04:18:33  No: 100229

ExcelVBAの最頻値はいわゆる純粋最頻値なので、テストの得点や身長体重などの数値データの集計には不向きです。
まぁ、そんなことはわかってますよね?

ということでExcelのMode関数の個数制限を無くして、内部の配列変数から最頻値を求める関数がなぜか手元にあったのでそのままコピペッ

' 最頻値を求める 
Public Function ModeValue(ByVal Values As Variant) As Double
    Dim i As Long
    Dim LB As Long
    Dim UB As Long
    Dim mCount As Long
    Dim mMaxCount As Long
    
    Call SortValue(Values)    
    LB = LBound(Values)
    UB = UBound(Values)
    
    mCount = 1
    mMaxCount = 0
    ModeValue = Values(LB)
    For i = LB To UB - 1
        If Values(i) = Values(i + 1) Then
            mCount = mCount + 1
        Else
            If mCount > mMaxCount Then
                mMaxCount = mCount
                ModeValue = Values(i)
            End If
            mCount = 1
        End If
    Next
    If mCount > mMaxCount Then
        ModeValue = Values(UB)
    End If
End Function

' 配列をソート
Private Function SortValue(ByRef Values As Variant, Optional ByVal ForDirection As Boolean = True) As Long
    Dim i As Long
    Dim j As Long
    Dim LB As Long
    Dim UB As Long
    Dim mFlag as Long
    Dim mTemp As Variant

    LB = LBound(Values)
    UB = UBound(Values)
    IF UB - LB <= 1 Then
        SortValue = 0
        Exit Function
    End IF

    For i = LB To UB - 1
        For j = LB To LB + UB - i - 1
            mFlag = 0
            IF ForDirection Then
                IF Values(j) > Values(j + 1) Then mFlag = 1
            Else
                IF Values(j + 1) > Values(j) Then mFlag = 1
            End IF
            IF mFlag = 1 Then
                mTemp = Values(j)
                Values(j) = Values(j + 1)
                Values(j + 1) = mTemp
            End If
        Next
    Next
    SortValue = 1
End Function

とはいえこれはあまり使い道は無いと思いますけど。
例えば30人分のテストの得点をこの関数に放りこんであげても、意味の有るデータは帰ってきません。
重複データが無い場合はExcelならN/Aを返すところですが、この関数は最大データを返します。
ぶっちゃけ使い物になりません。

数値データを集計する場合は間隔尺度や比例尺度を用いて度数分布表を作成し、そこから最頻値を求めることになります。

この場合階級には幅が存在するようになるため、最頻値は最大階級の中心値というわけにはいきません。

まぁ、これ以上は質問内容とずれてくるのでひとまず逃亡。


matsu  2008-02-07 22:27:55  No: 100230

>現在、MODEという関数を使ってますが、項目が30個までしか求められません。
>60個分の値に対して最頻値を求めることを考えています。ので、
>現在は10個毎に区切って求めていますが。。。
>また、セルからの読込みになってしまうので、内部の配列変数から最頻値を求めるようにもしてみたいです。

値をダミーのシートにコピーしてセル範囲を指定するのはどうでしょうか?
配列から求める場合は引数に配列を指定すればいけます。

Private Sub test()
    Dim work(50)    As Integer
    Dim i           As Integer
    
    For i = 0 To 50
        work(i) = Rnd * 10
    Next
    
    MsgBox WorksheetFunction.Mode(work)
End Sub


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加