python - Iterating through a dictionary using dates -
can 1 me how iterate through dictionary dates, have data set this
data=[{u'a': u'd', u'b': 100.0, u'c': 201l, u'd': datetime.datetime(2007, 12, 29, 0, 0), u'e': datetime.datetime(2008, 1, 1, 6, 27, 41)}, {u'a': u'w', u'b': 100.0, u'c': 201l, u'd': datetime.datetime(2007, 12, 29, 0, 0), u'e': datetime.datetime(2008, 2, 4, 6, 27, 41)}, {u'a': u'w', u'b': 100.0, u'c': 202l, u'd': datetime.datetime(2007, 12, 30, 0, 0), u'e': datetime.datetime(2008, 1, 1, 4, 20, 44)}, {u'a': u'd', u'b': 100.0, u'c': 202l, u'd': datetime.datetime(2007, 12, 30, 0, 0), u'e': datetime.datetime(2008, 3, 11, 6, 27, 41)}, {u'a': u'd', u'b': 100.0, u'c': 202l, u'd': datetime.datetime(2007, 12, 30, 0, 0), u'e': datetime.datetime(2008, 5, 8, 11, 2, 41)}, {u'a': u'd', u'b': 100.0, u'c': 203l, u'd': datetime.datetime(2008, 1, 2, 0, 0), u'e': datetime.datetime(2008, 6, 1, 6, 27, 41)}, {u'a': u'w', u'b': 100.0, u'c': 204l, u'd': datetime.datetime(2008, 2, 9, 0, 0), u'e': datetime.datetime(2008, 4, 21, 12, 30, 51)}, {u'a': u'd', u'b': 100.0, u'c': 204l, u'd': datetime.datetime(2008, 2, 9, 0, 0), u'e': datetime.datetime(2008, 8, 15, 15, 45, 10)}]
how can bring dictionary of below format
res={u'201l':(1,0,1),(2,1,0),(3,0,0),(4,0,0).. on till (12,0,0), u'202l':(1,1,0),(2,0,0),(3,0,1),(4,0,0),(5,0,1)...(12,0,0), u'203l':(1,0,0),(2,0,0),(3,0,0),(4,0,0),(5,1,0)...(12,0,0), u'204l':(1,0,0),(2,0,0),(3,0,0),(4,1,0),(5,0,0),(6,0,0,(7,0,0),(8,0,1)...(12,0,0)}
where 1, 2, 3 first, second month , on card issue date i.e 201l
issue date datetime.datetime(2007, 12, 29, 0, 0)
, 202l
datetime.datetime(2007, 12, 30, 0, 0)
first month means 2007-12-29
2008-1-29
(1,0,1)---where 1 first month 0 no of times w 1 no of times d
i tried
data_dict=defaultdict(counter) date_dic={} x in data: a,b,c,d=x['a'],x['c'],x['d'],x['e'] data_dict[b][a] += 1 key , value in data_dict.items(): date_dic[key] = tuple(map(datetime.date.isoformat, (c,d))) value in range(1,30): if value not x: continue
i have been stuck after if loop can add in above format.i end getting output,
defaultdict(<class 'collections.counter'>, {201l: counter({u'd': 1, u'w': 1}), 202l: counter({u'd': 2, u'w': 1}), 203l: counter({u'd': 1}), 204l: counter({u'd': 1, u'w': 1})})
i'd create list of dates, find 'bucket' put each item list.
you can create new dates relative starting point using datetime.timedelta()
objects:
startdate = data[0]['d'] buckets = [startdate + datetime.timedelta(days=30) * in xrange(12)]
now have 12 dates compare else against, know bucket put each subsequent value in:
>>> buckets [datetime.datetime(2007, 12, 29, 0, 0), datetime.datetime(2008, 1, 28, 0, 0), datetime.datetime(2008, 2, 27, 0, 0), datetime.datetime(2008, 3, 28, 0, 0), datetime.datetime(2008, 4, 27, 0, 0), datetime.datetime(2008, 5, 27, 0, 0), datetime.datetime(2008, 6, 26, 0, 0), datetime.datetime(2008, 7, 26, 0, 0), datetime.datetime(2008, 8, 25, 0, 0), datetime.datetime(2008, 9, 24, 0, 0), datetime.datetime(2008, 10, 24, 0, 0), datetime.datetime(2008, 11, 23, 0, 0)]
we can use bisect
module find matching bucket:
from bisect import bisect bisect(buckets, somedate) - 1 # returns value 0 - 11
we create such buckets per user need keep track of buckets in separate mapping. we'll create buckets on fly needed fit current transaction date.
next, use collections.defaultdict
instance track per-key tallies (key c
in input):
from collections import defaultdict res = defaultdict(list) empty_counts = {'d': 0, 'w': 0}
this creates list buckets hold, , empty counts dictionary deposits , withdrawals. used dictionary here because much easier work having manipulate (immutable) tuples later on. did not include month number (1 - 12); no point, have index each bucket (0 - 11), , can have variable number of buckets.
we need create buckets , counters needed fit current date in; instead of scanning throuh data find max transaction date per user expand our buckets , counts list needed:
def expand_buckets(buckets, bucket_counts, start, transaction): # function modifies buckets , bucket_counts lists in-place if not buckets: # initialize lists buckets.append(start) bucket_counts.append(dict(empty_counts)) # keep adding 30-day spans until can fit transaction date while buckets[-1] + datetime.timedelta(days=30) < transaction: buckets.append(buckets[-1] + datetime.timedelta(days=30)) bucket_counts.append(dict(empty_counts))
now can start counting:
per_user_buckets = defaultdict(list) entry in data: user = entry['c'] type = entry['a'] transaction_date = entry['e'] buckets = per_user_buckets[user] bucket_counts = res[user] expand_buckets(buckets, bucket_counts, entry['d'], transaction_date) # count transaction date entries per bucket bucket = bisect(buckets, transaction_date) - 1 bucket_counts[bucket][type] += 1
the bisect
call makes picking right bucket easy , fast.
the result example input is:
>>> pprint(dict(res)) {201l: [{'d': 1, 'w': 0}, {'d': 0, 'w': 1}], 202l: [{'d': 0, 'w': 1}, {'d': 0, 'w': 0}, {'d': 1, 'w': 0}, {'d': 0, 'w': 0}, {'d': 1, 'w': 0}], 203l: [{'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 1, 'w': 0}], 204l: [{'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 0, 'w': 1}, {'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 0, 'w': 0}, {'d': 1, 'w': 0}]}
Comments
Post a Comment