我有这个csv.file。假设我已经使用过DictReader
,现在我有了一些充满字典的列表,例如('name': 'Andrew'), ('points': 18)
等。
name points
Andrew 18
Kate 10
Jack 55
Andrew 31
Andrew 100
Jack 58
Andrew 34
Kate 22
Jack 5
Andrew 72
我想要做的是返回一个键值对,例如Andrew: (5, 100)
,其中值是:
我的第一个任务没有问题,但是找不到解决方案 对于第二个。那就是我试图做的:
name_counter = defaultdict(int)
max_points = defaultdict(int)
for dictionary in list_from_csv:
name_counter[dictionary['name']] += 1 #every time I meet the name, I add +1 to the value
max_points[dictionary['name']] = ???
我当时想只使用max(dictionary[points])
,但max应该从数字中选择,而不仅仅是一个。也许创建一个列表,但是不确定如何创建。还有其他想法吗?
不胜感激。
P.S。在我拥有这两个字典之后,我将需要根据密钥将它们合并,但是我希望它不会那么难。
答案 0 :(得分:2)
每次获取新值时,您只需要弄清楚该怎么做max_points[name]
,对吗?
让我们假设,max_points[name]
在每次迭代中都已正确设置为到目前为止所看到的最高值。那么,您需要如何处理新值?
简单:如果points
大于您到目前为止所看到的最大值,则为新的最大值;如果不是,则旧的最高值是新的最高值。
max
正是这样做的。所以:
max_points[dictionary['name']] = max(max_points[dictionary['name']], points)
现在我们只需要验证该假设是正确的。
因为您使用的是defaultdict(int)
,所以它总是从0开始。如果您的分数可能为负,那已经是错误的了,但否则,这是正确的-迄今为止您看到的最高分数,对于任何人,都是0。
在每个步骤中,如果在上一步中是正确的,则在下一步之后是正确的,因为max
就是这样做的。
因此,归纳起来,最后是正确的。
作为一个补充说明,与其一遍又一遍地重复dictionary['name']
,不如说看起来更好:
for dictionary in list_from_csv:
name = dictionary['name']
name_counter[name] += 1
max_points[name] = max(max_points[name], points)
答案 1 :(得分:0)
您可以使用itertools.groupby
:
import itertools
data = [{'name': 'Andrew', 'points': 18}, {'name': 'Kate', 'points': 10}, {'name': 'Jack', 'points': 55}, {'name': 'Andrew', 'points': 31}, {'name': 'Andrew', 'points': 100}, {'name': 'Jack', 'points': 58}, {'name': 'Andrew', 'points': 34}, {'name': 'Kate', 'points': 22}, {'name': 'Jack', 'points': 5}, {'name': 'Andrew', 'points': 72}]
grouped_data = [[a, list(b)] for a, b in itertools.groupby(sorted(data, key=lambda x:x['name']), key=lambda x:x['name'])]
final_data = [{a:(len(b), max(b, key=lambda x:x['points'])['points'])} for a, b in grouped_data]
输出:
[{'Andrew': (5, 100)}, {'Jack': (3, 58)}, {'Kate': (2, 22)}]
答案 2 :(得分:0)
为完整起见,这是第三方熊猫一线客:
res = df.groupby('name')['points'].agg(['size', 'max'])
结果
print(res)
size max
name
Andrew 5 100
Jack 3 58
Kate 2 22
设置
import pandas as pd
from io import StringIO
mystr = StringIO("""name points
Andrew 18
Kate 10
Jack 55
Andrew 31
Andrew 100
Jack 58
Andrew 34
Kate 22
Jack 5
Andrew 72""")
df = pd.read_csv(mystr, delim_whitespace=True)
答案 3 :(得分:0)
这是一个解决方案,不使用csv以外的任何其他导入。
我已将您的示例数据用作csv文件。我已阅读内容并创建了(名称,点)元组列表
import csv
list_of_tuples = []
with open('f1.csv', newline='') as csv_file:
dict_of_csv = csv.DictReader(csv_file)
for item in dict_of_csv:
list_of_tuples.append((item['name'], item['points']))
元组列表看起来像这样
[('Andrew', '18'), ('Kate', '10'), ('Jack', '55'), ('Andrew', '31'), ('Andrew', '100'), ('Jack', '58'), ('Andrew', '34'), ('Kate', '22'), ('Jack', '5'), ('Andrew', '72')]
result_dict以{key:(tuple_0,tuple_1),}格式存储数据 像
{ name: (name_count, max_points),
name1: (name_count1, max_points1),
...
}
字典中的值用它们的key
标识,在这种情况下为name
。
像dictionary['key']
一样,这里result_dict[name]
元组中的数据可以作为普通列表访问,例如tuple [0]和tuple [1]
所以这里是result_dict[name][0]
和result_dict[name][1]
result_dict = {}
for dict_item in list_of_tuples:
name = dict_item[0]
points = int(dict_item[1])
if name in result_dict:
name_count = result_dict[name][0]
max_points = result_dict[name][1]
result_dict[name] = (name_count + 1, points if max_points < points else max_points)
else:
# the name isn't in the dictionary, so we add the "name: (name_count, max_points)" to it
result_dict[name] = (1, points)
输出为:
{'Andrew': (5, 100), 'Kate': (2, 22), 'Jack': (3, 58)}