4

特定の日付 (mm-dd-yyyy-hour-minute) の各オブジェクトの数を示す次のようなリストがあるとします。

A = [
 [
    ['07-07-2012-21-04', 'orange', 1],
    ['08-16-2012-08-57', 'orange', 1],
    ['08-18-2012-03-30', 'orange', 1],
    ['08-18-2012-03-30', 'orange', 1],
    ['08-19-2012-03-58', 'orange', 1],
    ['08-19-2012-03-58', 'orange', 1],
    ['08-19-2012-04-09', 'orange', 1],
    ['08-19-2012-04-09', 'orange', 1],
    ['08-19-2012-05-21', 'orange', 1],
    ['08-19-2012-05-21', 'orange', 1],
    ['08-19-2012-06-03', 'orange', 1],
    ['08-19-2012-07-51', 'orange', 1],
    ['08-19-2012-08-17', 'orange', 1],
    ['08-19-2012-08-17', 'orange', 1]
 ],
 [
    ['07-07-2012-21-04', 'banana', 1]
 ],
 [
    ['07-07-2012-21-04', 'mango', 1],
    ['08-16-2012-08-57', 'mango', 1],
    ['08-18-2012-03-30', 'mango', 1],
    ['08-18-2012-03-30', 'mango', 1],
    ['08-19-2012-03-58', 'mango', 1],
    ['08-19-2012-03-58', 'mango', 1],
    ['08-19-2012-04-09', 'mango', 1],
    ['08-19-2012-04-09', 'mango', 1],
    ['08-19-2012-05-21', 'mango', 1],
    ['08-19-2012-05-21', 'mango', 1],
    ['08-19-2012-06-03', 'mango', 1],
    ['08-19-2012-07-51', 'mango', 1],
    ['08-19-2012-08-17', 'mango', 1],
    ['08-19-2012-08-17', 'mango', 1]
 ]

]

A で行う必要があるのは、各オブジェクトの欠落しているすべての日付 (A の最小日付から最大日付まで) を値 0 で埋めることです。欠落している日付とそれに対応する値 (0) が入力されたら、合計したいサブリストごとに、日付が繰り返されないように、各日付の値を上げます。

今、私がやろうとしていることは次のとおりです: A の日付と値を (u と v という名前のリストで) 別々に分割し、各サブリストを pandas シリーズに変換し、それぞれのインデックスをそれらに割り当てます。したがって、各zip(u、v)について:

def generate(values, indices):

    indices = flatten(indices)

    date_index = DatetimeIndex(indices)
    ts = Series(values, index=date_index)

    ts.reindex(date_range(min(date_index), max(date_index)))

    return ts

しかし、ここでは、インデックスの再作成によって例外が発生しています。私が探しているのは、完全にリスト内包表記または numpy 配列に基づいている (パンダを使用しない) 純粋に Pythonic な方法です。

時間単位での集計には別の問題があります。つまり、すべての日付が同じで時間だけが異なる場合、1 日の不足しているすべての時間を入力してから、1 時間ごとに同じ集計プロセスを繰り返します。欠落している時間は 0 の値で埋められます。

前もって感謝します。

4

1 に答える 1

2

これはどうですか:

from collections import defaultdict, OrderedDict                              
from datetime import datetime, timedelta                                      
from itertools import chain, groupby                                          

flat = sorted((datetime.strptime(d, '%m-%d-%Y-%H-%M').date(), f, c)           
              for (d, f, c) in chain(*A))                                     
counts = [(d, f, sum(e[2] for e in l))                                        
          for (d, f), l                                                       
          in groupby(flat, key=lambda t: (t[0], t[1]))]                       

# lets assume that there are some data                                        
start = counts[0][0]                                                          
end = counts[-1][0]                                                           
result = OrderedDict((start+timedelta(days=i), defaultdict(int))             
                     for i in range((end-start).days+1))                      
for day, data in groupby(counts, key=lambda d: d[0]):                         
    result[day].update((f, c) for d, f, c in data)

私の質問は:本当に存在しない日付を埋める必要がありますか? これが大量のデータであり、危険な量のデータでさえある状況を簡単に想像できます...それらをどこかにリストしたい:

from collections import defaultdict                                           
from datetime import datetime, timedelta                                      
from itertools import chain, groupby                                          

def aggregate(data, resolution='daily'):                                      
    assert resolution in ['hourly', 'daily']                                  
    if resolution == 'hourly':                                                
        round_dt = lambda dt: dt.replace(minute=0, second=0, microsecond=0)   
    else:                                                                     
        round_dt = lambda dt: dt.date()                                       

    flat = sorted((round_dt(datetime.strptime(d, '%m-%d-%Y-%H-%M')), f, c)    
                  for (d, f, c) in chain(*A))                                 
    counts = [(d, f, sum(e[2] for e in l))                                    
              for (d, f), l                                                   
              in groupby(flat, key=lambda t: (t[0], t[1]))]
    result = {}                                                              
    for day, data in groupby(counts, key=lambda d: d[0]):                    
        d = result[day] = defaultdict(int)                                   
        d.update((f, c) for d, f, c in data)                                 
    return result                                                            

def xaggregate(data, resolution='daily'):                                      
    aggregated = aggregate(data, resolution)                                 
    curr = min(aggregated.keys())                                            
    end = max(aggregated.keys())                                             
    interval = timedelta(days=1) if resolution == 'daily' else timedelta(seconds=3600)
    while curr <= end:
        # None is sensible value in case of missing data I think                                                       
        yield curr, aggregated.get(curr)                   
        curr += interval                                                                                 

一般に、私の提案は、リストを順序付けられた構造として使用しないことです (つまり、['07-07-2012-21-04', 'mango', 1])。tupleその方がこの目的には適していると思いますし、もちろんcollections.namedtupleそれはさらに望ましいことです。

于 2013-09-01T13:24:24.497 に答える