簡體   English   中英

將 CSV 值讀入列表字典的最 Pythonic 方式

[英]Most Pythonic way to read CSV values into dict of lists

我有一個 CSV 文件,標題位於數據列的頂部,如下所示:

a,b,c
1,2,3
4,5,6
7,8,9

我需要在列表字典中閱讀它:

desired_result = {'a': [1, 4, 7], 'b': [2, 5, 8], 'c': [3, 6, 9]}

使用DictReader閱讀本文時,我使用嵌套循環將項目附加到列表中:

f = 'path_to_some_csv_file.csv'
dr = csv.DictReader(open(f))
dict_of_lists = dr.next()
for k in dict_of_lists.keys():
    dict_of_lists[k] = [dict_of_lists[k]]
for line in dr:
    for k in dict_of_lists.keys():
        dict_of_lists[k].append(line[k])

第一個循環將 dict 中的所有值設置為空列表。 下一個循環遍歷從 CSV 文件讀入的每一行, DictReader創建一個鍵值字典。 內部循環將值附加到與相應鍵匹配的列表中,所以我最終得到了所需的字典列表。 我最終不得不經常寫這個。

我的問題是,是否有更 Pythonic 的方式使用沒有嵌套循環的內置函數來執行此操作,或者更好的習慣用法,或者存儲此數據結構的替代方法,以便我可以通過使用鍵查詢來返回可索引列表? 如果是這樣,是否還有一種方法可以預先格式化由列攝取的數據?

根據您存儲的數據類型以及是否可以使用 numpy,一個很好的方法是使用numpy.genfromtxt

import numpy as np
data = np.genfromtxt('data.csv', delimiter=',', names=True)

這將創建一個 numpy Structured Array ,它提供了一個很好的界面,用於按標題名稱查詢數據(如果您有標題行,請確保使用names=True )。

示例,給定data.csv包含:

a,b,c
1,2,3
4,5,6
7,8,9

然后,您可以通過以下方式訪問元素:

>>> data['a']        # Column with header 'a'
array([ 1.,  4.,  7.])
>>> data[0]          # First row
(1.0, 2.0, 3.0)
>>> data['c'][2]     # Specific element
9.0
>>> data[['a', 'c']] # Two columns
array([(1.0, 3.0), (4.0, 6.0), (7.0, 9.0)],
      dtype=[('a', '<f8'), ('c', '<f8')])

genfromtext還提供了一種方法,根據您的要求,“ genfromtext格式化由列攝取的數據”。

轉換器變量,可選

將列的數據轉換為值的一組函數。 轉換器還可用於為缺失數據提供默認值: converters = {3: lambda s: float(s or 0)}

如果您願意使用第三方庫,那么來自Toolzmerge_with函數使整個操作成為一個單線

dict_of_lists = merge_with(list, *csv.DictReader(open(f)))

僅使用 stdlib, defaultdict使代碼減少重復:

from collections import defaultdict
import csv

f = 'test.csv'

dict_of_lists = defaultdict(list)
for record in DictReader(open(f)):
    for key, val in record.items():    # or iteritems in Python 2
        dict_of_lists[key].append(val)

如果您需要經常這樣做,請將其分解為一個函數,例如transpose_csv

福特的回答沒有問題,我只是在這里添加我的(它使用了 csv 庫)

with open(f,'r',encoding='latin1') as csvf:
    dialect = csv.Sniffer().sniff(csvf.readline()) # finds the delimiters automatically
    csvf.seek(0)
    # read file with dialect
    rdlistcsv = csv.reader(csvf,dialect)
    # save to list of rows
    rowslist  = [list(filter(None,line)) for line in rdlistcsv]
    header = rowslist[0]
    data = {}
    for i,key in enumerate(header):
        ilist = [row[i] for row in rowslist]
        data.update({key: ilist})

編輯:實際上,如果你不介意使用熊貓,事情會變得更容易:

  1. 進口大熊貓

    import pandas as pd
  2. 導入文件並將其保存為熊貓數據框

    df = pd.read_csv(inputfile)
  3. 將 df 變成字典

    mydict = df.to_ditc(orient='list')

通過這種方式,您可以使用 csv 標題來定義鍵,並且對於每個鍵,您都有一個元素列表(類似於 Excel 列變成了列表)

您可以使用 dict 和 set comprehensions 使您的意圖更加明顯:

dr=csv.DictReader(f)
data={k:[v] for k, v in dr.next().items()}             # create the initial dict of lists
for line_dict in dr:
    {data[k].append(v) for k, v in line_dict.items()}  # append to each

您可以使用Alex Martelli 的方法在 Python 中展平列表列表以展平迭代器的迭代器,這將第一種形式進一步簡化為:

dr=csv.DictReader(f)
data={k:[v] for k, v in dr.next().items()}
{data[k].append(v) for line_dict in dr for k, v in line_dict.items()}

在 Python 2.X 上,如果您的 csv 文件很大,請考慮使用{}.iteritems{}.items()


進一步的例子:

假設這個 csv 文件:

Header 1,Header 2,Header 3
1,2,3
4,5,6
7,8,9

現在假設您想要將每個值的列表的字典轉換為浮點數或整數。 你可以做:

def convert(s, converter):
    try:
        return converter(s)
    except Exception:
        return s    

dr=csv.DictReader(f)
data={k:[convert(v, float)] for k, v in dr.next().items()}
{data[k].append(convert(v, float)) for line_dict in dr for k, v in line_dict.items()}

print data
# {'Header 3': [3.0, 6.0, 9.0], 'Header 2': [2.0, 5.0, 8.0], 'Header 1': [1.0, 4.0, 7.0]}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM