读取CSV文件并创建字典?

3
假设我有一个名为'players.csv'的文件,其中包含一些NFL球员的数据。 我的目标是读取该文件,并创建一个字典,以球员身高作为键,以包含球员简介元组列表的值。
HEIGHT,NAME,DRAFTED,AGE,POSITION,WEIGHT

6,Aaron,2005,31,QB,225

5,Jordy,2008,30,WR,217

5,Randall,2011,24,WR,192

球员概况元组示例,'name' 必须是一个字符串, 'age' 和 'position' 必须是整数。 'year' 排名和 'position' 必须被忽略。

player_profile = (name, age, position)

预期字典:

# players height are keys, player profiles are values.
dict = {
    6: [('Aaron', 31, 225)]
    5: [('Jordy', 30, 217), ('Randall', 24, 192)]
   }

以下是我目前的进展,但我卡住了。
final_dict = {}

#open csv file
with open(filename) as f:
    info = f.read()

#split the newline characters
info2 = info.split()

#exclude the header
info3 = info2[1:]

1
请参考文档中的csv.reader,它可以使这个过程变得简单许多。 - pvg
3个回答

2

使用csv模块defaultdict处理重复的键:

import csv
from collections import defaultdict

d = defaultdict(list)

with open("in.csv") as f:
    next(f) # skip header
    r = csv.reader(f)
    # unpack use height as key and  append name age and position
    for h, nm, _, a, p ,_ in r:
        d[int(h)].append((nm, int(a), p))

print(d)

输出:

defaultdict(<type 'list'>, {5: [('Jordy', 30, 'WR'), ('Randall', 24, 'WR')], 6: [('Aaron', 31, 'QB')]})

如果你真的想避免导入,可以使用str.split并使用dict.setdefault,但我认为没有理由不使用内置库,如csv和collections:

d = {}

with open("in.csv") as f:
    next(f)  
    for line in f:
        h, nm, _, a, p ,_  = line.split(",")
        d.setdefault(int(h),[]).append((nm, int(a), p))

print(d)

输出:

{5: [('Jordy', 30, 'WR'), ('Randall', 24, 'WR')], 6: [('Aaron', 31, 'QB')]}

您的输入示例不正确,因为POSITION是一个字符串,您应该使用WEIGHT来匹配您期望的输出:

with open("in.csv") as f:
    next(f) # skip header
    r = csv.reader(f)
    # unpack use height as key and  append name age and weight
    for h, nm, _, a, _ ,w in r:
        d[int(h)].append((nm, int(a), int(w)))

输出:

defaultdict(<type 'list'>, {5: [('Jordy', 30, 217), ('Randall', 24, 192)], 6: [('Aaron', 31, 225)]})

使用普通的字典进行相同的更改,以获得相同的输出结果。

有没有绕过“import csv”的方法?我正在寻找最简单的解决方案,而不需要导入任何内容。 - Vincent Luc
1
@VincentLuc,为什么你不导入,可以通过拆分和使用dict.setdefault来实现,这样效率更低。 - Padraic Cunningham

0

csv 模块的问题在于它不会自动处理数据类型转换,正如你可能已经从 Padraic 的回答中注意到的那样,键和年龄都是字符串。这意味着您需要进行额外的传递,可能使用 map,在其中将字符串转换为其正确的类型。此外,一旦读取文件,您很可能希望对其内容执行某种分析或其他处理。

因此,我建议使用 pandas.DataFrame 进行工作,它提供了类似字典的行为,如下所示:

import pandas
Q = pandas.read_csv("myfile.csv", index_col = "HEIGHT")

Q现在是一个DataFrame。要检索所有身高为5英尺的球员:

Q.ix[5] #Returns two rows according to the data posted in the question.

获取身高为5的玩家的年龄中位数:

Q.ix[5]["AGE"].median() #27.0 according to the data posted in the question.

如需更多关于pandas的信息,请参见此链接

希望这可以帮到您。


0

我认为这是这个问题最基本的解决方案。

from collections import defaultdict

players = defaultdict(list)
for line in open("players.csv"):
    line = line.strip()
    tokens = line.split(",")
    xs = [tokens[1], tokens[3], tokens[5]]
    players[tokens[0]].append(tuple(xs))

首先,您正在定义默认字典,并将列表作为值。然后,您需要浏览文件并删除一些特殊字符,例如“\n”等。然后,我们通过“,”拆分整个行。然后,我们知道每个位置的内容。我们知道数字在零位置,因此这是我们的键。其他属性位于第1、3和5个位置,因此我们还将这些标记包含在我们的列表中。我们将这些标记包含在列表中只是为了将此列表转换为元组。这是最简单的解决方案。我们也可以这样说。
players[tokens[0]].append((tokens[1], tokens[3], tokens[5]))

这也可以工作 :)

祝好, golobich


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接