【问题标题】:Need to do a math operation on every line in several CSV files in Python需要对 Python 中几个 CSV 文件中的每一行进行数学运算
【发布时间】:2011-11-13 03:09:08
【问题描述】:

我有大约 100 个 CSV 文件,我必须每个月处理一次,我正试图解决这个问题,但我碰壁了。我开始了解一些关于 Python 的东西,但是结合一些东西仍然会给我带来问题,所以我无法弄清楚。

这是我的问题:

我有很多 CSV 文件,这是我需要做的:

在每行的前面添加一个“列”(或后面,实际上并不重要,但前面是理想的)。另外,每行有5行(不包括将要添加的文件名),格式如下:

6位身份证号,YYYY-MM-DD(1),YYYY-MM-DD(2),YYYY-MM-DD(3),1-2位号码

对于给定目录中的每个 CSV,对于文件中的每一行(没有标题行),我需要从 YYYY-MM-DD(2) 中减去 YYYY-MM-DD(3)。

我需要行内的文件名,因为我将合并文件(如果包含在脚本中会很棒,但我想我可以弄清楚那部分),我需要知道记录来自哪个文件从。文件名格式始终为 '4-5-digit-number.csv'

我希望这是有道理的,如果没有,请告诉我。我什至不知道从哪里开始,所以我没有任何真正开始为我工作的示例代码。真的很沮丧,所以我很感谢你们提供的任何帮助,这个网站太棒了!

迈兰

【问题讨论】:

  • 我不明白你为什么需要文件本身的文件名。当您打开文件时,您知道它的名称。
  • In addition, each line has 5 rows,你的意思是列吗?
  • 我最终会将所有文件合并为一个,因此我需要知道哪一行来自哪个文件。每个文件基本上都概述了来自特定设施的一些数据,我需要知道是哪个设施,所以这就是我想要每一行中的文件名的原因。我的意思是专栏,对不起。

标签: python csv datestamp


【解决方案1】:

程序的基本大纲是这样的:

  1. 使用 os 模块从感兴趣的目录/目录中获取文件名
  2. 每次读取一个文件
  3. 对于文件中的每一行,将其拆分为带有columns = line.split(",") 的列
  4. 使用 datetime.date 将“2011-05-03”等字符串转换为 datetime.dates。
  5. 从第二个日期中减去第三个日期,得到 datetime.timedelta。
  6. 以您想要的格式输入所有信息(提示:str(foo) 生成 foo 的字符串表示形式,几乎适用于任何类型)并记住它以备后用
  7. 关闭文件,重新打开以进行写入,然后将新内容写入

【讨论】:

  • 我建议将步骤 7 替换为 write your new stuff out to a temporary file。然后8. Rename original file to .bak suffixed name9. Rename temporary file to original filename。从而将丢失数据的风险降到最低。
  • 非常感谢,帮了大忙
【解决方案2】:

标准库中的每个任务都有一个工具:

要遍历目录中的所有 CSV 文件,请使用 glob module

import glob
for csvfilename in glob.glob(r"C:\mydirectory\*.csv"):
    #do_something

要解析 CSV 文件,请使用 csv module:

import csv
with open(csvfilename, "rb") as csvfile:
    reader = csv.reader(csvfile, delimiter=",")
    for row in reader:
        # row is a list of all the entries in the current row

要解析日期并计算差异,请使用datetime module

from datetime import datetime
startdate = datetime.strptime("1999-10-20", "%Y-%m-%d")
enddate = datetime.strptime("2003-02-28", "%Y-%m-%d")
delta = enddate - startdate # difference in days

将值添加到行的开头:

row[0:0] = [str(delta)]

要将文件名附加到行尾:

row.append(csvfilename)

将一行写入新的 CSV 文件:

with open(csvfilename, "wb") as csvfile:
    writer = csv.writer(csvfile, delimiter=",")
    writer.writerow(row)

综合起来,你得到:

import glob
import csv
from datetime import datetime

with open("combined_files_csv", "wb") as outfile:
    writer = csv.writer(outfile, delimiter=",")
    for csvfilename in glob.glob(r"C:\mydirectory\*.csv"):
        with open(csvfilename, "rb") as infile:
            reader = csv.reader(infile, delimiter=",")
            for row in reader:
                startdate = datetime.strptime(row[3], "%Y-%m-%d")
                enddate = datetime.strptime(row[2], "%Y-%m-%d")
                delta = enddate - startdate # difference in days
                row[0:0] = [str(delta)]
                row.append(csvfilename)
                writer.writerow(row)

【讨论】:

  • 太棒了,感谢您提供这些提示,非常感谢您的指导
  • 我试用了你的脚本,它似乎完全符合我的需要,但是当它到达第 37 行(“for row in reader:”)时,它会抛出错误“_csv.Error : 迭代器应该返回字符串,而不是字节(你是否以文本模式打开文件?)”。如果有区别,我正在使用 Mac OS 10.6 和 Python 3.2.1。谢谢
  • 其实我现在就搞定了。我忽略了将“combined_files_csv”从字符串更改为实际文件。现在像魅力一样工作,非常感谢!这也让我深入了解如何定期在 CSV 上执行其他任务。
  • 啊,是的;在 Python 3 中, csv 模块的工作方式略有不同;你不用二进制模式打开文件,还有一个附加参数newline;见the docs。所以你会做open("file.csv", "w", newline = "")writer = csv.writer(outfile, delimiter = "")。除了python 标记之外,最好使用python-3.x 标记,因为没有它,大多数人会认为您在谈论Python 2。
  • 再次感谢,我仍在努力适应两者的差异。我认为最好让自己在 Python3 中工作以应对未来的挑战,但有时这有点棘手,因为我发现我参考的大多数信息都是为​​ 2.x 编写的,我必须将其更改为与 3 一起使用。 X。感谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多