使用Python从多个文本文件中提取列

4
我是一个有用的助手,可以为您翻译文本。
我有一个文件夹,里面包含5个文本文件,与各种站点相关--标题以这种方式格式化:
Rockspring_18_SW.417712.WRFc36.ET.2000-2050.txt

Rockspring_18_SW.417712.WRFc36.RAIN.2000-2050.txt

WICA.399347.WRFc36.ET.2000-2050.txt

WICA.399347.WRFc36.RAIN.2000-2050.txt

因此,文件名基本上遵循以下格式 - (网站名称)。 (网站编号)。 (WRFc36)。 (某些变量)。 (2000-2050.txt

每个文本文件都具有相似的格式,没有标题行:年 月 日 值(每个文本文件中包含约18500行)

我希望Python搜索类似的文件名(其中网站名称和网站编号匹配),并从其中一个文件中选择第一到第三列数据,并将其粘贴到新的txt文件中。 我还想复制并粘贴每个变量的第4列数据(雨,et等)并按特定顺序将它们粘贴到新文件中。

我知道如何使用csv模块(并定义用于空格分隔符的新方言)从所有文件中抓取数据并打印到新文本文件中,但我不确定如何自动创建每个网站名称/编号的新文件,并确保我的变量按正确顺序绘制出来-

我想要使用以下格式的一个文本文件(而不是5个),用于每个站点的输出,格式为(年,月,日,变量1,变量2,变量3,变量4,变量5),包含约18500行...

我相信我在这里忽略了一些非常简单的东西...... 这似乎是相当基础的...... 但是,任何帮助都将不胜感激!

更新

========

我已经更新了代码以反映下面的评论。
http://codepad.org/3mQEM75e

从collections导入defaultdict import glob import csv
#Create dictionary of lists--   [A] = [Afilename1, Afilename2, Afilename3...]
#                               [B] = [Bfilename1, Bfilename2, Bfilename3...] 
def get_site_files():
    sites = defaultdict(list)
    #to start, I have a bunch of files in this format ---
    #"site name(unique)"."site num(unique)"."WRFc36"."Variable(5 for each site name)"."2000-2050"
    for fname in glob.glob("*.txt"):
        #split name at every instance of "."
        parts = fname.split(".")
        #check to make sure i only use the proper files-- having 6 parts to name and having WRFc36 as 3rd part
        if len(parts)==6 and parts[2]=='WRFc36':
            #Make sure site name is the full unique identifier, the first and second "parts"
            sites[parts[0]+"."+parts[1]].append(fname)
    return sites

#hardcode the variables for method 2, below
Var=["TAVE","RAIN","SMOIS_INST","ET","SFROFF"]

def main():
    for site_name, files in get_site_files().iteritems():
        print "Working on *****"+site_name+"*****"
####Method 1- I'd like to not hardcode in my variables (as in method 2), so I can use this script in other applications.
        for filename in files:
            reader = csv.reader(open(filename, "rb"))
            WriteFile = csv.writer(open("XX_"+site_name+"_combined.txt","wb"))
            for row in reader:
                row = reader.next()
####Method 2 works (mostly), but skips a LOT of random lines of first file, and doesn't utilize the functionality built into my dictionary of lists...            
##        reader0 = csv.reader(open(site_name+".WRFc36."+Var[0]+".2000-2050.txt", "rb"))    #I'd like to copy ALL columns from the first file
##        reader1 = csv.reader(open(site_name+".WRFc36."+Var[1]+".2000-2050.txt", "rb"))    #    and just the fourth column from all the rest of the files
##        reader2 = csv.reader(open(site_name+".WRFc36."+Var[2]+".2000-2050.txt", "rb"))    #    (the columns 1-3 are the same for all files)
##        reader3 = csv.reader(open(site_name+".WRFc36."+Var[3]+".2000-2050.txt", "rb"))
##        reader4 = csv.reader(open(site_name+".WRFc36."+Var[4]+".2000-2050.txt", "rb"))
##        WriteFile = csv.writer(open("XX_"+site_name+"_COMBINED.txt", "wb"))               #creates new command to write a text file
##
##        for row in reader0:
##            row  = reader0.next()
##            row1 = reader1.next()
##            row2 = reader2.next()
##            row3 = reader3.next()
##            row4 = reader4.next()
##            WriteFile.writerow(row + row1 + row2 + row3 + row4)
##        print "***finished with site***"

if __name__=="__main__":
    main()
2个回答

2
这里有一种更简单的方法,可以按网站分组迭代您的文件。
from collections import defaultdict
import glob

def get_site_files():
    sites = defaultdict(list)
    for fname in glob.glob('*.txt'):
        parts = fname.split('.')
        if len(parts)==6 and parts[2]=='WRFc36':
            sites[parts[0]].append(fname)
    return sites

def main():
    for site,files in get_site_files().iteritems():
        # you need to better explain what you are trying to do here!
        print site, files

if __name__=="__main__":
    main()

我还不理解你所说的列的剪切和粘贴 - 你需要更清楚地解释你想要实现什么。

我在http://codepad.org/3mQEM75e上放了一些新代码,反映了您上面的模式。至于剪切和粘贴列——我有几个研究站点——每个研究站点都有5个文本文件(每个变量一个)。因此,对于5个研究站点,我将拥有25个文本文件。每个文本文件的列格式相同:年月日变量值。我想从一个文件中复制日期,并从所有其他文件中仅复制每个研究站点的变量值——因此对于5个研究站点,我最终将只得到一个格式为:年月日Var1 Var2 Var3 Var4 Var5的文本文件。 - TheGeoEngineer
请注意,在这种情况下,glob.iglob('*.txt')将创建一个迭代器并避免创建值列表。 - hochl
@hochl 我想如果我使用方法2(在此处查看代码codepad.org/3mQEM75e),glob.iglob可能会更简单,但我想使用方法1... glob.glob适用于两种情况,不过——嗯,我该如何将更新的代码粘贴到原始问题中呢?我无法弄清楚,所以我提供了链接(codepad.org/3mQEM75e)。 - TheGeoEngineer
不确定您的意思,但是您可以编辑您的问题。将代码链接在帖子中可能会降低其价值,因为如果链接消失,代码也无法访问。因此,直接在帖子中包含相关代码通常更好。 - hochl
@hochl 明白了!我已经编辑了我的问题,现在附上了代码,而不是可能在未来失效的链接。你有什么想法,为什么我会在上面发布的方法2中丢失随机行? - TheGeoEngineer

1

就获取文件名而言,我会使用以下类似的方法:

import os

# Gets a list of all file names that end in .txt
# ON *nix
file_names = os.popen('ls *.txt').read().split('\n')

# ON Windows
file_names = os.popen('dir /b *.txt').read().split('\n')

然后,要获取通常由句点分隔的元素,请使用:

# For some file_name in file_names
file_name.split('.')

接下来,您可以进行比较并提取所需的列(使用open(file_name,'r')或CSV解析器)

迈克尔·G。


您还需要从文件名列表中删除“''”(空字符串)。 - mjgpy3
你对我写的这段代码有什么看法?(http://codepad.org/3mQEM75e)它没有使用你的代码,但也许你对这个版本有一些见解? - TheGeoEngineer

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