【问题标题】:aggregate and sum daily data to month in python在python中将每日数据汇总并汇总到月份
【发布时间】:2014-07-24 19:53:42
【问题描述】:

我在 Python 中有一个二维列表,其中包含一天的纪元秒数和相应的值。我需要将此列表聚合成一个 json 月份数组以及所有相应每日值的总和。

python 列表如下所示:

array = [[1230768000000, 23], [1244073599000, 5], [1269206974000, 8], [1291908086000, 23]...]

我需要将它 jsonify 成一个如下所示的 json 数组:

[{key:'2009-01',value:28},{key:'2009-02',value:324} ... ]

我已经尝试了以下代码,但它并不能完全输出我需要的内容。

month_aggregate = defaultdict(list)
for [d,v] in array:
  truncated = int(str(d)[:-3])
  year_month = datetime.utcfromtimestamp(truncated).date().isoformat()[:-3]
  month_aggregate[year_month].append(v)

>> {'2011-08': [559, 601, 545, 578], '2011-09': [572, 491, 595], ... }

非常感谢提示

【问题讨论】:

  • @ZJS 我同意...导入 panda 并为如此小的一次性任务创建一个数据框似乎有点矫枉过正。

标签: python json arraylist grouping aggregate


【解决方案1】:

试试这个:

array = [[1230768000000, 23], [1244073599000, 5], [1269206974000, 8], [1291908086000, 23]]

month_aggregate = dict()
for [d,v] in array:
    truncated = int(str(d)[:-3])    
    year_month = datetime.utcfromtimestamp(truncated).date().isoformat()[:-3]
    # If the entry was not present previously create one with the current value v
    if not month_aggregate.has_key(year_month):
        month_aggregate[year_month] = v
    else:
        # Otherwise add the value to the previous entry
        month_aggregate[year_month] += v

# Create a JSON Array from the month_aggregate dictionary
month_aggregate_json_list = [ {'value':v, 'key':k} for k, v in month_aggregate.iteritems() ]
print month_aggregate_json_list

给这个

[{'key': '2009-01', 'value': 23}, {'key': '2009-06', 'value': 5}, {'key': '2010-03', 'value': 8}, {'key': '2010-12', 'value': 23}]

【讨论】:

  • 不错的答案...然后我应该能够 jsonify() Flask 中的最终列表?
【解决方案2】:

这正是 itertools 中的 groupby 的用途。 Group by 返回迭代器,该迭代器将使用给定函数来确定项目所属的组,并为每个组返回一个迭代器,该迭代器迭代该组中的所有项目。

from itertools import groupby
from time import gmtime, strftime 
# gmtime uses the UTC timezone, use the function localtime if preferred

def get_year_month_from_datum((millis, _value)):
    return strftime("%Y-%m", gmtime(millis / 1000))

aggregate = {key: sum(value for _time, value in values)
    for key, values in groupby(array, get_year_month_from_datum)} 

json_aggr = [{"key": key, "value": sum(value for _time, value in values)} 
    for key, values in groupby(array, get_year_month_from_datum)]

groupby 函数假定输入数组已经根据分组值排序,如果没有,则按 sorted(array) 而不是 array 分组将起作用。

【讨论】:

    【解决方案3】:

    以下答案使用 Collections 中的 Counter 类,这可能是解决此问题的最佳/最快数据类型

    from operator import add
    from collections import Counter
    
    l = [[1230768000000, 23], [1244073599000, 5], [1269206974000, 8], [1291908086000, 23]]
    
    getDate = lambda x: time.strftime('%Y-%m', time.localtime(x/1000))
    counter = reduce(add,[Counter({getDate(key):val}) for key,val in l])
    

    此时,如果您真的想将所有信息转换回 json,那么您就有了一个不错的 Collections 数据类型,只需使用列表推导...

    json = [{'key':k,'value':v} for k,v in counter.iteritems()]
    

    【讨论】:

      【解决方案4】:

      尝试使用集合中的计数器。前几天我发现了它,它很有用。

      from collections import Counter
      month_aggregate = Counter()
      for [d,v] in array:
          truncated = int(str(d)[:-3])
          year_month = datetime.utcfromtimestamp(truncated).date().isoformat()[:-3]
          month_aggregate[year_month] += v
          [{"key":k, "value":v} for k,v in month_aggregate.items()]
      

      给出:

      [{'key': '2009-06', 'value': 5},
       {'key': '2010-03', 'value': 8},
       {'key': '2010-12', 'value': 23},
       {'key': '2009-01', 'value': 23}]
      

      【讨论】:

      • 这很接近了...我以前从未听说过 Counter() 但现在才开始使用它并喜欢它...如果您通过迭代 month_aggregate.items 冲出了答案创建一个 json 数组,我会把它给你
      猜你喜欢
      • 2011-07-09
      • 2011-08-28
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 2021-02-23
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多