Consulting

Page 1 of 2 1 2 LastLast
Results 1 to 20 of 22

Thread: return the top occuring values in a list

  1. #1
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location

    return the top occuring values in a list

    Is there a formula or code that can return the values having the most (say 5 or 10, or perhaps user-defined) number of occurences in a list? Auto-Filter can return the top 10 values, but I want the top occurances, regardless of value.

  2. #2
    Hi

    Are the values being counted numeric, alpha or alpha-numeric?


    Tony

  3. #3
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    the values are numeric.

  4. #4
    Distinguished Lord of VBAX VBAX Grand Master Bob Phillips's Avatar
    Joined
    Apr 2005
    Posts
    25,453
    Location
    One way, assuming numbers are in A1:A20

    B1:=A1
    B2: =IF(ISERROR(MATCH(0,COUNTIF(B$1:B1,$A$1:$A$200&""),0)),"",
    INDEX(IF(ISBLANK($A$1:$A$200),"",$A$1:$A$200),MATCH(0,COUNTIF(B$1:B1,$A$1:$ A$200&""),0)))

    which is an array formula, it should be committed with Ctrl-Shift-Enter, not just Enter.

    Copy B2 down to B20

    C1: =IF($B$1:$B$20<>"",COUNTIF($A$1:$A$20,$B$1:$B$20),"")
    copy down to C20

    You can then use conditional formatting in column B with a formula of =AND(C1<>"",C1>=LARGE($C$1:$C$20,5)) to pick out the most frequent.

  5. #5
    VBAX Expert Shazam's Avatar
    Joined
    Sep 2005
    Posts
    530
    Location
    See if this works.


    Say if your list starts in cell A2. Then in input this formula in cell B2:

    =IF(SUM(COUNTIF($B$1:B1,$A$2:$A$100))=COUNTA($A$2:$A$100),"",INDEX(A2:$A$10 0,MATCH(0,--ISNUMBER(MATCH(A2:$A$100,$B$1:B1,0)),0)))

    and copy it down.




    Then input this formula in cell C2:

    =IF(B2="","",LARGE(COUNTIF(A:A,B$2:B$12),ROW()-1))

    and copy it down.


    Both formulas need to be confirmed with:

    CTRL+SHIFT+ENTER

  6. #6
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    Thanks a lot XLD and Shazan!

    Both are great solutions.

    One thing though, my lists are quite long, and I should probably use a VBA approach so as not to add any more to the file sizes.

    Can you guys convert the above formulas to VBA, where I can then use a command button to exacute the code?

    Thanks again

  7. #7
    Hi

    Another approach would be to use the FREQUENCY function. You will have to determine a unique list of the numbers (many ways to do that), then use frequency to determine the counts per number. Then using the RANK formula along with INDEX / MATCH, you can extract the numbers for as many as required.


    Tony

  8. #8
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    One thing I should have mentioned is that there are other cells/columns related to the list being checked for top occurences, and I'd like to have all of those cells copied over to another location as well (like Advanced Filter). How do I do that?

    Using Shazam's example file, I added a couple columns to show what I mean. VBA or UDF would be fine too.

    Tony, I'm not familiar with the Frequency or Rank functions - can you kindly give me an example.

    Thanks

  9. #9
    VBAX Contributor
    Joined
    Jul 2005
    Posts
    169
    Location
    [vba]
    Sub test()
    Dim dic As Object, a
    Set dic = CreateObject("scripting.dictionary")
    a = Range("c2", Range("c" & Rows.Count).End(xlUp)).Value
    For Each e In a
    If Not IsEmpty(e) Then
    If Not dic.exists(e) Then
    dic.Add e, 1
    Else
    dic(e) = dic(e) + 1
    End If
    End If
    Next
    Range("k2").Resize(dic.Count) = _
    Application.Transpose(dic.keys)
    Range("l2").Resize(dic.Count) = _
    Application.Transpose(dic.items)
    Set dic = Nothing: Erase a
    End Sub
    [/vba]

  10. #10
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    Thanks a lot for your code, Jindon.

    And thanks again to everyone for providing me several approaches that I can use for other similar functions.

  11. #11
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    Shazam,

    I discovered a problem with your code and am hoping you can tell me how to fix it. It seems that the code has a problem with the first number in the list - it always places that first number on the top of the 'Occuring" list even if it is not the most occuring. Any ideas as to how to correct this? (see your attachment)

    Jindon,
    I tried to use your code but need some guidance, if you don't mind.

    XLD,
    your code works great, but it doesn't sort the list in most-occuring to least occuring, which I would prefer. The sort function doesn't work on it since the cells contain formulas rather than values. Is there a way to sort the list in order of occurence (in descending order - most occuring on top)?

    Thanks a lot.

  12. #12
    VBAX Contributor
    Joined
    Jul 2005
    Posts
    169
    Location
    1) hit Alt + F11 to open vb editor
    2) go to [Insert] -> [Module] then paste the code there
    3) click x to close the window to get back to Excel
    4) select the sheet in question then go to [Tools]->[Macro]->[Macros] and choose test thenhit Run

    "test" was assinged to commandbutton in the attached

  13. #13
    Zest

    Just caught up with this.

    I've put in examples of the Frequency, rank and extracting based on a "unique" ranking process.

    Tony

  14. #14
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    Been away a few days.

    Thanks a lot, ACW (Tony)!
    That's great. Is there any way to sort the list by UniqRank or Top10 (an error pops up ("you cannot change part of an array") when I try to sort.


    Thank you too, Jindon.
    I know how to use vba, but the code was somehow not working before, but is works fine now.

    One thing though, I have a few columns I'd like to apply your code to, and be able to rank and sort each one by 'Unique', or 'Occuring'. Is there a way to do that? Can you please tell me what changes I need to make to the code?

    Thanks again for both your help.

  15. #15
    VBAX Expert Shazam's Avatar
    Joined
    Sep 2005
    Posts
    530
    Location
    Hopefuly I got this right. See the attachment below.

  16. #16
    VBAX Regular
    Joined
    Dec 2005
    Posts
    99
    Location
    Your formula works great, Shazam.

    Except, when I changed the list's cell references to a dynamic named range, the formula calculates only the first few values in the list, instead of the entire list. Any ideas why that is, and what's needed?

    Thanks for your help.

  17. #17
    Zest1

    The top 10 is sorted in order of frequency. How do you want this listing sorted? I thought that was the way you wanted them to appear.


    Tony

  18. #18
    VBAX Expert Shazam's Avatar
    Joined
    Sep 2005
    Posts
    530
    Location
    See if this will do.

    I named the formula box List
    =OFFSET(Table!$A$2,,,COUNTA(Table!$A$2:$A$65536))


    Attachment below.
    Last edited by Shazam; 04-19-2006 at 07:00 PM.

  19. #19
    VBAX Contributor
    Joined
    Jul 2005
    Posts
    169
    Location
    Zest1
    if your have multiple columns of data and if it is consecutive

    just change
    a = Range("c2", Range("c" & Rows.Count).End(xlUp)).Value
    to
    a = Range("c2", Range("c" & Rows.Count).End(xlUp)).resize(,2).Value
    resize(,2) expand one more column ,3 to 2 more, 4 to 3 more and so forth

    if you have separate columns then try
    Sub test2()
        Dim dic As Object, a, myRange As Range, msg As String, rng As Range, r As Range
        msg = "Click on the top cell of the data"
        On Error Resume Next
        Do
            If rng Is Nothing Then
                Set myRange = Application.InputBox(msg, Type:=8)
                Set rng = Range(myRange.Cells(1, 1), ActiveSheet.Cells(Rows.Count, myRange.Column).End(xlUp))
            Else
                Set myRange = Application.InputBox(msg, Type:=8)
                Set rng = Union(rng, Range(myRange.Cells(1, 1), _
                    ActiveSheet.Cells(Rows.Count, myRange.Column).End(xlUp)))
            End If
        Loop While Err.Number = 0
        On Error GoTo 0
        If myRange Is Nothing Then Exit Sub
        Set dic = CreateObject("scripting.dictionary")
        For Each r In rng
            If Not IsEmpty(r) Then
                If Not dic.exists(r.Value) Then
                    dic.Add r.Value, 1
                Else
                    dic(r.Value) = dic(r.Value) + 1
                End If
            End If
        Next
        Range("k2").Resize(dic.Count) = _
        Application.Transpose(dic.keys)
        Range("l2").Resize(dic.Count) = _
        Application.Transpose(dic.items)
        Range("k1", Range("k" & Rows.Count).End(xlUp)).Resize(, 2).Sort _
        key1:=Range("l1"), order1:=xlDescending, header:=xlYes
        Set dic = Nothing
    End Sub

  20. #20
    VBAX Wizard lucas's Avatar
    Joined
    Jun 2004
    Location
    Tulsa, Oklahoma
    Posts
    7,323
    Location
    Hi Jindon,
    you said dictionary object was your specialty, I see why..nice one
    Steve
    "Nearly all men can stand adversity, but if you want to test a man's character, give him power."
    -Abraham Lincoln

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •