聚合 Tally 计数器 [英] Aggregating Tally counters

查看:38
本文介绍了聚合 Tally 计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很多时候我发现自己用 Tally[ ] 计算出现次数,然后,一旦我丢弃了原始列表,就不得不将另一个列表中的结果添加(并加入)到该计数器列表中.

Many times I find myself counting occurrences with Tally[ ] and then, once I discarded the original list, having to add (and join) to that counters list the results from another list.

这通常发生在我计算配置、出现次数、进行一些离散统计等时.

This typically happens when I am counting configurations, occurrences, doing some discrete statistics, etc.

所以我为 Tally 聚合定义了一个非常简单但方便的函数:

So I defined a very simple but handy function for Tally aggregation:

aggTally[listUnTallied__List:{}, 
         listUnTallied1_List,
         listTallied_List] := 
 Join[Tally@Join[listUnTallied, listUnTallied1], listTallied] //. 
     {a___, {x_, p_}, b___, {x_, q_}, c___} -> {a, {x, p + q}, b, c};

这样

l = {x, y, z}; lt = Tally@l;
n = {x};
m = {x, y, t};

aggTally[n, {}]
  {{x, 1}}

aggTally[m, n, {}]
  {{x, 2}, {y, 1}, {t, 1}}

aggTally[m, n, lt]
  {{x, 3}, {y, 2}, {t, 1}, {z, 1}}

这个函数有两个问题:

1) 性能

Timing[Fold[aggTally[Range@#2, #1] &, {}, Range[100]];]
  {23.656, Null}
(* functional equivalent to *)
Timing[s = {}; j = 1; While[j < 100, s = aggTally[Range@j, s]; j++]]
  {23.047, Null}

2) 它不会验证最后一个参数是 real Tallyed list 还是 null(不过对我来说不太重要)

2) It does not validate that the last argument is a real Tallied list or null (less important for me, though)

有没有简单、优雅、更快、更有效的解决方案?(我明白这些要求太多了,但愿是免费的)

Is there a simple, elegant, faster and more effective solution? (I understand that these are too many requirements, but wishing is free)

推荐答案

也许,这会满足您的需求?

Perhaps, this will suit your needs?

aggTallyAlt[listUnTallied__List : {}, listUnTallied1_List, listTallied : {{_, _Integer} ...}] :=
{#[[1, 1]], Total@#[[All, 2]]} & /@ 
       GatherBy[Join[Tally@Join[listUnTallied, listUnTallied1], listTallied], First]

时间要好得多,并且对最后一个参数进行了基于模式的检查.

The timings are much better, and there is a pattern-based check on the last arg.

这是一个更快的版本:

aggTallyAlt1[listUnTallied__List : {}, listUnTallied1_List, listTallied : {{_, _Integer} ...}] :=
Transpose[{#[[All, 1, 1]], Total[#[[All, All, 2]], {2}]}] &@
   GatherBy[Join[Tally@Join[listUnTallied, listUnTallied1], listTallied], First]

时间:

In[39]:= Timing[Fold[aggTallyAlt1[Range@#2, #1] &, {}, Range[100]];]
Timing[s = {}; j = 1; While[j < 100, s = aggTallyAlt1[Range@j, s]; j++]]

Out[39]= {0.015, Null}

Out[40]= {0.016, Null}

这篇关于聚合 Tally 计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆