我是python的新手,正在学习如何以正确的方式做事。
我有词典列表d
。每个字典代表用户,并包含user_id,age等信息。此列表d
可以包含几个代表同一用户的字典(但信息略有不同,这与我的目的无关)。我想创建直方图,显示给定年龄的d
中有多少用户。如何以有效的方式做到这一点?
编辑: 我想强调一点,我需要消除列表中的重复项。
答案 0 :(得分:3)
嗯,解决这个问题的经典方法是创建一个defaultdict:
import collections
histogram = collections.defaultdict(int)
然后遍历列表中的字典,并(使用d_list
而不是d
作为字典列表的名称),
for d in d_list:
histogram[d['age']] += 1
但是你包含了令我困惑的其他信息。你说多个dicts可以代表同一个用户。你想从直方图中消除那些重复吗?如果这是您的问题,一种方法是使用user_records
元组作为键将用户存储在(firstname, lastname)
的词典中。然后,表示同一用户的连续词典将相互粉碎,并且每个用户仅保留一个记录。然后迭代 字典中的值(可能使用user_records.itervalues()
)。
可以修改此一般方法,以使用每个记录中的最佳值来识别唯一用户。如果user_id
值对于每个用户是唯一的,则将其用作密钥而不是(firstname, lastname)
。但是你的问题(对我来说)user_id
对于两个相同的用户来说不一定是相同的。
如果你有删除的重复项,如果你使用的是Python> = 2.7,那么还有一个快捷方式:
histogram = collections.Counter(d['age'] for d in user_records.itervalues())
一些示例代码...说我们有一个record_list
:
>>> record_list
[{'lastname': 'Mann', 'age': 23, 'firstname': 'Joe'},
{'lastname': 'Moore', 'age': 23, 'firstname': 'Alex'},
{'lastname': 'Sault', 'age': 33, 'firstname': 'Marie'},
{'lastname': 'Mann', 'age': 23, 'firstname': 'Joe'}]
>>> user_ages = dict(((d['firstname'], d['lastname']), d['age']) for d in record_list)
>>> user_ages
{('Joe', 'Mann'): 23, ('Alex', 'Moore'): 23, ('Marie', 'Sault'): 33}
如您所见,record_list
有重复,但user_ages
字典没有。现在计算年龄就像通过Counter
运行值一样简单。
>>> collections.Counter(user_ages.itervalues())
Counter({23: 2, 33: 1})
可以使用任何可以作为特定用户的唯一标识符的字符串或不可变对象来完成同样的事情。
答案 1 :(得分:2)
您可以使用itertools.groupby
将所有具有相同年龄的词典分组,然后只计算这些列表的长度。
例如:
import itertools
l = [{'user_id': 1, 'age': 20},
{'user_id': 2, 'age': 21},
{'user_id': 3, 'age': 21},
{'user_id': 4, 'age': 20},
{'user_id': 5, 'age': 21},
{'user_id': 6, 'age': 21},
]
def get_age(d):
return d.get('age')
print [(age, len(list(group)))
for age, group in itertools.groupby(sorted(l, key=get_age),
key=get_age)]
示例输出:
[(20, 2), (21, 5)]
注意:正如@Dougal所指出的,列表必须是sorted
。否则itertools.groupby
将无法正常工作。
答案 2 :(得分:-2)
试图改进@ senderle的答案,希望我能更好地理解这个问题。
我假设列表包含字典,其中键是用户ID,数据是具有age
属性的对象:
import collections
# Merge all dictionaries to one uid->age mapping (I'm sure there's a shorter way)
all_ages={}
for d1 in d:
for uid,data in d1.iteritems():
all_ages[uid]=data.age
# Count distinct users per age
histogram = collections.defaultdict(int)
for uid,age in all_ages.iteritems():
histogram[age]+=1