【问题标题】:Read a CSV file and create a dictionary?读取 CSV 文件并创建字典?
【发布时间】:2015-10-01 01:58:03
【问题描述】:

假设我在下面有一个“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' 必须是整数。起草的“年份”和“职位”必须忽略。

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:]

【问题讨论】:

  • 查看文档中的 csv.reader,它使这变得非常简单。

标签: python list csv dictionary tuples


【解决方案1】:

使用csv moduledefaultdict 来处理重复键:

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 和集合等内置库:

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)]})

使用普通 dict 进行相同的更改以获得相同的输出。

【讨论】:

  • 有没有办法解决“导入 csv”?我正在寻找最简单的解决方案,无需导入任何内容。
  • @VincentLuc,你为什么不导入,可以通过拆分和使用 dict.setdefault 来完成,只是效率会降低
【解决方案2】:

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.

有关熊猫的更多信息,请参阅this link

希望这会有所帮助。

【讨论】:

    【解决方案3】:

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

    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]))
    

    它也可以工作:)

    问候, 戈洛比奇

    【讨论】:

      猜你喜欢
      • 2013-03-02
      • 2017-03-06
      • 1970-01-01
      • 2016-09-03
      • 2017-04-13
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多