Python 从多个文件中搜索和排序数据
我有一组1000个文本文件,它们的名称分别为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
和。每个文件包含数百万行,每行有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)