Python - csv writer 按列而不是按行写入

Posted

技术标签:

【中文标题】Python - csv writer 按列而不是按行写入【英文标题】:Python - csv writer write by column, not row 【发布时间】:2015-04-24 20:44:04 【问题描述】:

我正在处理一系列文本文件,我想从中保留一些变量。我试图将这些变量保存在 csv 文件中。每个文本文件将从此 csv 文件中获取 1 行和 N 列。我可以有 1000 个或更多文件,这将导致 csv 文件具有 1000 行和 N 列(N 可以是 10 或更多或更少)。我正在尝试使用以下代码

res=[variable1, variable2, variable3, ..., variableN]
csvfile = "summary.csv"
with open(csvfile, "w") as output:
    writer = csv.writer(output, lineterminator='\n')
    writer.writerows(res)

问题是它在每一行中写入一个值,然后移动到下一个变量的下一行。而我希望每个文本文件的所有变量占据 1 行(和 N 列)。我应该如何更改我的代码才能使其正常工作?

编辑

import re
import collections
from collections import Counter
import csv
import sys


wanted1 = re.findall('\w+', open('words1.csv').read().lower())
wanted2 = re.findall('\w+', open('words2.csv').read().lower())
for f in sys.argv[1:]:
    words = re.findall('\w+', open('f').read().lower())
    cnt = Counter()
    cnt1 = 0
    cnt2 = 0
    cntWords = 0
    for word in words:
        cntWords += 1
            if word in wanted1:
                cnt[word] += 1
                cnt1 += 1
            if word in wanted2:
                cnt[word] += 1
                cnt2 += 1   
print cnt1, cnt2, cntWords
res=[cnt1, cnt2, cntWords]
csvfile = "summary.csv"
with open(csvfile, "w") as output:
    writer = csv.writer(output, lineterminator='\n')
    writer.writerow(res)

在这种情况下,这些变量中的每一个都是一个数字。我还想添加一些包含字符串内容的变量。每个文本文件将占据 1 行。每个变量将占据一个单元格。

例如,cnt1 的值可能为 10000,cnt2 的值可能为 2000,cntWords 的值可能为 30000 等等。

我尝试更改代码以处理文件夹中的所有 .txt 文件,但现在出现错误

  File "countWords.py", line 29
    writer = csv.writer(output, lineterminator='\n')
                                                   ^
IndentationError: unindent does not match any outer indentation level

编辑 2:Output.csv 应该是这样的

       Column 1 Column 2 Column 3
Row 1: Cnt1     Cnt2     CntWords      (all row 1 values should be derived from file1.txt)
Row 2: Cnt1     Cnt2     CntWords      (all row 2 values should be derived from file2.txt)
Row 3: Cnt1     Cnt2     CntWords      (all row 3 values should be derived from file3.txt)
Row 4: Cnt1     Cnt2     CntWords      (all row 4 values should be derived from file4.txt)
Row 5: Cnt1     Cnt2     CntWords      (all row 5 values should be derived from file5.txt)
Row 6: Cnt1     Cnt2     CntWords      (all row 6 values should be derived from file6.txt)

Cnt1 表示 Cnt1 的值,Cnt2 表示 Cnt2 的值,CntWords 表示 CntWords 的值(这些将是数字)

       Column 1 Column 2 Column 3
Row 1: 5000     3000     10000      (all row 1 values should be derived from file1.txt)
Row 2: 510     420     1423      (all row 2 values should be derived from file2.txt)

这意味着输入的是2个文本文件,第一个文本文件有单词表1的5000个单词,单词表2的3000个单词,总共10000个单词,而第二个文本文件有单词表1的510个单词,420词表2的词,共1423个词。

【问题讨论】:

我不清楚variable1 等中包含哪些类型的数据。我的回答在这里解决了两种可能性,但如果您更新您的问题以向我们提供示例输入数据,将会很有帮助和预期的输出,以及你现在得到的错误输出。这不一定是真实数据,只是一个示例,向我们展示正在发生的事情以及您想要什么。 好的,请稍候,我会尽快更新我的答案。 刚刚编辑了我最初的帖子。谢谢 看,你在这里做的是完全不同的事情。您将 Counter 对象写入 CSV 的事实完全改变了您需要做的事情。每个计数器的预期输出是什么? 抱歉没有正确解释。对于文件循环内的每个文本文件,计数器应设置为零。我有两个单词列表,我计算每个文本文件中属于该单词列表的单词数。然后我还计算每个文本文件中的总字数。我想把这些写在一个摘要 csv 文件中(每个文件应该占据一行 N 列,N 是我要保留的变量数) 【参考方案1】:

如果您只想将 3 个计数器写入 CSV 文件,那么只需在循环中写入 CSV 文件。在循环之外创建 CSV 写入器,并在处理文件时向其中写入行:

find_words = re.compile(r'\w+').findall

# create *sets* for faster membership tests
wanted1 = set(find_words(open('words1.csv').read().lower()))
wanted2 = set(find_words(open('words2.csv').read().lower()))

csvfile = "summary.csv"
with open(csvfile, "wb") as output:
    writer = csv.writer(output)

    for f in sys.argv[1:]:
        cnt1 = cnt2 = cntWords = 0

        with open(f) as inputfile:
            for line in inputfile:
                for word in find_words(line.lower()):
                    cntWords += 1
                    if word in wanted1:
                        cnt1 += 1
                    if word in wanted2:
                        cnt2 += 1   

        writer.writerow([cnt1, cnt2, cntWords])

我还将您的 wanted* 列表替换为用于快速成员资格测试的集合(而不是每次在恒定时间内找到单词时扫描整个列表),并改为逐行扫描输入文件以避免破坏记忆。

【讨论】:

这段代码给了我以下错误:文件“countWordsLM.py”,第 26 行 cntWords += 1 ^ IndentationError: expected an indented block 。另外,最后一行是否缺少括号或某事? 看起来不错(并且您正在做的优化速度更快)。问题是它将所有内容放在一列中,550,66,553705,而这些数字应该放在单独的列中..有什么想法可以改变吗? @adrCoder:那些单独的列,用逗号分隔列。如果您需要不同的列分隔符,请告诉csv.writer() 对象。 你不应该把文件的字数降低或……吗?有些数字低于我之前得到的数字,您确定您从列表和文件中正确计算了单词吗? (单词可能很小或带有大写字母或其他任何内容,您是否正在检查这些?也许 open(f) 中的单词也应该归结为 .lower() ? @adrCoder:我错过了str.lower() 电话,是的。【参考方案2】:

第 18 行的缩进错误,应该是这样的

csvfile = "summary.csv"
with open(csvfile, "w") as output:
    writer = csv.writer(output, lineterminator='\n')
    for f in sys.argv[1:]:
        words = re.findall('\w+', open('f').read().lower())
        cnt1, cnt2 = 0, 0
        cntWords = len(words)
        for word in words:
            if word in wanted1:
                cnt1 += 1
            if word in wanted2:
                cnt2 += 1
        print cnt1, cnt2, cntWords
        res = [cnt1, cnt2, cntWords]
        writer.writerow(res)

附:计数器用法见example

【讨论】:

缩进问题不是实际问题 @MartijnPieters 为什么不呢?他想在一个 csv raw 中写入一个文件。 对,这个问题一开始是完全不同的;很可能唯一剩下的就是缩进错误。 我想指出,以这种方式计算单词也会计算单词重复 你好,我认为它需要是 open(f).read().lower()),open('f').read().lower()) 给我一个错误 Traceback (最近一次通话最后一次):文件“countWordsLM.py”,第 14 行,在 words = re.findall('\w+', open('f').read().lower()) IOError: [ Errno 2] 没有这样的文件或目录:'f'。此外,它将所有三个变量都放在一个单元格中,我们如何将 cnt1 放在一列中,cnt2 在另一列中,cntWords 在另一列中等等?至少您的代码为每个文本文件创建了一行,因此确实是一个进步

以上是关于Python - csv writer 按列而不是按行写入的主要内容,如果未能解决你的问题,请参考以下文章

按列而不是轴对Numpy数组进行排序[重复]

使用 CRLF 而不是 LF 的 CSV Writer (Python)

使用writer.writerows(reader)在python3中逐个编写csv行而不是一次写入csv行

如何将多个csv按行合并?(不是首尾相接的按列合并)

python将两个csv文件按列合并为一个csv

Python - 读取 csv 并按列对数据进行分组