【问题标题】:Create dictionary from CSV where column names are keys从 CSV 创建字典,其中列名是键
【发布时间】:2021-01-28 07:25:00
【问题描述】:

我正在尝试读取 csv 文件(实际上是 tsv,但 nvm)并将其设置为字典,其中其键是所述 csv 的列名,其余行是这些键的值。 我还有一些用“#”字符标记的 cmets,我打算忽略它们:

csv_in.csv

##Some comments
##Can ignore these lines
Location   Form                  Range         <-- This would be the header
North      Dodecahedron          Limited       <---|
East       Toroidal polyhedron   Flexible      <------ These lines would be lists
South      Icosidodecahedron     Limited       <---| 

主要思想是像这样存储它们:

final_dict = {'Location': ['North','East','South'], 
'Form': ['Dodecahedron','Toroidal polyhedron','Icosidodecahedron'],
'Range': ['Limited','Flexible','Limited']}

到目前为止,我可以像这样接近:

tryercode.py

import csv
dct = {}

# Open csv file
with open(tsvfile) as file_in:
# Open reader instance with tab delimeter
reader = csv.reader(file_in, delimiter='\t')
# Iterate through rows 
for row in reader:
    # First I skip those rows that start with '#'
    if row[0].startswith('#'):
        pass
    elif row[0].startswith('L'):
        # Here I try to keep the first row that starts with the letter 'L' in a separate list
        # and insert this first row values as keys with empty lists inside
        dictkeys_list = []
        for i in range(len(row)):
            dictkeys_list.append(row[i])
            dct[row[i]] = []
    else:
        # Insert each row indexes as values by the quantity of rows
        print('¿?')

到目前为止,字典的骨架看起来还不错:

print(dct)
{'Location': [], 'Form': [], 'Range': []}

但到目前为止,我尝试的所有操作都未能按照预期的方式将值附加到键的空列表中。只能对第一行这样做。

        (...)
    else:
        # Insert each row indexes as values by the quantity of rows
        print('¿?')
        for j in range(len(row)):
            dct[dictkeys_list[j]] = row[j]   # Here I indicate the intented key of the dict through the preoviously list of key names

我在stackoverflow上进行了广泛搜索,但找不到这种方式(代码模板的灵感来自this post的答案,但字典的结构不同。

【问题讨论】:

  • 最后一行使用dct[dictkeys_list[j]].append(row[j])

标签: python csv dictionary


【解决方案1】:

使用collections.defaultdict,我们可以创建一个自动将其值初始化为列表的字典。然后我们可以遍历csv.DictReader 来填充defaultdict

鉴于此数据:

A,B,C
a,b,c
aa,bb,cc
aaa,bbb,ccc

这段代码

import collections
import csv

d = collections.defaultdict(list)

with open('myfile.csv', 'r', newline='') as f:
    reader = csv.DictReader(f)
    for row in reader:
        for k, v in row.items():
            d[k].append(v)
print(d)

产生这个结果:

defaultdict(<class 'list'>, {'A': ['a', 'aa', 'aaa'],
                             'B': ['b', 'bb', 'bbb'], 
                             'C': ['c', 'cc', 'ccc']})

【讨论】:

  • 非常感谢。为什么我总是出错?我收到了这个错误NameError: name 'buf' is not defined
  • @YasserKhalil buf 是一个错字 - 应该是 f。我已经更正了示例 - 感谢您发现它。
  • 非常感谢您对我的琐碎问题感到抱歉。
【解决方案2】:

我修改了你的代码并运行它。您的代码可以使用正确的结果。
代码如下

import csv
dct = {}

# Open csv file
tsvfile="./tsv.csv"  # This is the tsv file path
with open(tsvfile) as file_in:
# Open reader instance with tab delimeter
    reader = csv.reader(file_in, delimiter='\t')
    for row in reader:
    # First I skip those rows that start with '#'
        if row[0].startswith('#'):
            pass
        elif row[0].startswith('L'):
        # Here I try to keep the first row that starts with the letter 'L' in a separate list
        # and insert this first row values as keys with empty lists inside
            dictkeys_list = []
            for i in range(len(row)):
                dictkeys_list.append(row[i])
                dct[row[i]] = []
        else:
        # Insert each row indexes as values by the quantity of rows
            for i in range(len(row)):
                dct[dictkeys_list[i]].append(row[i])
print(dct)
# Iterate through rows

这样的运行结果 此外,我将您的进一步修改如下,我认为代码可以处理更复杂的情况

import csv
dct = {}

# Open csv file
tsvfile="./tsv.csv"  # This is the tsv file path
is_head=True    # judge if the first line
with open(tsvfile) as file_in:
# Open reader instance with tab delimeter
    reader = csv.reader(file_in, delimiter='\t')
    for row in reader:
        # First I skip those rows that start with '#'
        # Use strip() to remove the space char of each item
        if row.__len__()==0 or row[0].strip().startswith('#'):
            pass
        elif is_head:
        # Here I try to keep the first row that starts with the letter 'L' in a separate list
        # and insert this first row values as keys with empty lists inside
            is_head=False
            dictkeys_list = []
            for i in range(len(row)):
                item=row[i].strip()
                dictkeys_list.append(item)
                dct[item] = []
        else:
        # Insert each row indexes as values by the quantity of rows
            for i in range(len(row)):
                dct[dictkeys_list[i]].append(row[i].strip())
print(dct)
# Iterate through rows

【讨论】:

    【解决方案3】:

    您好,您可以试试 pandas 库。

    import pandas as pd
    df = pd.read_csv("csv_in.csv")
    df.to_dict(orient="list")
    

    【讨论】:

      【解决方案4】:

      为了重现这一点,我创建了一个包含以下内容的 csv 文件并保存为“csvfile.csv”。

      Location,Form,Range
      North,Dodecahedron,Limited
      East,Toroidal polyhedron,Flexible
      South,Icosidodecahedron,Limited
      

      现在为了实现你的目标,我使用了如下熊猫库:

      import pandas as pd
      df_csv = pd.read_csv('csvfile.csv')
      dict_csv = df_csv.to_dict(orient='list')
      print(dict_csv)
      

      这是您需要的输出:

      {'Location': ['North', 'East', 'South'],
       'Form': ['Dodecahedron', 'Toroidal polyhedron', 'Icosidodecahedron'],
       'Range': ['Limited', 'Flexible', 'Limited']}
      

      希望,这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2014-10-08
        • 1970-01-01
        • 2019-09-25
        • 1970-01-01
        • 2021-05-14
        • 2018-09-16
        • 1970-01-01
        • 2016-02-28
        • 2021-12-29
        相关资源
        最近更新 更多