【问题标题】:Python: Read from and write to a CSV file [duplicate]Python:读取和写入 CSV 文件 [重复]
【发布时间】:2012-07-25 22:28:41
【问题描述】:

我正在尝试从 CSV 文件 (A) 读取数据,提取数据,然后将其写入另一个 CSV 文件 (B)。在新文件 B 中,我想要两列。第 1 列列出文件 A 中第 1 列的名称,第 2 列列出文件 A 中第 1 列的计数。例如,如果文件 A 看起来像这样,没有“:”(它们排成两列):

Animal: Gender
Rabbit: Male
Dog: Male
Rabbit: Female
Cat: Male
Cat: Male
Dog: Female
Dog: Male
Turtle: Male

我希望文件 B 中的输出看起来像这样(实际上在不同的列中再次没有 ':'):

Animal: Count
Cat: 2
Dog: 3
Rabbit: 2
Turtle: 1

这是我第一次做这样的事情,这就是我到目前为止所做的事情,但是我未能将数据打印到文件 B 中并正确完成“计数”。有人可以帮我解决这个问题吗?

import csv
ReadData=csv.reader(open('C:\Users\..\FileA.csv','rb'), delimiter=',')

def column(ReadData, i):
    return [row[i] for row in ReadData]

for line in ReadData:
   WriteData=csv.writer(open('C:\Users\..\FileB.csv','wb'),
                        delimiter=' ', quotechar=':', quoting=csv.QUOTE_ALL)
   print column(ReadData,1)

提前感谢您的帮助!

【问题讨论】:

  • link 向您展示如何使用标记进行编辑/发布
  • 感谢您的快速回复!我一直在检查此链接,但在放置空格时遇到问题...我可能遗漏了一些东西...
  • 对于代码,只需 (1) 将其粘贴,(2) 突出显示/选择代码块,然后点击 (3) Control-K .. 它将向右移动(我认为 4列)并使其正确显示为代码。
  • 谢谢大家。我想有人在我尝试修复它时编辑了格式。不,这不是家庭作业。我正在从头开始学习 Python 以进行研究。
  • 如果我试图解决这个问题,我会先阅读所有内容,可能会使用字典来保持运行总数,然后在阅读整个输入后,写出我的字典。 . .

标签: python csv


【解决方案1】:

要在 Python >=2.7 中进行计数,请参阅 this example for collections.Counter。使用collections.defaultdict,请参阅here

在您对csv.writer 的调用中,quotechar=':' 可能是一个错误(这会使WriteData.writerow(['Hello World', 12345])发出“:Hello World: 12345”,就好像冒号是引号一样。

还要注意你的函数column(ReadData, i) 消耗ReadData;随后对 ReadData 的调用可能会返回一个空列表(未经测试)。这对您的代码来说不是问题(至少现在不是)。

这是一个没有 CSV 模块的解决方案(毕竟这些文件看起来不太像 CSV):

import collections

inputfile = file("A")

counts = collections.Counter()

for line in inputfile:
    animal = line.split(':')[0]
    counts[animal] += 1

for animal, count in counts.iteritems():
    print '%s: %s' % (animal, count)

【讨论】:

  • 最好写成animals = (line.split(':')[0] for line in inputfile); counts = collections.Counter(animals)
  • 非常感谢您提供所有资源!我会试试看!
  • 为了清楚起见,我想在上面使用 ':' 放置数据示例(尽管它在真实数据中不存在),因为我无法将文本与空格或制表符对齐。 . 对此我很抱歉。
  • @owl,然后line.split() 将在任何空白字符处拆分。
  • 谢谢!在实际数据中,我有多个列。有没有办法指定我要查看哪一列?
【解决方案2】:

我会回答你问题的计数部分,也许你可以将它与你问题的 csv 部分结合起来。

l = [
    ('Animal','Gender'),
    ('Rabbit','Male'),
    ('Dog','Male'),
    ('Rabbit','Female'),
    ('Cat','Male'),
    ('Cat','Male'),
    ('Dog','Female'),
    ('Dog','Male'),
    ('Turtle','Male')
    ]

d = {}
for k,v in l:
    if not k in d:
        d[k] = 1
    else:
        d[k] += 1

for k in d:
    print "%s: %d" % (k,d[k])

我没有过滤你的标题行,这段代码的输出是:

Turtle: 1
Cat: 2
Rabbit: 2
Animal: 1
Dog: 3

编辑

你可以替换这个:

if not k in d:
    d[k] = 1
else:
    d[k] += 1

有了这个:

d[k] = d.setdefault(k,0) + 1

【讨论】:

  • 你应该使用defaultdict
  • 我建议使用collections.defaultdict(int) - 如果做不到这一点,至少使用dict.setdefault...
  • @Jon,是的,我更新了帖子以显示 setdefault 的使用。
  • 感谢大家的帮助。我会试试的!
【解决方案3】:

看看itertools 模块和groupby 函数。例如:

from itertools import groupby

animals = [
    ('Rabbit', 'Male'),
    ('Dog', 'Male'),
    ('Rabbit', 'Female'),
    ('Cat', 'Male'),
    ('Cat', 'Male'),
    ('Dog', 'Female'),
    ('Dog', 'Male'),
    ('Turtle', 'Male')
    ]

def get_group_key(animal_data):
    return animal_data[0]

animals = sorted(animals, key=get_group_key)
animal_groups = groupby(animals, get_group_key)

grouped_animals = []
for animal_type in animal_groups:
    grouped_animals.append((animal_type[0], len(list(animal_type[1]))))

print grouped_animals

>>> [('Cat', 2), ('Dog', 3), ('Rabbit', 2), ('Turtle', 1)]

【讨论】:

  • 如果一组动物不完全连续 - 这将产生不正确的结果(请参阅上面结果中的“兔子”)。请注意,sum(1 for _ in iterable) 是一种无需具体化列表或其他序列即可获取迭代器长度的方法
  • 感谢您的帮助!我会一一尝试您的所有建议。
  • @Jon 是的,错过了数据上的sort。关于不实现列表的好点。
【解决方案4】:

根据数据的大小和复杂性...您可能需要考虑使用 pandas - http://pandas.pydata.org/ 上的信息并在 PyPi 上可用。

但是请注意,这可能是过度杀戮,但我想我会把它加入其中。

from pandas import DataFrame

# rows is processed from string in the OP
rows = [['Rabbit', ' Male'], ['Dog', ' Male'], ['Rabbit', ' Female'], ['Cat', ' Male'], ['Cat', ' Male'], ['Dog', ' Female'], ['Dog', ' Male'], ['Turtle', ' Male']]

df = pandas.DataFrame(rows, columns=['animal', 'gender'])

>>> df.groupby('animal').agg(len)
        gender
animal        
Cat          2
Dog          3
Rabbit       2
Turtle       1

>>> df.groupby(['animal', 'gender']).agg(len)
animal  gender 
Cat      Male      2
Dog      Female    1
         Male      2
Rabbit   Female    1
         Male      1
Turtle   Male      1

【讨论】:

  • 感谢分享!您是否知道是否有办法克服在代码中实际打印出“行”中的组合?我拥有的实际数据有数百个“动物”,共有 16 列...
  • @owl 只需将结果分配给一个变量...pandas 是基于numpy 数组,所以如果你熟悉它,你就有能力进行数值计算高效...有点学习曲线,但值得...
  • 感谢您的介绍!我正在尝试我得到的所有答案,但还没有达到你的答案,但我会尝试!