Python 使用日期遍历字典
有谁能帮我在字典中循环使用日期吗?我有这样的数据集Python 使用日期遍历字典,python,date,python-2.7,iteration,Python,Date,Python 2.7,Iteration,有谁能帮我在字典中循环使用日期吗?我有这样的数据集 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
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)}]
我怎样才能把它输入以下格式的词典
res={u'201L':(1,0,1),(2,1,0),(3,0,0),(4,0,0).. so 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)}
其中1、2、3是从发卡日期算起的第一个月、第二个月等,即
对于201L
发行日期为datetime.datetime(2007,12,29,0,0)
,202L
发行日期为datetime.datetime(2007,12,30,0,0)
第一个月是指从2007年12月29日到2008年1月29日
(1,0,1)---where 1 is the first month
0 is no of times W
1 is no of times D
我试过这样的东西
data_dict=defaultdict(Counter)
date_dic={}
for x in data:
a,b,c,d=x['a'],x['c'],x['d'],x['e']
data_dict[b][a] += 1
for key , value in data_dict.items():
date_dic[key] = tuple(map(datetime.date.isoformat, (c,d)))
for value in range(1,30):
if value not x: continue
在if循环之后,我一直被困在上面的格式中,我可以添加什么来获取。我最终得到类似这样的输出
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})})
defaultdict(,{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})
我会创建一个日期列表,然后找到“bucket”将每个项目放入该列表中
您可以使用以下命令从起点创建新的相对日期:
现在,您有12个日期来比较所有其他日期,因此您知道将每个后续值放入哪个存储桶:
>>> 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)]
然后,我们可以使用查找匹配的存储桶:
from bisect import bisect
bisect(buckets, somedate) - 1 # Returns a value from 0 - 11
我们为每个用户创建这样的存储桶,因此我们需要在单独的映射中跟踪存储桶。我们将根据需要动态创建bucket,以适应当前事务日期
接下来,我们使用a跟踪每个键的计数(输入中的键c
):
这将为您的存储桶创建一个列表,并为存款和取款创建一个空的计数字典。我在这里使用了字典,因为它比以后处理(不可变)元组要容易得多。我也没有包括月数(1-12);没有意义,您已经为每个bucket(0-11)建立了一个索引,并且您可以拥有可变数量的bucket
我们需要根据需要创建桶和计数器,以适应当前日期;我们不需要扫描数据来查找每个用户的最大交易日期,而是根据需要展开存储桶和计数列表:
def expand_buckets(buckets, bucket_counts, start, transaction):
# This function modifies the buckets and bucket_counts lists in-place
if not buckets:
# initialize the lists
buckets.append(start)
bucket_counts.append(dict(empty_counts))
# keep adding 30-day spans until we can fit the transaction date
while buckets[-1] + datetime.timedelta(days=30) < transaction:
buckets.append(buckets[-1] + datetime.timedelta(days=30))
bucket_counts.append(dict(empty_counts))
调用bisect
可以轻松快速地选择正确的桶
示例输入的结果是:
>>> 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}]}
我看到用户
204L
有2个发卡日期;在这种情况下,您可能需要重新计算每个事务的存储桶?目前,我的回答假设每个用户只有一个开始日期,我们可以改为每个发行日期缓存存储桶。因此,对于204L
,取款时间为第三个30天,但与新发行日期相比,存款位于第六个存储桶,而不是我当前代码将其放入的第七个存储桶。你能确认吗?我们可以根据需要扩展存储桶,我会更新。你也可以迭代v
;这只是一个常规的Python列表;如果在第一个月之后没有活动,则没有第二个桶。使用try
,除了indexer
来处理这些,并将该用户当月的计数设置为0。每个用户的buckets=defaultdict(lambda:user\u buckets(entry['d'))
也可以工作。@J.F.Sebastian:这假定条目当时在本地范围内;我更喜欢这里的显式处理。
def expand_buckets(buckets, bucket_counts, start, transaction):
# This function modifies the buckets and bucket_counts lists in-place
if not buckets:
# initialize the lists
buckets.append(start)
bucket_counts.append(dict(empty_counts))
# keep adding 30-day spans until we can fit the transaction date
while buckets[-1] + datetime.timedelta(days=30) < transaction:
buckets.append(buckets[-1] + datetime.timedelta(days=30))
bucket_counts.append(dict(empty_counts))
per_user_buckets = defaultdict(list)
for 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
>>> 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}]}