Python 从多个文件中搜索和排序数据

Python 从多个文件中搜索和排序数据,python,bash,Python,Bash,我有一组1000个文本文件,它们的名称分别为和。每个文件包含数百万行,每行有7列,如: ccc245 1 4 5 5 3 -12.3 对我来说,最重要的是第一列和第七列的值;成对的ccc245,-12.3 我需要做的是在_sxxx.txt文件中找到所有,第七列值最低的10个案例,我还需要得到每个值的位置,在哪个文件中。我需要像这样的东西: FILE 1st_col 7th_col in_s540.txt ccc3456 -9000.5 in_s520.txt ccc488 -723.4

我有一组1000个文本文件,它们的名称分别为
。每个文件包含数百万行,每行有7列,如:

ccc245 1 4 5 5 3 -12.3
对我来说,最重要的是第一列和第七列的值;成对的
ccc245,-12.3

我需要做的是在_sxxx.txt
文件中找到所有
,第七列值最低的10个案例,我还需要得到每个值的位置,在哪个文件中。我需要像这样的东西:

FILE  1st_col  7th_col

in_s540.txt ccc3456 -9000.5
in_s520.txt ccc488 -723.4
in_s12.txt ccc34 -123.5
in_s344.txt ccc56 -45.6
我曾考虑为此使用python和bash,但目前我没有找到一种实用的方法。我所知道要做的就是:

  • 中的所有
    文件连接到.TXT中的
  • 使用:
    for i in.TXT搜索其中的最低值;do sort-k6n$i|head-n 10;完成
  • 给定前十名列表中的第1列和第7列值,使用
    grep-n VALUE in_s*
    ,使用它们来过滤in_s文件,因此我得到每个值的文件名
  • 它可以工作,但有点乏味。我想知道是否有一种只使用bash或python或两者都使用的更快的方法。或者用另一种更好的语言


    谢谢

    请在python中尝试以下内容:

    min_values = []
    
    def add_to_min(file_name, one, seven):
        # checks to see if 7th column is a lower value than exiting values
        if len(min_values) == 0 or seven < max(min_values)[0]:
            # let's remove the biggest value
            min_values.sort()
            if len(min_values) != 0:
                min_values.pop()
            # and add the new value tuple
            min_values.append((seven, file_name, one))
    
    # loop through all the files
    for file_name in os.listdir(<dir>):
        f = open(file_name)
        for line in file_name.readlines():
            columns = line.split()
            add_to_min(file_name, columns[0], float(columns[6]))
    
    # print answers
    for (seven, file_name, one) in min_values:
        print file_name, one, seven
    
    min_值=[]
    def add_to_min(文件名,一,七):
    #检查第7列的值是否低于现有值
    如果len(最小值)=0或七<最大值(最小值)[0]:
    #让我们去掉最大值
    最小值。排序()
    如果len(最小值)!=0:
    min_values.pop()
    #并添加新的值元组
    追加((七个,文件名,一个))
    #循环浏览所有文件
    对于os.listdir()中的文件名:
    f=打开(文件名)
    对于文件_name.readlines()中的行:
    columns=line.split()
    将_添加到_min(文件名,列[0],浮点(列[6]))
    #打印答案
    对于最小值中的(七个,文件名,一个):
    打印文件名,一,七
    
    还没有测试过,但应该可以开始了

    版本2,只需运行一次排序(在S.Lott的提示之后):

    值=[]
    #循环浏览所有文件,并列出所有行的长列表
    对于os.listdir()中的文件名:
    f=打开(文件名)
    对于文件_name.readlines()中的行:
    columns=line.split()
    append((文件名,列[0],float(列[6]))
    #排序值,打印10个最小值
    value.sort()
    值[:10]中的(七,文件名,一)
    打印文件名,一,七
    
    只要重新阅读您的问题,有数百万行,您可能会耗尽RAM….

    我会:

    • 以前10项为例
    • 把它们分类,然后
    • 对于从文件中读取的每一行,将元素插入前10行:
      • 如果其值低于当前top10中的最高值
      • (保持性能排序)
    我不会在这里发布完整的程序,因为它看起来像家庭作业


    是的,如果不是10,这将不是最佳的

    对shell解决方案的一个小小改进:

    $ cat in.txt
    in_s1.txt
    in_s2.txt
    ...
    $ cat in.txt | while read i
    do
      cat $i | sed -e "s/^/$i /" # add filename as first column
    done |
    sort -n -k8 | head -10 | cut -d" " -f1,2,8
    

    如果你的文件是百万行,你可能想考虑使用“缓冲”。下面的脚本通过那些百万行,每次比较字段7和缓冲区中的值。如果一个值小于缓冲区中的值,缓冲区中的一个被新的较低的值替换。

      for file in in_*.txt
        do
            awk -vt=$t 'NR<=10{
                c=c+1
                val[c]=$7
                tag[c]=$1
            }
            NR>10{
                for(o=1;o<=c;o++){
                    if ( $7 <= val[o] ){
                        val[o]=$7
                        tag[o]=$1
                        break
                    }
                }
            }
            END{
                for(i=1;i<=c;i++){
                    print val[i], tag[i] | "sort"
                }
    
            }' $file
        done
    
    _*.txt中文件的
    
    做
    awk-vt=$t'NR10{
    
    对于(o=1;o而言,这可能与您要查找的内容非常接近:

    for file in *; do sort -k6n "$file" | head -n 10 | cut -f1,7 -d " " | sed "s/^/$file /" > "${file}.out"; done
    
    cat *.out | sort -k3n | head -n 10 > final_result.out
    
    在python中,使用--它正是为这种任务而设计的

    Python 2.5和2.6的示例(已测试):

    import heapq, glob
    
    def my_iterable():
        for fname in glob.glob("in_s*.txt"):
            f = open(fname, "r")
            for line in f:
                items = line.split()
                yield fname, items[0], float(items[6])
            f.close()
    
    result = heapq.nsmallest(10, my_iterable(), lambda x: x[2])
    print result
    
    接受上述答案后更新

    查看Python2.6的源代码,似乎有一种可能性,它确实
    list(iterable)
    ,并在这方面起作用……如果是这样的话,那么这将不适用于1000个文件,每个文件都有数百万行。如果第一个答案给出MemoryError等,那么这里有一个替代方法将列表的大小限制为n(在您的情况下,n==10)

    注意:仅限2.6;如果您在2.5版中需要它,请使用文档中解释的条件
    heapplace()
    。使用
    heappush()
    heappushpop()
    ,它们没有
    参数:-(因此我们必须伪造它)

    import glob
    from heapq import heappush, heappushpop
    from pprint import pprint as pp
    
    def my_iterable():
        for fname in glob.glob("in_s*.txt"):
            f = open(fname, "r")
            for line in f:
                items = line.split()
                yield -float(items[6]), fname, items[0]
            f.close()
    
    def homegrown_nlargest(n, iterable):
        """Ensures heap never has more than n entries"""
        heap = []
        for item in iterable:
            if len(heap) < n:
                heappush(heap, item)
            else:
                heappushpop(heap, item)
        return heap
    
    result =  homegrown_nlargest(10, my_iterable())
    result = sorted(result, reverse=True)
    result = [(fname, fld0, -negfld6) for negfld6, fname, fld0 in result]
    pp(result)
    
    导入全局
    从heapq导入heappush,heappushpop
    从pprint导入pprint作为pp
    def my_iterable():
    对于glob.glob(“in_s*.txt”)中的fname:
    f=打开(fname,“r”)
    对于f中的行:
    items=line.split()
    收益率-浮动(项目[6]),fname,项目[0]
    f、 关闭()
    def国产最大(n,可移植):
    “”“确保堆中的条目不超过n个”“”
    堆=[]
    对于iterable中的项目:
    如果len(heap)
    “要在所有in_sxxx.txt文件中查找第七列值最低的10个案例”这不是您的脚本所做的。它为每个文件打印最小值。这将从每个文件中获取十个最小值,并对生成的
    n*10
    值列表进行排序。这不是要求的。哎呀,忘记了
    head
    命令。修复了。感谢您的否决票。这
    minu values.sort()
    非常麻烦。我认为可以对其进行修改以删除不必要的排序。是的,它很小,但会执行数百万次,似乎没有帮助。也许,但我们需要使用pop删除最大的值,因此需要对最小值进行排序。您可能可以更有效地进行排序,但有时比f更简单aster,特别是如果代码只运行几次。让我看看是否能想出更好的方法。我想你
    import glob
    from heapq import heappush, heappushpop
    from pprint import pprint as pp
    
    def my_iterable():
        for fname in glob.glob("in_s*.txt"):
            f = open(fname, "r")
            for line in f:
                items = line.split()
                yield -float(items[6]), fname, items[0]
            f.close()
    
    def homegrown_nlargest(n, iterable):
        """Ensures heap never has more than n entries"""
        heap = []
        for item in iterable:
            if len(heap) < n:
                heappush(heap, item)
            else:
                heappushpop(heap, item)
        return heap
    
    result =  homegrown_nlargest(10, my_iterable())
    result = sorted(result, reverse=True)
    result = [(fname, fld0, -negfld6) for negfld6, fname, fld0 in result]
    pp(result)