从一个目录中加载所有的csv/txt文件,通过Python合并它们

6

我有一个包含数百个(可能超过1k)时间顺序数据的csv数据文件夹。理想情况下,这些数据应该在一个csv文件中,以便我可以一次性分析全部数据。我想知道的是,是否有一种使用Python将所有文件追加到彼此上的方法。

我的文件存在以下类似位置的文件夹中:

C:\Users\folder\Database Files\1st September
C:\Users\folder\Database Files\1st October
C:\Users\folder\Database Files\1st November
C:\Users\folder\Database Files\1st December
etc

在每个文件夹中都有3个csv文件(我使用csv这个术语是因为这些文件实际上保存为.txt文件,其中包含用“|”分隔的值)

假设这些文件名为:

MonthNamOne.txt
MonthNamTwo.txt
MonthNameOneTwoMurged.txt

我该如何编写代码,或者是否有可能编写代码来遍历这个目录中的所有文件夹,并将所有名为OneTwoMerged.txt的文件合并在一起?


3
从学习如何使用 os.path.walk() 开始。这将为您提供一种查找所有文件的简单方法。在掌握了这个之后,先不要考虑 csv 部分。然后,剩下的将会很容易 :-) 或者可以从更简单的 os.walk() 开始。在一开始会比较少混淆。 - Tim Peters
2
如果您恰好拥有bash msys或cygwin,您可以使用命令cat mydir/**/*OneTwoMurged.txt > my_merged_file.txt将所有文件合并到一个文件中。 - kalhartt
2
@TimPeters 既然 os.path.walk 已被弃用并且在 3.x 中也不再使用,我认为 OP 应该忽略 os.path.walk - Jon Clements
@JonClements,好建议,Jon!我同意。 - Tim Peters
1
os.walk - korylprince
显示剩余3条评论
3个回答

15

对于文件夹中所有后缀为.csv的文件

import glob
import os

filelist = []

os.chdir("folderwithcsvs/")
for counter, files in enumerate(glob.glob("*.csv")):
    filelist.append(files)
    print "do stuff with file:", files, counter

print filelist

for fileitem in filelist:
    print fileitem

很显然,“做事部分”取决于您想对文件执行什么操作,这是获取文件列表的步骤。

如果您想每月对文件执行某些操作,则可以使用datetime并创建可能的月份,同样适用于天或年度数据。

例如,对于名称为Month Year.csv的月度文件,它将查找每个文件。

import subprocess, datetime, os

start_year, start_month = "2001", "January"

current_month = datetime.date.today().replace(day=1)
possible_month = datetime.datetime.strptime('%s %s' % (start_month, start_year), '%B %Y').date()
while possible_month <= current_month:
    csv_filename = possible_month.strftime('%B %Y') + '.csv'
    month = possible_month.strftime('%B %Y').split(" ")[0]
    year = possible_month.strftime('%B %Y').split(" ")[1]
    if os.path.exists("folder/" + csv_filename):
        print csv_filename
    possible_month = (possible_month + datetime.timedelta(days=31)).replace(day=1)

显然,您可以根据自己的感觉进行更改,如果您需要更多信息或者这已经足够了,请告诉我。


能否选择一个“月份年份.csv”文件,如果存在,则执行相关操作? - AEA
@AEA 那就像这样:Novemember 2013.csv - Dennis Sylvian
是的,那正是我所需要的 :) - AEA
完美运行,时间到期后(目前为止19小时),将给您赏金。 - AEA

5

这段代码将递归处理一个目录,并匹配指定文件模式进行处理,最后将处理结果追加。此外,它也会解析csv文件,因此你可以对每行数据进行单独的分析和处理。根据需要进行修改 :)

#!python2
import os
import fnmatch
import csv
from datetime import datetime as dt

# Open result file
with open('output.txt','wb') as fout:
    wout = csv.writer(fout,delimiter='|')

    # Recursively process a directory
    for path,dirs,files in os.walk('files'):

        # Sort directories for processing.
        # In this case, sorting directories named "Month Year" chronologically.
        dirs.sort(key=lambda d: dt.strptime(d,'%B %Y'))
        interesting_files = fnmatch.filter(files,'*.txt')

        # Example for sorting filenames with a custom chronological sort "Month Year.txt"
        for filename in sorted(interesting_files,key=lambda f: dt.strptime(f,'%B %Y.txt')):

            # Generate the full path to the file.
            fullname = os.path.join(path,filename)
            print 'Processing',fullname

            # Open and process file
            with open(fullname,'rb') as fin:
                for line in csv.reader(fin,delimiter='|'):
                    wout.writerow(line)

就像Tom Clements在评论中所说的“os.path.walk”已经被弃用,而且在3.x中也不再存在,我认为OP应该忽略“os.path.walk”。 - Dennis Sylvian
@DennisSylvian,这是 os.walk 而不是 os.path.walk - Mark Tolonen
1
这段代码存在时间顺序问题,会以随机的、依赖于操作系统的顺序访问文件。 - alko
@alko,这取决于文件内容。如果csv行中包含日期信息,则合并到一个文件中无关紧要。如果没有日期信息,则合并可能会存在歧义,但我们没有关于内容的任何信息。 - Mark Tolonen
1
@MarkTolonen:我之所以问OP这个问题,就是为了知道我们是否需要将名称中的信息推入csv中。目前还没有回应。 - DSM
1
已更新一个示例,用于指定处理目录和文件的排序顺序。 - Mark Tolonen

3

读入 pandas 数据帧(轴的选择取决于您的应用程序),我的示例将添加相同长度的列

import glob
import pandas as pd


df=pd.DataFrame()
for files in glob.glob("*.csv"):
    print files 
    df = pd.concat([df,pd.read_csv(files).iloc[:,1:]],axis=1)

axis = 0 表示按行相加


@Mogsdad 如果你的CSV文件行数不同,但列数相同,那该怎么办呢?如果有4个CSV文件(其中3个有2行,1个有3行),并且它们都有两列,你会如何编辑呢? - Archimeow
@JMeo - 你应该将其作为一个新问题发布。 - Mogsdad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接