数据处理过程中常用到的数据文件格式有txt,csv,excel,xml,数据库。本文的应用对象是数据处理,所以我们关注的是结构化数据。至于基础的文本读写不在本文的讨论范围。对于不同类型的数据,我们用到的工具也不同。
- txt,csv通常存储关系型数据,也就是是可以用二维数组表示。对于这一类数据,我们一般使用pandas读写。所以这里介绍pandas内置的函数处理方法。
- excel也可以存储关系型数据,但对比csv可以设计更复杂的结构。我们使用xlrd读取,xlwt写入。
- xml可以存储多层级的数据,例如描述一个对象时需要多层次,多维度的数据。Python支持两种机制——SAX和minidom。SAM是基于事件响应机制的,也就是顺序读取xml文件,发现一个节点就会调用相关函数。而minidom是根据xml整个文件建立一个树形结构,然后提供遍历搜索的方法。我们这里介绍minidom方法。
- 数据库是管理数据的专业工具,特别适用于多人共享数据的场合。本文介绍Python对MySQL数据库的读写。实际上Python对SQLite数据库的支持更好。但是SQLite实际上只是使用SQL语句操作文件。如果只是想锻炼SQL语言,开发又只限于本地,SQLite倒是个不错的选择。
txt文本数据读取
pandas可以使用函数read_table()读取txt文件
import pandas as pd
# 根据正则解析来辨识间隔符号
txtframe = pd.read_table('./Data/tmp_4.txt',sep=r'\s+')
print(txtframe, "\n-----*-----")
txtframe = pd.read_table('./Data/tmp_4.txt',sep=r'\s+',header=None,engine='python')
print(txtframe, "\n-----*-----")
# 使用skiprows选项,可以排除多余的行。把要排除的行的行号放到数组中,赋给该选项即可。
txtframe = pd.read_table('./Data/tmp_4.txt',sep=r'\s+',skiprows=[3,4])
txtframe = txtframe.reset_index(drop=True)
print(txtframe)
我没有找到pandas对txt的写入文件,实际上csv和txt是共通的,我们可以用to_csv函数来写入txt文件。但还是有点不专业。这里补充numpy对txt文件的处理。
import numpy as np
data = np.loadtxt('./Data/tmp_2.csv',delimiter=',')
print(data)
np.savetxt('./Data/tmp_7.txt',data,fmt='%d',delimiter=',',newline='\n')
csv文件读写
pandas支持多种数据读写方法,这里列举一些方法。
读取 | 写入 | 数据文件 |
---|---|---|
read_clipboard | to_clipboard | 从剪贴板中读写 |
read_csv | to_csv | CSV |
read_excel | to_excel | Excel |
read_sql | to_sql | |
read_pickle | to_pickle | |
read_json | to_json | |
read_msgpack | to_msgpack | |
read_stata | to_stata | |
read_gbq | to_gbq | 从Google BigQuery加载数据 |
read_hdf | to_hdf | |
read_html | to_html | |
read_parquet | to_parquet | |
read_feather | to_feather |
pandas中read_csv()和to_csv()可以处理csv文件
import pandas as pd
a = np.arange(1,26,1)
a = a.reshape((5,5))
b = pd.DataFrame(a,columns=['i1','i2','i3','i4','i5'])
#!!!写入文件
b.to_csv('./Data/tmp_1.csv')
# 使用index和 header选项,把它们的值设置为False,可取消默认写入index和header
b.to_csv('./Data/tmp_2.csv',index =False,header=False)
# 可以用to_csv()函数的na_rep选项把空字段替换为你需要的值。常用值有NULL、0和NaN
b.to_csv('./Data/tmp_3.csv',na_rep="空")
#!!!读取文件
csvframe = pd.read_csv('./Data/tmp_1.csv')
print(csvframe, "\n-----*-----")
csvframe = pd.read_table('./Data/tmp_1.csv',sep=',')
print(csvframe, "\n-----*-----")
# 设置header为None,表示文件没有表头,第一行为数据,添加默认表头
csvframe = pd.read_csv('./Data/tmp_2.csv',header=None)
print(csvframe, "\n-----*-----")
# 指定表头。我们假设文件中有m列数据,设定的names有n个列名。
# 如果m>n,默认从最后一列(右侧)开始匹配,多余的右侧第一列作为index,其余数据舍弃
# 如果m==n,正常匹配
# 如果m<n,默认从第一列(左侧)开始匹配,多余的列名全部赋值Nan
csvframe = pd.read_csv('./Data/tmp_2.csv',names=['d1','d2','d3','d4','d5','d6'])
print(csvframe, "\n-----*-----")
#等级索引,可以指定以某一列为索引,支持多列索引。
csvframe = pd.read_csv('./Data/tmp_3.csv',index_col=['i1','i2'])
print(csvframe, "\n-----*-----")
excel文件读写
使用xlrd读取excel读取数据
import xlrd
# 设置路径
path = './Data/1.xlsx'
# 打开execl
workbook = xlrd.open_workbook(path)
# 输出Excel文件中所有sheet的名字
print(workbook.sheet_names())
# 根据sheet索引或者名称获取sheet内容
Data_sheet = workbook.sheets()[0] # 通过索引获取
# Data_sheet = workbook.sheet_by_index(0) # 通过索引获取
# Data_sheet = workbook.sheet_by_name(u'名称') # 通过名称获取
print(Data_sheet.name) # 获取sheet名称
rowNum = Data_sheet.nrows # sheet行数
colNum = Data_sheet.ncols # sheet列数
# 获取所有单元格的内容
for i in range(rowNum):
for j in range(colNum):
print('{0} '.format(Data_sheet.cell_value(i, j)))
# 获取整行和整列的值(列表)
rows = Data_sheet.row_values(0) # 获取第一行内容
cols = Data_sheet.col_values(1) # 获取第二列内容
print (rows)
print (cols)
# 获取单元格内容
cell_A1 = Data_sheet.cell(0, 0).value
cell_B1 = Data_sheet.row(0)[1].value # 使用行索引
cell_A2 = Data_sheet.col(0)[1].value # 使用列索引
print(cell_A1, cell_B1, cell_A2)
# 获取单元格内容的数据类型
# ctype:0 empty,1 string, 2 number, 3 date, 4 boolean, 5 error
print('cell(0,0)数据类型:', Data_sheet.cell(0, 0).ctype)
# 获取单元格内容为日期的数据
date_value = xlrd.xldate_as_tuple(Data_sheet.cell_value(1,0),workbook.datemode)
print(type(date_value), date_value)
print('%d:%d:%d' % (date_value[0:3]))
使用xlwt编写excel文件
import xlwt
path = './Data/2.xlsx'
# 创建工作簿
workbook = xlwt.Workbook(encoding='utf-8')
#创建文字格式
style = xlwt.XFStyle() # 初始化样式
font = xlwt.Font() # 为样式创建字体
font.name = 'Times New Roman'
font.bold = True
font.color_index = 4
font.height = 220
style.font = font
borders = xlwt.Borders()
borders.left = 6
borders.right = 6
borders.top = 6
borders.bottom = 6
style.borders = borders
#!!!如果对一个单元格重复操作,会引发error。所以在打开时加cell_overwrite_ok=True解决
sheet1 = workbook.add_sheet(u'sheet1',cell_overwrite_ok=True)
#表头内容
header = [u'甲',u'乙',u'丙',u'丁',u'午',u'己',u'庚',u'辛',u'壬',u'癸']
# 写入表头
for i in range(0, len(header)):
sheet1.write(0, i, header[i], style)
sheet1.write(1,0,u'合计',style)
#1,2,3,4表示合并区域是从第2行到第3行,从第4列到第5列,0表示要写入的单元格内容,style表示单元格样式
sheet1.write_merge(1,2,3,4,0,style)
# 保存文件
workbook.save(path)
xml文件读写
xml的样例文件是
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<maxid>4</maxid>
<login username="pytest" passwd='123456'>
<caption>Python</caption>
<item id="4">
<caption>测试</caption>
</item>
</login>
<item id="2">
<caption>Zope</caption>
</item>
</catalog>
读取xml文件
import xml.dom.minidom
#打开xml文档
dom = xml.dom.minidom.parse('./Data/tmp_5.xml')
#得到文档元素对象
root = dom.documentElement
print(root.nodeName)
#节点值,这个属性只对文本结点有效
print(root.nodeValue)
print(root.nodeType)
print(root.ELEMENT_NODE)
#通过子节点的nodeName查询结点,由于存在同名子节点,所以返回list类型
item_list = root.getElementsByTagName('item')
item1 = item_list[0]
item2 = item_list[1]
#通过结点的属性名获取属性值
id1 = item1.getAttribute('id')
id2 = item2.getAttribute('id')
print(item1.nodeName,id1)
print(item2.nodeName,id2)
item_list = root.getElementsByTagName('caption')
item1 = item_list[0]
item2 = item_list[1]
#获取结点的数据
print(item1.firstChild.data)
print(item2.firstChild.data)
写入xml文件
import xml.dom.minidom
impl = xml.dom.minidom.getDOMImplementation()
dom = impl.createDocument(None, 'employees', None)
root = dom.documentElement
employee = dom.createElement('employee')
employee.setAttribute('id' ,'1')
root.appendChild(employee)
#创建element结点,结点名为name
nameE=dom.createElement('name')
#创建文本结点,文本结点只有数据,没有<></>包裹
nameT=dom.createTextNode('linux')
#文本结点作为element结点的第一个子节点
nameE.appendChild(nameT)
employee.appendChild(nameE)
ageE=dom.createElement('age')
ageT=dom.createTextNode('30')
ageE.appendChild(ageT)
employee.appendChild(ageE)
f= open('./Data/tmp_6.xml', 'w', encoding='utf-8')
dom.writexml(f, addindent=' ', newl='\n',encoding='utf-8')
f.close()
输出文件结果
<?xml version="1.0" encoding="utf-8"?>
<employees>
<employee id="1">
<name>linux</name>
<age>30</age>
</employee>
</employees>
数据库数据读取与存储
python3目前不支持MySQL,所以我们只能在python2下面执行测试程序。这里推荐一个教程,有助于掌握MySQL与Python的配合应用——mysql 数据库
使用命令行mysql -u root -p
,输入密码进入sql环境。在这个环境中可以直接执行SQL语句。当然也有一些特殊命令,例如show databases
可以查看已有的数据库。
在Python方面需要使用mysql-python。这里介绍数据库的常用操作所对应的Python函数。
- 增
import MySQLdb
#host是ip地址,本地可以使用localhost代替
conn = MySQLdb.connect(host='localhost',user='root',passwd=password,db='OUC',port=3306,charset='utf8')
cur = conn.cursor()
cur.execute("insert into users(username,password,email) values (%s,%s,%s)",("python","123123","python@gmail.com"))
#将一句指令多次执行
cur.executemany("insert into users (username,password,email) values (%s,%s,%s)",\
(("google","111222","g@gmail.com"),\
("facebook","222333","f@face.book"),\
("github","333444","git@hub.com"),\
("docker","444555","doc@ker.com")))
conn.commit()
cur.close()
conn.close()
- 删
import MySQLdb
import MySQLdb
conn = MySQLdb.connect(host='localhost',user='root',passwd=password,db='OUC',port=3306,charset='utf8')
cur = conn.cursor()
cur.execute("delete from users where id=2")
conn.commit()
cur.execute("select * from users")
print cur.fetchall()
cur.close()
conn.close()
- 改
import MySQLdb
conn = MySQLdb.connect(host='localhost',user='root',passwd=password,db='OUC',port=3306,charset='utf8')
cur = conn.cursor()
#注意("mypython",)中的逗号是必须的,缺失会报错
cur.execute("update users set username=%s where id=2",("mypython",))
conn.commit()
cur.execute("select * from users where id=2")
print cur.fetchone()
cur.close()
conn.close()
- 查
import MySQLdb
'''数据查询'''
conn = MySQLdb.connect(host='localhost',user='root',passwd=password,db='OUC',port=3306,charset='utf8')
cur = conn.cursor()
cur.execute("select * from users")
#获取所有数据
lines = cur.fetchall()
for line in lines:
print line
#由于光标移动重新查询
cur.execute("select * from users")
#获取一条记录
print cur.fetchone()
#光标向下移动一条记录,默认是“relative”
cur.scroll(1)
print cur.fetchone()
cur.scroll(-2,'relative')
print cur.fetchone()
#移动到第一条记录
cur.scroll(0,'absolute')
print cur.fetchone()
#从当前位置获取指定数目的记录
lines = cur.fetchmany(1)
for line in lines:
print line
cur.close()
#通过指定cursorclass可以使查询返回的具有字典结构
cur_dict = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
cur_dict.execute("select * from users")
lines = cur_dict.fetchall()
for line in lines:
print line
cur_dict.close()
conn.close()