# Create a list that shows values that did and did not occur

I have a set of data

data = {1, 1, 2, 2, 4, 4, 4}


and another set of data

datakey = {1, 2, 3, 4, 5, 6}


I then use CountBy[] and Sort[] to sort data[] into ascending order and to show count of data[] against datakey[]

CountsBy[Sort[data], datakey]


Running this shows

<|{1, 2, 3, 4, 5, 6}[1] -> 2, {1, 2, 3, 4, 5, 6}[2] ->  2, {1, 2, 3, 4, 5, 6}[4] -> 3|>


This shows that there are 2 amounts of 1, 2 amounts of 2 etc.

I have tried a similar approach using Tally[]

Tally[Sort[data]]


which returns

{{1, 2}, {2, 2}, {4, 3}}


What i would like to show is a list that contains the counts of what is present and not present.

Such that it shows

<|[1] -> 2, [2] -> 2, [3] -> 0, [4] -> 3|>

Where it shows the counts of what is in the list and what isnt.

• You might need Tally. Commented Mar 27, 2020 at 11:54
• Something like AssociationThread[datakey, Lookup[Counts[data], datakey, 0]] or Merge[{AssociationThread[datakey, 0], Counts[data]}, Max]? Commented Mar 27, 2020 at 11:56
• Maybe you will find PositionIndex useful... Commented Mar 27, 2020 at 12:01
• @J.M.'stechnicaldifficulties this works perfectlty, thank you for your help. Commented Mar 27, 2020 at 12:09

As recommended by @J.M.'stechnicaldifficulties

AssociationThread[datakey, Lookup[Counts[data], datakey, 0]]


produces the result

<|1 -> 2, 2 -> 2, 3 -> 0, 4 -> 3, 5 -> 0, 6 -> 0|>


I think you will find the following much faster for large cases.

With[{t = Tally[Join[datakey, data]]}, Transpose[Transpose[t] - {0, 1}]]


For example:

data = RandomChoice[RandomInteger[{1, 1000000}, 1000000], 10000000];
datakey = Range@1000000;
Length@Union@data