在数据处理过程中,可能会需要采用筛选、提取、重新生成等方法来对数据进行处理,下面以csv文件为例,介绍使用Python处理文本文件的方法。
开始之前
在面对文件读写类的问题时,
open
函数是一定绕不开的,下面先介绍几种
open
函数使用的技巧。
-
使用
with
来处理上下文,可以在读/写完成后自动关闭文件
file_path = 'test.csv'
# bad
fp = open(file_path, 'r')
fp.read()
fp.close()
# good
with open(file_path, 'r') as fp:
fp.read()
-
对文件直接进行循环(文件本身就是一个可迭代对象,可以直接进行循环遍历)
# bad
with open(file_path, 'r') as fp:
lines = fp.readlines()
for index in range(lines):
print(lines[index])
# good
with open(file_path, 'r') as fp:
for line in fp:
print(line)
# bad
with open(file1, 'r') as fp1:
with open(file2, 'w') as fp2:
for line in fp1:
fp2.write(line)
# good
with open(file1, 'r') as fp1, open(file2, 'w') as fp2:
for line in fp1:
fp2.write(line)
csv
csv文件是一类出现频率非常高的文本文件,在python中有许多方法可以读写他。下面介绍两种读写的方法。
在开始之前,先来介绍一下csv文件的格式,比如下面这个文件,里面有4行,第一行是表头或者叫列名(可以没有表头),每一列之间使用
,
隔开。后面3列是对应的内容,也是使用
,
进行隔开;每一行都是单独的,行与行之间使用
\n
进行分割,这个
\n
是一个不可见字符,作用是换行。
name,age,city
liming,12,taian
zhangsan,20,heze
lisi,18,shenzhen
读取
原生方法
原生方法是指不借助第三方库,只使用python本身来进行读写。
根据上面我们对csv文件的了解,我们可以得到下面这些信息
-
第一行可能是表头,也可能直接就是数据
-
列与列之间使用
,
进行分割
-
行与行之间使用
\n
进行分割
下面来编写函数来进行解析csv文件,我们需要一个文件路径
csv_file
来进行读取,需要分隔符
sep
,来确定列与列之间是由什么来进行分割的,最后还需要一个
header
来控制是否在最后的数据中保留第一行(因为第一行可能是表头,不是真正的数据)
def parse_csv(csv_file, sep=',', header=False):
result = [] # 存放最终的数据
with open(csv_file, 'r') as fp:
# 如果是True,那么可以跳过第一行
if header:
fp.readline() # 直接丢弃(读取)第一行
for line in fp:
result.append(line.split(sep)) # 根据sep来进行分割
return result
Pandas
pandas是python中一个十分强大的数据分析工具,下面使用pandas来实现和上面代码一样的功能
import pandas as pd
result = pd.read_csv(csv_file, sep=',', header=None) # 包括第一行
result = pd.read_csv(csv_file, sep=',') # 不包括第一行
可以发现,两种方式的代码量相差很大,第二种方法几乎是一行代码就可以实现csv的读取。上面两种方法都是读取的操作,下面来介绍写入的操作
写入
原生方法
在写入的时候,我们只需要构造出符合csv文件格式的字符串,然后写入文件即可
将每一列的数据使用分隔符
sep
进行连接,将每一行之间的数据使用
\n
进行分割
data = [
['liming','12','taian'],
['zhangsan','20','heze'],
['lisi','18','shenzhen'],
def write_csv(data, output_file, sep=','):
with open(output_file, 'w') as fp:
for line in data:
# 使用sep将每一行中的数据连接起来
# 同时在最后加上\n来进行换行
fp.write(sep.join(line) + '\n')
pandas
import pandas as pd
data = [
['liming', '12', 'taian'],
['zhangsan', '20', 'heze'],
['lisi', '18', 'shenzhen'],
df = pd.DataFrame(data) # 需要先构造一个数据表
# 把构造的数据表存下来,不存表头,不存索引
df.to_csv(output_file, header=None, index=None)
下面我将从一个具体的案例来讲述如何使用python来完成文本处理的任务。
案例讲解
需求
有一个csv文件,第一列是
gene_id
,第二列是表达量
现在你需要在里面筛选20个特定的基因,同时根据另一个文件为这20个
gene_id
重命名
最后将筛选出来的
gene_id
和
expression
保存到一个新的csv文件里面
实现
下面我们也是使用两种方法来完成这个需求
原生方法
def get_geneid_map(geneid_map_csv):
""" 将第二个csv文件转化从dict中,旧id做key,新id做value """
result = {}
with open(geneid_map_csv,'r') as fp:
fp.readline() # 去掉表头
for line in fp:
line = line.strip('\n') # 去掉最后的\n
line = line.split(',') # 根据,进行分割
result[line[0]] = line[1] # 存到字典里面
return result
def parse_gene_file(gene_file,geneid_map_dict):
result = []
with open(gene_file,'r') as fp:
fp.readline() # 去掉表头
for line in fp:
line = line.strip('\n')
line = line.split(',')
if line[0] in geneid_map_dict:
result.append([
geneid_map_dict[line[0]], # 根据旧id获得新id
line[1] # 表达量
return result
def save_to_csv(result,output_file):
with open(output_file,'w') as fp:
for line in result:
fp.write(','.join(line) + '\n')
if __name__ == '__main__':
csv_file1 = 'gene.csv'
csv_file2 = 'geneid_map.csv'
csv_result = 'filter.csv'
geneid_map = get_geneid_map(csv_file2)
result = parse_gene_file(csv_file1,geneid_map)
save_to_csv(result,csv_result)
pandas
if __name__ == '__main__':
csv_file1 = 'gene.csv'
csv_file2 = 'geneid_map.csv'
csv_result = 'filter.csv'
import pandas as pd
# 读取csv文件,数据不包含header
gene = pd.read_csv(csv_file1,sep=',')
geneid = pd.read_csv(csv_file2,sep=',')
# 使用isin筛选需要的id,同时拷贝一份
filter_gene = gene[gene['gene_id'].isin(geneid['gene_id1'])].copy()
# 构造字典,与上面构造的字典相同
geneid_map = {v['gene_id1']:v['gene_id2'] for k,v in geneid.to_dict('index').items()}
# 使用字典对旧id进行替换
filter_gene['gene_id'] = filter_gene['gene_id'].map(geneid_map)
# 保存csv,不包含表头,不包含索引
filter_gene.to_csv(csv_result,header=None,index=None)
后台回复
csv
即可获得案例中使用的文件
在本文中,我们将学习如何在CSV 文件使用 Python 读取和写入数据,以及如何将 CSV 文件转换为 JSON 格式,反之亦然。我们将探讨如何使用 csv 模块,并查看有助于理解其工作原理的示例。