Python运算符和优先级

运算符 说明
yield X 生成器函数结果(返回send()值)
lambda args1:X 匿名函数生成器(调用后返回X)
X if Y else Z 三元选择(当Y为真时计算X,否则计算Z)
X or Y 逻辑或
X and Y 逻辑与
not X 逻辑非
X in Y, X not in Y 成员是否在可迭代对象中
X is Y, X is not Y 对象等价测试
X Y, X >= Y 大小比较
X == Y, X != Y 相等运算符
X | Y 集合并
X ^ Y 集合对称差
X ^ Y 集合交
X << Y, X >> Y 将X左/右移Y位
X + Y, X – Y 加,减
X * Y, X / Y, X // Y, X % Y 乘,除,整除,取余
-X, +X 负,正
~X 按位非补(倒置)
X ** Y 乘方
X[i] 索引(序列,映射,其他)
X[i:j:k] 切片
X(args) 调用(函数,方法,类和其他可调用对象)
X.attr 属性引用
(…) 元组,表达式,生成器表达式
[…] 列表,列表内涵
{…} 字典,集合,字典与集合内涵

参考:
《Python袖珍指南》(第五版)

Python常用转义字符

转义字符 含义 转义字符 含义
\newline 忽略换行 \t 水平制表符
\\ 反斜杠(\) \v 竖直制表符
\’ 单引号(‘) \N{id} Unicode dbase id
\” 双引号(“) \uhhhh Unicode 16位十六进制
\a 蜂鸣(Bell) \Uhhhhhhhh Unicode 32位十六进制
\b 空格 \xhh Hex(最多两位数字)
\f 换页 \ooo Octal(达到三位数字)
\n 换行 \0 Null(非字符串结尾)
\r 回车 \other 非转义字符

这里的大部分转义字符跟linux系统保持一致!
\Uhhhhhhhh严格采用8个十六进制数字(h)。\u和\U只可以用在Unicode字符串文字中。

BED格式转GTF格式

# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 19:43:00 2015
 
@author: biochen
"""
 
import sys, getopt, csv
 
# get parameter
opts, args = getopt.getopt(sys.argv[1:], "hi:o:s:")
input_file = ""
output_file = ""
source = ""
for op, value in opts:
    if op == "-i":
        input_file = value
    elif op == "-o":
        output_file = value
    elif op == "-s":
        source = value
    elif op == "-h":
        print("Usage: python3 BED2GTF.py -i input.bed -o output.gtf -s source")
        sys.exit()
 
 
BED_in_file = open(input_file, "r")
GTF_out_file = open(output_file, "w")
BED = csv.reader(BED_in_file, dialect = "excel-tab")
GTF = csv.writer(GTF_out_file, dialect = "excel-tab", quotechar = "'")
 
for item in BED:
    transcript = []
    transcript.append(item[0])
    transcript.append(source)
    transcript.append("transcript")
    transcript.append(int(item[1]) + 1)
    transcript.append(int(item[2]) + 1)
    transcript.append(item[4])
    transcript.append(item[5])
    transcript.append(".")
    transcript.append('transcript_id "' + item[3] + '";')
    GTF.writerow(transcript)
    exon_number = int(item[9])
    exon_size = list(map(int, (filter(lambda x:x and len(x.strip()) > 0, item[10].split(",")))))
    exon_start = list(map(int, (filter(lambda x:x and len(x.strip()) > 0, item[11].split(",")))))
    for i in range(exon_number):
        exon = []
        exon.append(item[0])
        exon.append(source)
        exon.append("exon")
        exon.append(int(item[1]) + exon_start[i] + 1)
        exon.append(exon[3] + exon_size[i] - 1)
        exon.append(item[4])
        exon.append(item[5])
        exon.append(".")
        exon.append('transcript_id "' + item[3] + '\";')
        GTF.writerow(exon)
 
BED_in_file.close()
GTF_out_file.close()

GTF格式转BED格式

 # -*- coding: utf-8 -*-
"""
Created on Wed Dec 16 11:03:05 2015
 
@author: biochen
"""
 
import sys, getopt, csv, re
 
opts, args = getopt.getopt(sys.argv[1:], "hi:o:")
for op, value in opts:
    if op == "-i":
        GTF_in_File_Name = value
    elif op == "-o":
        BED_in_File_Name = value
    elif op == "-h":
        print("Usage: python3 GTF2BED.py -i input.gtf -o output.bed")
        sys.exit()
 
GTF_in_file = open(GTF_in_File_Name, "r")
BED_out_file = open(BED_in_File_Name, "w")
GTFs = csv.reader(GTF_in_file, dialect = "excel-tab")
BEDs = csv.writer(BED_out_file, dialect = "excel-tab")
 
transcripts = {}
for GTF in GTFs:
    if GTF[2] == "exon":
        transcript_id = re.findall('transcript_id "([^;]*)"', GTF[8])[0]
        if transcript_id in transcripts:
            transcripts[transcript_id][6].append([int(GTF[3]), int(GTF[4])])
        else:
            transcripts[transcript_id] = []
            transcripts[transcript_id].append(GTF[0])
            transcripts[transcript_id].append(GTF[3])
            transcripts[transcript_id].append(GTF[4])
            transcripts[transcript_id].append(GTF[5])
            transcripts[transcript_id].append(GTF[6])
            transcripts[transcript_id].append(transcript_id)
            transcripts[transcript_id].append([[int(GTF[3]), int(GTF[4])]])
 
for transcript in transcripts:
    transcripts[transcript][6].sort()
    transcript_start = transcripts[transcript][6][0][0]
    transcript_end = transcripts[transcript][6][len(transcripts[transcript][6]) - 1][1]
    exon_sizes = ""
    exon_starts = ""
    for exon in transcripts[transcript][6]:
        exon_size = exon[1] - exon[0] + 1
        exon_start = exon[0] - transcript_start
        exon_sizes = exon_sizes + str(exon_size) + ","
        exon_starts = exon_starts + str(exon_start) + ","
    BED = []
    BED.append(transcripts[transcript][0])
    BED.append(transcript_start - 1)
    BED.append(transcript_end)
    BED.append(transcripts[transcript][5])
    BED.append(transcripts[transcript][3])
    BED.append(transcripts[transcript][4])
    BED.append(transcript_start - 1)
    BED.append(transcript_end)
    BED.append("0, 0, 0")
    BED.append(len(transcripts[transcript][6]))
    BED.append(exon_sizes)
    BED.append(exon_starts)
    BEDs.writerow(BED)
 
GTF_in_file.close()
BED_out_file.close()

Python计算Rank(秩)

在统计学中,有时候我们需要求一组数据的Rank,如非参检验、Spearman相关性等。Rank中文意思叫做顺序,更专业点的叫法是”秩”。这里介绍一下用Python求Rank。
先看一个简单的例子:

>>> a = [1.0, 5.6, 3.5, 9.7, 7.8]
>>> # rank_a = [1, 3, 2, 5, 4]
...
>>> rank_a = sorted(range(len(a)), key = a.__getitem__)
>>> rank_a
[0, 2, 1, 4, 3]
>>> rank_a = [i + 1 for i in rank_a]
>>> rank_a
[1, 3, 2, 5, 4]

上面的例子中,列表a中的元素是没有重复的,直接排序即可。如果有重复元素怎么办呢?最简单的办法是使用SciPy提供的rankdata()函数。

>>> from scipy.stats import rankdata
>>> rankdata([0, 2, 3, 2])
array([ 1. ,  2.5,  4. ,  2.5])
>>> rankdata([0, 2, 3, 2], method='min')
array([ 1,  2,  4,  2])
>>> rankdata([0, 2, 3, 2], method='max')
array([ 1,  3,  4,  3])
>>> rankdata([0, 2, 3, 2], method='dense')
array([ 1,  2,  3,  2])
>>> rankdata([0, 2, 3, 2], method='ordinal')
array([ 1,  2,  4,  3])

rankdata()函数返回一个array对象,默认的方法是average,即相同元素的Rank值取算术平均数,同时rankdata()函数还提供了其他方法。
如果觉得安装SciPy库太麻烦,我们也可以自己实现。下面的代码计算重复元素的Rank使用的方法是average,返回一个列表。

def rank_simple(vector):
    return sorted(range(len(vector)), key=vector.__getitem__)
 
def rankdata(vector):
    n = len(vector)
    ivec = rank_simple(vector)
    svec = [vector[rank] for rank in ivec]
    sumranks = 0
    dupcount = 0
    newvector = [0] * n
    for i in range(n):
        sumranks = sumranks + i
        dupcount = dupcount + 1
        if i == n - 1 or svec[i] != svec[i + 1]:
            averank = sumranks / float(dupcount) + 1
            for j in range(i - dupcount + 1, i + 1):
                newvector[ivec[j]] = averank
            sumranks = 0
            dupcount = 0

Python列表推导式

Python进阶之一就是学会写列表推导式。列表推导式用较为优雅的方式生成列表,从而避免冗余代码,不过对于新手来讲,代码的可读性不高。我们先看下面一段示例。

>>>a = [1, 2, 3, 4]
>>>b = [item * 2 for item in a]
>>>b
[2, 4, 6, 8]

上述代码将一个列表中每一个元素加倍生成一个新的列表,可以写成如下更容易理解的形式:

>>>a = [1, 2, 3, 4]
>>>b = []
>>>for item in a:
...     b.append(item * 2)
...
>>>b
[2, 4, 6, 8]

结果是一样的,但是列表推导式所需的代码更少。如果我们只想保留偶数并加倍,可以这么写:

>>>a
[1, 2, 3, 4]
>>>b = [item * 2 for item in a if item % 2 == 0]
>>>b
[4, 8]

总结一下,Python列表推导式的模式为[expression for item in sequence if conditions]。列表推导式放在[]中;首先是一个表达式,定义了对每一个元素要做什么;接下来是一个for循环,从一个序列中依次拿出一个元素;最后是if条件,可以没有if条件。[]改为()得到的是一个生成器(generator),改为{}得到一个字典或者集合。
用列表推导式可以写出更有创意的代码,当然如果代码很难被读懂,应该尽量实现更好可读性的代码。可读性高的代码才更加具有生命力。

Python字典(dict)的setdefault()方法

如果需要统计一个字符串中每一个字符出现的次数,我会写出如下的代码:

Strings = "Welcome to my blog: blog.biochen.com!"
count = {}
for character in Strings:
	if character in count:
		count[character] = count[character] + 1
	else:
		count[character] = 0
		count[character] = count[character] + 1
print(count)

需要初始化字典中的元素的场景还是很常见的,似乎用if..else…看起来比较傻。不过Python内置了字典(dict)的setdefault()方法,上述代码可以写成这样子:

Strings = "Welcome to my blog: blog.biochen.com!"
count = {}
for character in Strings:
	count.setdefault(character, 0)
	count[character] = count[character] + 1
print(count)

dict.setdefault(key, default=None)的作用是,如果健不在字典中,将会添加健,并将值设置为默认值。
不过用if…else…比用setdefault()速度要快!!!

 

Python实现DNA序列互补、反向、反向互补

DNA有两条链,但是通常我们只用其中一条链来表示,另外一条链是它的反向互补序列。利用Python我们可以轻松地实现DNA序列的反向、互补、及反向互补。

定义函数DNA_complement()实现DNA序列互补配对,函数DNA_reverse() 实现DNA序列反向。

def DNA_complement(sequence):
    sequence = sequence.upper()
    sequence = sequence.replace('A', 't')
    sequence = sequence.replace('T', 'a')
    sequence = sequence.replace('C', 'g')
    sequence = sequence.replace('G', 'c')
    return sequence.upper()
 
def DNA_reverse(sequence):
    sequence = sequence.upper()
    return sequence[::-1]

我们来演示一下:

>>> DNA = "acctgCaG" #原序列
>>> DNA_complement(DNA) #互补序列
'TGGACGTC'
>>> DNA_reverse(DNA) #反向序列
'GACGTCCA'
>>> DNA_reverse(DNA_complement(DNA)) #反向互补序列
'CTGCAGGT'

Python去掉列表中的重复元素

集合(set)是不允许有重复元素的,我们可以将列表(list)转换为集合,再转换回列表。
>>> List1 = [“b”, “c”, “a”, “d”, “a”, “c”]
>>> List2 = list(set(List1))
>>> List2
[‘a’, ‘b’, ‘d’, ‘c’]
去除重复元素之后顺序变了,如果想要保持原来的顺序,可以将新列表按照原来的列表排序。
>>> List2.sort(key = List1.index)
>>> List2
[‘b’, ‘c’, ‘a’, ‘d’]
还可以换一种写法。
>>> List2 = sorted(set(List1), key = List1.index)
>>> List2
[‘b’, ‘c’, ‘a’, ‘d’]