一次解析一个文件2行

时间:2017-07-06 14:26:36

标签: python

Python初学者。我有一个看起来像这样的文件(每个字段都是\ t分隔):

chr1_1792868_SNP    Bcin01g04980    NON_SYNONYMOUS  NON_SYNONYMOUS[T](gene:Bcin01g04980|transcript:Bcin01g04980.1|P->S:225) ...         
chr1_1792869_SNP    Bcin01g04980    NON_SYNONYMOUS  NON_SYNONYMOUS[T](gene:Bcin01g04980|transcript:Bcin01g04980.1|P->L:225) ...                 
chr2_19719_SNP  Bcin02g00005    SYNONYMOUS  SYNONYMOUS[A](gene:Bcin02g00005|transcript:Bcin02g00005.1)  ...         
chr2_19811_SNP  Bcin02g00005    SYNONYMOUS  SYNONYMOUS[A](gene:Bcin02g00005|transcript:Bcin02g00005.1)  ...         
chr2_20024_SNP  Bcin02g00005    NON_SYNONYMOUS  NON_SYNONYMOUS[C](gene:Bcin02g00005|transcript:Bcin02g00005.1|S->A:331)             
chr2_20025_SNP  Bcin02g00005    SYNONYMOUS  SYNONYMOUS[A](gene:Bcin02g00005|transcript:Bcin02g00005.1)

我想解析文件并一次比较2行,并比较它们之间的值。

所以在这种情况下,我想比较第1行和第2行,检查是否有" SYNONYMOUS"在每个人的第3个领域。如果是的话,我会做一些事情,如果没有(这种情况)我继续前进到第3和第4行(这次比较两个" SYNONYMOUS"值为正),我会选择该行的第一个值做了更多的事情(与另一个词典比较)。

我想做类似的事情:

with open ('file.txt') as mutmut_mutants:
    for line1 in mutmut_mutants:
        line2 = next(mutmut_mutants)
        print type(line1)
        print line2+ "line2"

但问题是我正在处理字符串而不是列表元素(在大列表中的行/元素上)。处理列表似乎比使用字符串/正则表达式更容易。然后我想到了这个:

with open ('file.txt') as mutmut_mutants:
    for i in csv.reader(mutmut_mutants, delimiter='\t'):
        for k,(l1, l2) in enumerate(zip(i[0::2], i[1::2])):
            print str(zip(i[0::2], i[1::2]))

但是我无法让它发挥作用(而且我不能很清楚地获得拉链和i [0 :: 2])。我要做的是:比较第2行和第2行,如果两行中的SYNONYMOUS获得每行的第一个字符串(chrX_XXXXX_SNP)。

有关我应该如何进行的任何想法?

6 个答案:

答案 0 :(得分:0)

我认为你要找的是字符串的split方法。像在第一个代码示例中一样遍历文件,然后使用以下选项分隔选项卡上的每一行:

ls = []
with open ('file.txt') as mutmut_mutants:
    for line1 in mutmut_mutants:
        fields = line1.split('\t')
        ls.append(fields)

拆分选项卡上的字符串将为您提供由制表符分隔的每个字段的列表。然后,您可以将其附加到列表中,然后根据需要进行处理。因此,例如,要访问第四行的第三个字段,您只需ls[3][2]。希望这会有所帮助。

答案 1 :(得分:0)

它可能取决于你的文本文件的重量(你可以拥有非常多的SNP ......)。

如果您可以将整个文件加载到一个变量中:

# Store everything in one variable - readlines() to have a list of lines
mutmut_mutants = open('file.txt', "r").readlines()

# The number of lines
n = len(mutmut_mutants)

# Loop two by two (end at n-1 or n-2)
for i in range(0, n-1, 2):
    first_line = mutmut_mutants[i]
    second_line = mutmut_mutants[i+1]

    # Split those lines (the separator is \t ?) and compare what's
    # inside, for example
    syn1 = first_line.split("\t")[2]
    syn2 = second_line.split("\t")[2]
    if syn1 == syn2 and syn1 == "SYNONYMOUS":
        # Do stuff

如果您无法在一个变量中加载所有内容。哼。我可能无法提出一些甚至非常漂亮的东西。希望这会有所帮助。

答案 2 :(得分:0)

你有一个迭代器,一次产生1个项目,即文件对象。

你需要一个包装那个并一次生成2个项目的迭代器。

这是一种天真的方法:

def even_by_two(incoming):
    while True:
        one = next(incoming)
        two = next(incoming)
        yield (one, two)
    # This will break on a StopIteration exception,
    # which is ok for a generator.
    # The odd item at the end will be silently missed.

演示:

with open('/etc/passwd') as f:
  for one, two in even_by_two(f):
    print ("one -> ", one)
    print ("two -> ", two)

问题当然是,如果行数不均匀,最后一行将会丢失。

这是一种不那么天真的方法,它通过给定大小的块来切割输入迭代器;最后一个块可以更小。

def by_n(how_much, incoming):
    while True: # We need a post-condition, got no do-while in Python.
        result = []
        count = 0
        # The `for` will advance the iterator, but not past its end.
        for value in incoming:  
            result.append(value)
            count += 1
            if count >= how_much:
                break
        if result:
            yield result
        else:  # We got nothing from the iterator, it must be over.
            break

>>> list(by_n(2, iter('abcdefg')))
[['a', 'b'], ['c', 'd'], ['e', 'f'], ['g']]
>>> list(by_n(5, iter('abcdefg')))
[['a', 'b', 'c', 'd', 'e'], ['f', 'g']]

请注意,输入必须是生成器/迭代器,例如一个文件,或csv.reader。一个简单的列表或字符串将不起作用,因此上面的iter(...)会生成一个迭代器。

答案 3 :(得分:0)

使用csv.reader是一种更好的解析CSV文件的方法,而不是手动执行。但是,您可以显式使用迭代器,而不是使用for循环,就像使用file对象一样。

with open ('file.txt') as mutmut_mutants:
    reader = csv.reader(mutmut_mutants, delimiter='\t')
    while True:
        try:
            l1 = next(reader)
            l2 = next(reader)
        except StopIteration:
            pass

        # Use l1 and l2 here

答案 4 :(得分:0)

您可以使用pandas模块将文件作为数据框读取(尽管您可能在排序列名时遇到一些麻烦。

假设你不熟悉大熊猫(把它放在你要学习的东西的清单上,对于任何与数据相关的东西都很值得),你可以试试这样的东西:

with open('file.txt') as f:
    data = f.readlines()

indexes = []
for i, line in enumerate(data[:-1]):
    if (line.split('    ')[2] == data[i+1].split('    ')[2]) and line.split('    ')[2] == 'SYNONYMOUS':
        indexes.append(i)

for i in indexes:
     print data[i], data[i+1] # or do whatever you want with those

索引是文件中每对符合条件的第一行的位置列表。

根据你想做的事情,pandas可能是更好的方式(这只是一个猜测,因为我不能将你的例子加载到pandas中,因为行的长度不同(由于......) )

import pandas as pd

df = pd.read_csv('file.txt', sep='\t', header=0) # might be header=None

df.columns=['mutation', 'strain', 'syn', 'info']

match_df = df.loc[df['syn'] == df['syn'].shift(1)] # might need to specify axis= for .shift

这将为您提供(再次)每对中第一个的数据帧。

答案 5 :(得分:0)

你可以制作两个数组并存储当前行和前一行:

list = []
list_before =[]
with open ('file.txt', 'r') as mutmut_mutants:
 list.append(mutmut_mutants.readline().split())
 print(list)

然后比较当前和前一个列表在同一位置是否为SYNNONYMOUS。

print(list[0][0][:3]) = "cnr"
print(list[0][0][-4:]) = "_SNP"

希望如果有帮助