5
$\begingroup$

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.

Thank you for your time,

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

2 Answers 2

7
$\begingroup$

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|>

Thank you for your help.

$\endgroup$
4
$\begingroup$

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

r1 = AssociationThread[datakey, 
    Lookup[Counts[data], datakey, 0]]; // AbsoluteTiming
r2 = With[{t = Tally[Join[datakey, data]]}, 
    Transpose[Transpose[t] - {0, 1}]]; // AbsoluteTiming

(r1 // Values) == r2[[All, 2]]

2.14736

0.176966

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.