我是python的新手,为两个制表符分隔的输入文件制作了两个数组。我正在寻找一种方法来将一个数组的列(元素)以数字方式与另一个数组的元素进行比较。有没有办法做到这一点。我的代码到现在为止
#!/usr/bin/python
import sys
from array import *
#print len(sys.argv)
if len(sys.argv) != 4:
print 'Usage: python scores.py <infile1> <infile2> <outfile>'
sys.exit(1)
f1 = open ("12877overlappedallvariants.gvf", "r")
f2 = open ("unmatched.12877overlappedallvariants.gvf", "r")
f3 = open ("out.txt", "w")
for line in f1.readlines():
cols = line.split('\t')
#print cols[5:6]
for line in f2.readlines():
cols1 = line.split('\t')
#print cols1[5:6]
我在下面的代码部分尝试了这个但不起作用
slice1 = cols[5:6]
slice2 = cols1[5:6]
new_list = []
for element in slice1:
if element in slice2:
new_list.append(element)
print new_list
我试图看看array1的元素5是否等于,大于或小于array2的元素5。任何帮助表示赞赏。感谢。
答案 0 :(得分:1)
值得注意的是,这些是列表,而不是数组。有区别。
每次循环时你都会覆盖cols
- 这意味着你只能得到最后一行数据 - 这里有一个列表理解来获取你想要的所有数据,或者更好的是,根本就没有完全存储数据 - 按照你想要的操作进行操作。
比较的主要问题是你正在采用列表切片,而不是仅仅采用你需要的元素。这使你想要做的事情过于复杂。
因此,正如我在评论中提到的,您可以对初始代码进行大量改进 - 主要是with
语句和csv
模块。
首先,使用with
语句打开文件。我们也使用csv.reader()
,使用"excel-tab"
方言,因为它是制表符分隔文件,csv.QUOTE_NONNUMERIC
告诉它值是数字,所以我们不必将它们从字符串以后。请注意,如果只有某些值是数字,则需要引用所有非数字值才能使用此方法,或者明确转换这些值而不使用它。
with open("file1.tsv") as file1, open("file2.tsv") as file2:
rows = csv.reader(file2, dialect="excel-tab", quoting=csv.QUOTE_NONNUMERIC)
rows1 = csv.reader(file2, dialect="excel-tab", quoting=csv.QUOTE_NONNUMERIC)
要执行检查,只需执行以下操作(从上面with
块中继续):
for cols, cols1 in zip(rows, rows1): #Use itertools.izip() in 2.x for efficiency.
first = cols[4]
second = cols1[4]
if first < second:
...
elif first == second:
...
else: #first > second
...
请注意使用zip一次循环遍历这两个文件。我们需要循环遍历文件,因为它们一次返回一行,每行都是每列的数据列表。然后,您可以随意使用数据。我给出了一个比较第五个值的例子(注意索引4
- python是0
索引的 - 也就是说,第一个值是0
,所以第五个值是{{1} })。
通过循环浏览文件,我们确保不必创建列表并临时存储数据 - 如果我们最终处理大文件,这将非常有用。
如果您需要稍后使用该数据,并希望将其作为列表,则可以通过在{{1}周围调用4
来简单地创建两个rows
对象列表}第
答案 1 :(得分:0)
有一些事情你需要注意 - 首先,在阅读你的文件之后,你只存储了最后一行(在一个名为'cols'的变量中不少;)。循环如:
lines1=f1.readlines()
lines2=f2.readlines()
for f1line,f2line in zip(lines1,lines2):
#compare here
可能更合适。这会将两个文件的全部内容读入内存 - 有一些方法可以在不读取大量数据的情况下执行此操作,但有时这是最简单的方法。 zip
可能有点令人困惑,但基本上,它匹配file1的第一行和file2的第一行,然后匹配两个文件的第二行,依此类推......
如@Lattyware的评论所述,上述内容相当于:
for f1line,f2line in zip(f1,f2):
#compare here
因为文件可以迭代。在python 2中,它仍将一次读取/存储两个文件,但在python 3中,它一次只能从每个文件中生成一行。最后,如果您不想在python 2中存储文件的所有内容,可以使用itertools.izip
import itertools
for f1line,f2line in itertools.izip(f1,f2):
#compare here
的工作原理与zip
类似,只是它一次产生一个元素。这里的缺点是当你转移到python 3时itertools.izip
消失了......但是,在这种情况下,2to3
应该进行适当的转换。 (有关详细信息,请参阅评论)。
至于比较,这在很大程度上取决于文件包含的内容。如果它包含数字,你可以这样做......
for f1line,f2line in zip(lines1,lines2):
row1=map(float,f1line.split())
row2=map(float,f2line.split())
#compare the 5th element
if(row1[4]==row2[4]):
#equal
elif(row1[4]>row2[4]):
...
如果你没有map(float,...)
位,python将进行字符串比较。
python也有cmp function可能很有用。
答案 2 :(得分:0)
我会这样写:
import csv
file1 = csv.reader(open('name1'), delimiter='\t')
file2 = csv.reader(open('name2'), delimiter='\t')
for row1, row2 in zip(file1, file2):
print cmp(row1[5], row2[5])
`
cmp返回-1表示lt,0表示eq,或1表示gt
如果行?[5]是数字,那么......
print cmp(float(row1[5]), float(row2[5])) # or int, or any other dtype