【问题标题】:extract rows and filenames from multiple csv files从多个 csv 文件中提取行和文件名
【发布时间】:2011-11-04 23:41:37
【问题描述】:

我在一个文件夹中有多个日期为文件名的 csv 文件(20080101.csv 到 20111031.csv)。 csv 文件有共同的标题。 csv 文件如下所示:

20080101.csv  
X ;Y; Z  
1 ; 1 ; 3  
1 ; 2 ; 6  
1 ; 3 ; 24  
2 ; 1 ; 24  
2 ; 2 ; 24  

20080102.csv   
X ;Y; Z  
1 ; 1 ; 0.1  
1 ; 2 ; 2  
1 ; 3 ; 67  
2 ; 1 ; 24  
2 ; 2 ; 24  

20080103.csv  
X ;Y; Z  
1 ; 1 ; 3  
1 ; 3 ; 24  
2 ; 1 ; 24  
2 ; 2 ; 24  

20080104.csv   
X ;Y; Z  
1 ; 1 ; 34  
1 ; 2 ; 23  
1 ; 3 ; 67  
2 ; 1 ; 24  
2 ; 2 ; 24  

……等等。我想编写一个脚本来读取行,如果在给定的行中我们有 X=1 和 Y=2,则将整行复制到一个新的 csv 文件以及提供以下输出的文件名:

X ;Y ; Z ; filename  
1  ; 2 ; 6 ; 20080101  
1  ; 2 ; 2 ; 20080102  
1  ; 2 ; NA; 20080103  
1  ; 2 ; 23; 20080104 

任何想法如何做到这一点以及关于我应该研究的模块或任何示例的任何建议。 感谢您的时间和帮助。

干杯, 纳文

【问题讨论】:

  • 您对 (x,y) 不是 (1,2) 的记录不感兴趣?把它们扔掉?
  • 你真的可以将分号分隔的文件称为 csv 吗?
  • @Danny 字符分隔值?我正在抓住稻草:)
  • 我看到一个除以条,为什么不是分号。有人想为任何目的重新使用逗号
  • hmmm...奇怪的作业...我可以从这个练习中学到什么?

标签: python


【解决方案1】:

这是一个结构良好的问题,逻辑应该是显而易见的。有人提供完成的代码会破坏分配的目的。首先,在问题中添加“作业”标签,然后考虑您要做什么: 1)循环文件(跟踪每个文件名,因为它打开) 2) 从当前文件中读取行 3) 如果满足选择条件(x==1 和 y==2),则写入该行。

要开始,请尝试:

import csv, os

for fn in os.listdir():
    if ".csv" in fn:
        with open(fn, 'r', newline='') as f:
            reader = csv.reader(f, delimiter=";")
            for row in reader:
                ...

然后扩展解决方案以打开输出文件并使用 csv.writer 写入选定的行。

【讨论】:

    【解决方案2】:

    这应该可以完成工作:

    import glob
    import os
    
    outfile = open('output.csv', 'w')
    outfile.write('X ; Y ; Z ; filename\n')
    for filename in glob.glob('*.csv'):
      if filename == 'output.csv': # Skip the file we're writing.
        continue
      with open(filename, 'r') as infile:
        count = 0 
        lineno = 0 
        for line in infile:
          lineno += 1
          if lineno == 1: # Skip the header line.
            continue
          fields = line.split(';')
          x = int(fields[0])
          y = int(fields[1])
          z = float(fields[2])
          if x == 1 and y == 2:
            outfile.write('%d ; %d ; %g ; %s\n' % (x, y, z, filename))
            count += 1
        if count == 0: # Handle the case when no lines were found.
          outfile.write('1 ; 2 ; NA ; %s\n' % filename)
    outfile.close()
    

    请注意,如果您无法控制或信任文件格式,您可能需要处理转换为 int/float 时引发的异常。

    【讨论】:

    • 非常感谢...抱歉回复晚了..作为初学者我花了一些时间来理解每一个有价值的回复。学python确实很有趣!!
    【解决方案3】:

    您可以一次读取每个文件。逐行阅读

    files = ['20080101.csv', '20080102.csv', '20080103.csv'] #...etc
    for f in files:
        file = open(f, 'r')
        for line in file:
            ray = line.split(';')
            if (ray[0].strip() == '1' and ray[1].strip() == '2'):
                fout = open('output.csv', 'a')
                fout.write(ray[0].strip() + ' ; ' + ray[1].strip() + ' ; ' + ray[2].strip() + ' ; ' + f + '\n')
                fout.close()
        file.close()
    

    经过测试并且有效。可能需要稍作修改。

    【讨论】:

    • if 总是会失败,因为 ray 是一个字符串列表。
    • @AdamZalcman:我检查了这段代码,它可以工作。 ray 是一个字符串列表。我将每个字符串剥离为数字,然后将其与“1”和“2”进行比较。请对此进行测试,并在告诉我错误之前告诉我您遇到了错误。
    • 当我写评论时,您正在与裸整数 1 和 2 进行比较。
    • @AdamZalcman 您的评论是在我上次编辑后 2 分钟写的。但我不会和你分道扬镳。上面的代码现在可以正常工作了。
    • 你是对的,你的编辑在我的评论之前。我没有重新加载页面。此外,代码确实有效。
    【解决方案4】:

    如果你知道你每天都有一个文件,没有丢失的一天,那么我会使用 glob('*.csv') 来获取文件名列表,一一打开,然后像 Tyler 一样阅读

    如果您知道有些日子文件丢失,我会使用 datetime 来加上 datetime.date(2008,1,1) 并循环递增一天。然后每天我使用 .strftime() + '.csv' 编写文件名,并尝试处理文件(如果没有文件,只需使用 NA 编写重新编码)

    【讨论】:

      【解决方案5】:

      以下应该有效:

      import csv
      with open('output.csv', 'w') as outfile:
          outfile.write('X ; Y ; Z ; filename\n')
          fmt = '1 ; 2 ; %s ; %s\n'
          files = ['20080101.csv', '20080102.csv', '20080103.csv', '20080104.csv']
          for file in files:
              with open(file) as f:
                  reader = csv.reader(f, delimiter=';')
                  for row in reader:
                      if len(row) > 2 and row[0].strip() == '1' and row[1].strip() == '2':
                          outfile.write(fmt % (row[2].strip(), file[:-4]))
                          break
                  else:
                      outfile.write(fmt % ('NA', file[:-4]))
      

      【讨论】:

        猜你喜欢
        • 2016-01-08
        • 2020-11-30
        • 1970-01-01
        • 2017-01-12
        • 2016-06-14
        • 1970-01-01
        • 2013-08-07
        • 1970-01-01
        • 2014-12-10
        相关资源
        最近更新 更多