在Python

时间:2015-04-30 15:25:35

标签: python csv

我的场景:我正在阅读一个csv文件。我希望能够访问每行生成的字段的字典,以及未解析的原始行。

目标是最终对字段进行一些处理,使用结果来决定我感兴趣的行,并将这些行只写入输出文件。

一个简单的解决方案,包括两次读取文件,如下所示:

def dict_and_row(filename):
    with open(filename) as f:
        tmp = [row for row in DictReader(f)]

    with open(filename) as f:
        next(f)    # skip header
        for i, line in enumerate(f):
            if len(line.strip()) > 0:
                yield line.strip(), tmp[i]

有什么更好的建议吗?

修改:更具体地说明使用方案。我打算通过dict中的一些数据对行进行索引,然后使用这个索引来查找我感兴趣的行。例如:

d = {}
for raw, parsed in dict_and_row(somefile):
      d[(parsed["SOMEFIELD"], parsed ["ANOTHERFIELD"])] = raw

然后在

for pair in some_other_source_of_pairs:
      if pair in d:
            output.write(d[pair])

3 个答案:

答案 0 :(得分:5)

我最终用一个保存最后一行读取的对象包装文件,并将此对象传递给DictReader。

class FileWrapper:
  def __init__(self, f):
    self.f = f
    self.last_line = None

  def __iter__(self):
    return self

  def __next__(self):
    self.last_line = next(self.f)
    return self.last_line

然后可以这样使用:

  f = FileWrapper(file_object)
  for row in csv.DictReader(f):
      print(row)   # that's the dict
      print(f.last_line)   # that's the line

或者我可以实施dict_and_row

 def dict_and_row(filename):
    with open(filename) as f:
         wrapper = FileWrapper(f)
         reader = DictReader(wrapper)
         for row in reader:
              yield row, wrapper.last_line 

这也允许访问其他属性,例如读取的字符数。

不确定这是否是最佳解决方案,但它确实具有保留对字符串的访问权限的优势,因为它们最初是从文件中读取的。

答案 1 :(得分:4)

你可以使用Pandas这是一个很好的库来进行这种处理......

import pandas as pd

# read the csv file
data = pd.read_csv('data.csv')

# do some calculation on a column and store it in another column
data['column2'] = data['column1'] * 2

# If you decide that you need only a particular set of rows
# that match some condition of yours
data = data[data['column2'] > 100]

# store only particular columns back    
cols = ['column1', 'column2', 'column3']
data[cols].to_csv('data_edited.csv')

答案 2 :(得分:1)

这类似于我不得不做的事情。我需要将正确格式化的CSV数据行放入列表中,对其进行操作,然后保存。我使用io.StringIO()来获取CSV以写入列表,然后将其传回。没有您的数据,我无法100%确定,但这应该有效。请注意,我不是一次读取文件,而是将其读取一次,然后将相关的行重新写回CSV格式。

import csv
from io import StringIO

def dict_and_row(filename):
    field_names = ['a', 'b']  # Your field names here.
    output = StringIO(newline='\n')
    with open(filename, 'r', newline='\n') as f:
        writer = csv.DictWriter(output, fieldnames=field_names)
        reader = csv.DictReader(f)

        writer.writeheader()  # If you want to return the header.
        for line in reader:
            if True:  # Do your processing here...
                writer.writerow(line)

    data = [line.strip() for line in output.getvalue().splitlines()]

    for line in data:
        yield line