찾다

 >  Q&A  >  본문

python优化代码(文本查找)效率?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<code>#!/usr/bin/env python

# -*- coding: utf-8 -*-

infile2 = open('genemark.gff3', 'r')

infile1 = set(line1.strip() for line1 in open('1.txt', 'r'))

for line in infile2:

    line = line.strip().split()

    if line[2] == 'gene':

        chr, start, end = line[0], int(line[3]), int(line[4])

        for line1 in infile1:

            line1 = line1.split()

            chr1, start1, end1 = line1[1], int(line1[2]), int(line1[3])

            if chr1 == chr:

                if start1 < start < end1:

                    print line1[0], line[-1]

                if start1 < end < end1:

                    print line1[0], line[-1]

                if start1 > start and end > end1:

                    print line1[0], line[-1]</code>

genemark.gff3 格式类似下边:

1

2

<code>chr1D    GeneMark.hmm    gene    2705930    2711118    .    +    .    ID=1903228_g;Name=1903228_g

chr1D    GeneMark.hmm    mRNA    2705930    2711118    .    +    .    ID=1903228_t;Name=1903228_t;Parent=1903228_g</code>

1.txt:

1

2

<code>UN011157 chr1D 2705329 2706342 98.4 95.0 972 30 21 0

UN003843 chr1D 2705681 2721144 61.4 97.4 633 12 5 0</code>

附上原始文件的百度云链接,希望感兴趣的参考
点击下载 密码 enu8

综合楼下各位朋友的答案,现推荐两种
第一种 根据 @ferstar @用筹兮用严 的答案,即并行版

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

<code>#!/usr/bin/env python

# encoding: utf-8

 

from collections import defaultdict

from multiprocessing import Pool, cpu_count

from functools import partial

 

 

def find_sth(f2, f1=None):

    start, end = int(f2[3]), int(f2[4])

    for uno1, start1, end1 in f1[f2[0]]:

        if (start1 <= start and start <= end1) or (start1 <= end and end <= end1) or (start1 >= start and end >= end1):

            with open("out.txt", "a") as fh:

                fh.write(uno1 + "\t" + f2[-1] + "\n")

                #print(uno1, f2[-1])

 

 

def main():

    with open('1.txt', 'r') as f1:

        infile1 = defaultdict(set)

        for uno1, chr1, start1, end1, *others in map(str.split, f1):

            infile1[chr1].add((uno1, int(start1), int(end1)))

    with open('genemark.gff3', 'r') as f2:

        infile2 = [x for x in map(str.split, f2) if x[2] == 'gene']

    pool = Pool(cpu_count())

    pool.map(partial(find_sth, f1=infile1), infile2)

    pool.close()

    pool.join()

 

 

if __name__ == "__main__":

    main()</code>

第二种 @citaret 他的版本(单核版),对单核来说,不逊于上述代码。但是两者结果稍有不同,并行版结果更全(这里少了73条,出在判断条件的边界问题,由于对intervaltree熟悉,怎么改还不知道),现在边界问题已修改,两种代码结果完全一样,perfect!
如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<code>

from collections import defaultdict

from intervaltree import Interval, IntervalTree

 

with open('1.txt') as f:

    d1 = defaultdict(list)

    xs = map(lambda x: x.strip().split(), f)

    for x in xs:

        y = (x[0], int(x[2]), int(x[3]))

        d1[x[1]].append(y)

 

    for k, v in d1.items():

        d1[k] = IntervalTree(Interval(s, e, u) for u, s, e in v)

 

with open('genemark.gff3') as f:

    for line in f:

        line = line.strip().split()

        if line[2] == 'gene':

            chr, start, end = line[0], int(line[3]), int(line[4])

            for start1, end1, un1 in d1[chr][start-1:end+1]:

                print(un1, line[-1])

</code>

PHP中文网PHP中文网2889일 전461

모든 응답(6)나는 대답할 것이다

  • 巴扎黑

    巴扎黑2017-04-18 09:18:12

    성능 최적화를 위한 여지는 없지만 코드는 약간 조정할 수 있습니다.

    으아악

    회신하다
    0
  • 阿神

    阿神2017-04-18 09:18:12

    다음은 두 가지 제안입니다.

    1. 코드가 너무 깊게 중첩되었습니다. 함수에서 가능한 한 빨리 반환하여 중첩 수준을 줄일 수 있습니다. 마찬가지로 루프에서 계속을 사용하여 중첩 수준을 줄일 수 있습니다.

    2. 공연소개

    으아악

    루프를 통해 매번 file1의 줄을 분할하는 것은 매우 현명하지 않습니다

    다음은 제가 수정한 코드입니다

    으아악

    회신하다
    0
  • PHPz

    PHPz2017-04-18 09:18:12

    genemark.gff3 목록과 1.txt 사전을 각각 구성하기 위해 공간을 교환합니다.

    으아악

    수정된 버전 v2는 내부 루프에서 int()를 제거하고 출력을 단순화합니다.

    으아악

    v3: 질문의 의미를 주의 깊게 연구한 결과, 메인 루프는 조각과 교차하는 세트의 모든 조각을 찾는 것임을 알았습니다.

    으아악

    각 컬렉션의 조각 수는 6000~10000개이며 순회는 비효율적입니다. 따라서 조각과 교차하는 모든 조각을 빠르게 가져오려면 간격 트리를 사용하는 것이 좋습니다.

    으아악

    시간 테스트 결과는 간격 트리를 구축하는 데 10초가 걸리지만 교차 과정의 속도는 약 100배 향상되었습니다.
    간격 참조 https://pypi.python.org/pypi/...

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-18 09:18:12

    파일을 연 후 닫을 필요는 없나요

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-18 09:18:12

    으아악

    6층 @ferstar님이 제안한 병렬화 방향은 맞는데 코드에 문제가 있네요...
    변경했습니다:

    으아악

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-18 09:18:12

    매우 흥미로운 점을 발견했습니다. 모두가 매우 긍정적으로 반응했지만 실제 결과는 심심해서 약간의 테스트를 수행했습니다.

    질문에 제공된 샘플 텍스트에는 두 줄만 있으므로 1.txtgenemark.gff34000

    에 각각 두 배로 늘렸습니다. 으아악

    응답한 층 수를 기준으로 정렬합니다. 예를 들어 질문자의 코드는 hi.py, 1층 응답자의 코드는 hi1.py 등입니다.

    • 질문 제목을 먼저 보세요

    • 으아악
    반복적인 느낌

    • 1층 응답자

    • 으아악
    또 할머니 댁에 갔다

    • 2층 응답자

    • 으아악
    • 3층 응답자

    • 으아악
    3층 응답자의 결과는 2층과 동일하지만 10초 이상 느립니다

    • 4층 답변(4층 반 친구들에게 잘못했어요. py3 코드입니다)

    • 으아악
    물론 소통이 발전을 가져오고 현재의 결과는 정확합니다

    요약

    실제로 질문자의 코드 결과가 중복된 것으로 보이며, 4층 응답자의 결과가 맞습니다

    나의 계획 - 4층 코드를 병렬로 조금씩 변경하기

    작성한 내용에 문제가 있어서 @yongchixiyongyan이 올바른 병렬 코드를 업데이트했고, 나중에 볼 친구들이 참조할 수 있도록 코드가 변경되지 않습니다

    직접 채점(python3)

    으아악

    그럼 운영효율을 보세요

    으아악

    시간 측면에서 훨씬 느린 것 같습니다(4000행의 데이터는 불과 수백 KB에 불과합니다). 질문자는 실제 데이터로 테스트해 볼 수 있으며, 처리되는 데이터가 클수록 더 명확해집니다. 병렬 처리의 효율성 이점

    PS: 질문자가 처리하는 데이터의 실제 크기는 MB 또는 GB 수준일 것으로 추정됩니다. 이 수준에서는 병렬 처리가 필요합니다

    원본 데이터 및 결과 주소 링크: http://pan.baidu.com/s/1hrSZQuS 비밀번호: u93n

    회신하다
    0
  • 취소회신하다