Python数据分析(四):数据的获取与处理
2019-12-03 本文已影响0人
风之舟
在python的学习过程中,我们会经常遇到各种格式的数据加载、处理与存储。今天我们来总结一下常见格式数据的读取与处理。
一、各种各样的文本数据
1.1 CSV与TXT读取
1、csv
csv 文件格式的本质是一种以文本存储的表格数据(使用 Excel 工具即可读写 csv 文件)。csv 文件的每行代表一行数据,每行数据中每个单元格内的数据以逗号隔开。首先我们先来看一下数据长什么样子,这里使用的是jupyter notebook编辑器。
!cat '/opt/jupyter_file/dataset/数据获取与分析/data1.csv'
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
接下来我们看一下数据的读取:
df=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data1.csv')
df
或者下面一种:
#需要知道分隔符
pd.read_table('/opt/jupyter_file/dataset/数据获取与分析/data1.csv',sep=',')
我们也可以设置一下参数:
#read_csv读取时会自动识别表头,
#数据有表头时不能设置header为空(默认读取第一行,即header=0);
#数据无表头时,若不设置header,第一行数据会被视为表头,应传入names参数设置表头名称或设置header=None。
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data1.csv',header=None)
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data1.csv',names=['a','b','c','d','e'])
还可以设置一下索引列:
names=['a','b','c','d','e']
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data1.csv',names=names,index_col='e')#制定索引列
相对复杂的索引列:
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/csv_mindex.csv',index_col=['key1','key2'])
!cat '/opt/jupyter_file/dataset/数据获取与分析/data4.csv'
# hey!
a,b,c,d,message
# just wanted to make things more difficult for you
# who reads CSV files with computers, anyway?
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data4.csv',skiprows=[0,2,3])#跳过索引为0,2,3的行
result=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data5.csv')
result
pd.isnull(result)
result=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data5.csv',na_values=['null'])
result
sentinels={'message':['foo','NA'],'something':['two']}
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data5.csv',na_values=sentinels)#设置为0
这里我总结一下read_csv()常用到的参数
类型 | 说明 |
---|---|
sep | 指定分隔符。如果不指定参数,则会尝试使用逗号分隔。 |
delimiter | 定界符,备选分隔符(如果指定该参数,则sep参数失效) |
delim_whitespace | 指定空格(例如’ ‘或者’ ‘)是否作为分隔符使用,等效于设定sep='\s+'。如果这个参数设定为Ture那么delimiter 参数失效。 |
header | 指定行数用来作为列名,数据开始行数 |
names | 用于结果的列名列表,如果数据文件中没有列标题行,就需要执行header=None。 |
index_col | 用作行索引的列编号或者列名,如果给定一个序列则有多个行索引。 |
dtype | 每列数据的数据类型。 |
skiprows | 需要忽略的行数(从文件开始处算起),或需要跳过的行号列表(从0开始)。 |
skipfooter | 从文件尾部开始忽略。 (c引擎不支持) |
nrows | 需要读取的行数(从文件头开始算起)。 |
na_values | 一组用于替换NA/NaN的值。如果传参,需要制定特定列的空值。默认为‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘nan’`. |
na_filter | 是否检查丢失值(空字符串或者是空值)。对于大文件来说数据集中没有空值,设定na_filter=False可以提升读取速度。 |
skip_blank_lines | 如果为True,则跳过空行;否则记为NaN。 |
encoding | 指定字符集类型,通常指定为'utf-8'. |
2、txt
第一种:适合文本类型的读取,编排没有格式要求
f=open('/opt/jupyter_file/dataset/数据获取与分析/data3.txt')
f.read()
第二种:有一定的格式,这时可以通过指定分隔符来解决
list(open('/opt/jupyter_file/dataset/数据获取与分析/data3.txt'))#提前看一下内容
[' A B C\n',
'aaa -0.264438 -1.026059 -0.619500\n',
'bbb 0.927272 0.302904 -0.032399\n',
'ccc -0.264273 -0.386314 -0.217601\n',
'ddd -0.871858 -0.348382 1.100491\n']
#或者另一种方式
!cat '/opt/jupyter_file/dataset/数据获取与分析/data3.txt'
A B C
aaa -0.264438 -1.026059 -0.619500
bbb 0.927272 0.302904 -0.032399
ccc -0.264273 -0.386314 -0.217601
ddd -0.871858 -0.348382 1.100491
pd.read_table('/opt/jupyter_file/dataset/数据获取与分析/data3.txt',sep='\s+')#分隔符,正则表达式(规则),至少有一个空格
1.2 分片/块读取文本数据
result=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data6.csv')
result
pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data6.csv',nrows=5)#读取前5行
chunker=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data6.csv',chunksize=100)#分块读取,表明每100行为1个chunk。
#返回的reader是TextFileReader类型,它指向若干个chunk位置,只在访问数据的时候才真正把数据读入到内存。
#这是一个可迭代的类型,采用for in的形式,即可逐个访问chunk。
#每个chunk都是dataframe类型的。
chunker
tot=Series([])
for piece in chunker:
#取并集,value求和
#fill_value参数使a中value的NaN=fill_value,然后与b中相同索引的value相加
tot=tot.add(piece['key'].value_counts(),fill_value=0)#取序列中value的交集,并统计每个value出现的次数。value作为index,次数作为序列值。
tot=tot.sort_values(ascending=False)
tot[:10]
1.3、把数据写入文本格式
data=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data5.csv')
data
data.to_csv('/opt/jupyter_file/dataset/数据获取与分析/out.csv')
!cat '/opt/jupyter_file/dataset/数据获取与分析/out.csv'
#输出结果
,something,a,b,c,d,message
0,one,1,2,3.0,4,
1,two,5,6,,8,world
2,three,9,10,11.0,12,foo
data.to_csv(sys.stdout,sep='|')
#输出结果
|something|a|b|c|d|message
0|one|1|2|3.0|4|
1|two|5|6||8|world
2|three|9|10|11.0|12|foo
result=data.to_csv(sys.stdout,na_rep='null')
result
#输出结果
,something,a,b,c,d,message
0,one,1,2,3.0,4,null
1,two,5,6,null,8,world
2,three,9,10,11.0,12,foo
data.to_csv(sys.stdout,index=False,header=False)#不要index和header
#输出结果
one,1,2,3.0,4,
two,5,6,,8,world
three,9,10,11.0,12,foo
data.to_csv(sys.stdout,index=False,columns=['a','b','c'])
#输出结果
a,b,c
1,2,3.0
5,6,
9,10,11.0
dates=pd.date_range('1/1/2000',periods=7)#长度为7
ts=Series(np.arange(7),index=dates)
ts.to_csv('/opt/jupyter_file/dataset/数据获取与分析/tseries.csv')
!cat tseries.csv
#输出结果
2000-01-01,0
2000-01-02,1
2000-01-03,2
2000-01-04,3
2000-01-05,4
2000-01-06,5
2000-01-07,6
1.4 手动读写数据(按要求)
!cat '/opt/jupyter_file/dataset/数据获取与分析/data7.csv'
#输出结果
"a","b","c"
"1","2","3"
"1","2","3","4"
import csv
f=open('/opt/jupyter_file/dataset/数据获取与分析/data7.csv')
reader=csv.reader(f)
for line in reader:
print(line)
#输出结果
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3', '4']
lines=list(csv.reader(open('/opt/jupyter_file/dataset/数据获取与分析/data7.csv')))
lines[0]
#输出结果
['a', 'b', 'c']
header,values=lines[0],lines[1:]
#参数为可迭代的对象,并且可以有多个参数。该函数返回一个以元组为元素的列表,其中第 i 个元组包含每个参数序列的第 i 个元素。返回的列表长度被截断为最短的参数序列的长度。只有一个序列参数时,它返回一个1元组的列表。没有参数时,它返回一个空的列表。
data_dict={h: v for h,v in zip(header,zip(*values))}
data_dict
#输出结果
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}
a=[1,2,3,4]
b=[1,2,3]
c=[1,2,3,4,5]
zz=zip(a,b,c)
for line in zz:
print(line)
#输出结果
(1, 1, 1)
(2, 2, 2)
(3, 3, 3)
#csv的文件的形式有很多,只需定义csv.dialect的一个子类即可定义出新格式(如专门的分隔符、字符串引用约定、行结束符等)
#第一行是继承(my_dialect继承自csv.Dialect)后面四行是赋值
class my_dialect(csv.Dialect):
lineterminator='\n'
delimiter='|'
quotechar='"'
quoting=csv.QUOTE_MINIMAL
with open('/opt/jupyter_file/dataset/数据获取与分析/mydata.csv','w') as f:
writer=csv.writer(f,dialect=my_dialect)
writer.writerow(('one','two','three'))
writer.writerow(('1','2','3'))
writer.writerow(('4','5','6'))
writer.writerow(('7','8','9'))
!cat '/opt/jupyter_file/dataset/数据获取与分析/mydata.csv'
#输出结果
one|two|three
1|2|3
4|5|6
7|8|9
1.5JSON格式的数据
obj=\
"""
{"姓名":"张三",
"住处":["天朝","挖煤国","万恶的资本主义日不落帝国"],
"宠物":null,
"兄弟":[{"姓名":"李四","年龄":"25","宠物":"汪星人"},
{"姓名":"王五","年龄":"23","宠物":"喵星人"}]
}
"""
import json
result=json.loads(obj)
result
#输出结果
{'姓名': '张三',
'住处': ['天朝', '挖煤国', '万恶的资本主义日不落帝国'],
'宠物': None,
'兄弟': [{'姓名': '李四', '年龄': '25', '宠物': '汪星人'},
{'姓名': '王五', '年龄': '23', '宠物': '喵星人'}]}
result["兄弟"][0]
#输出结果
{'姓名': '李四', '年龄': '25', '宠物': '汪星人'}
result["兄弟"][1]
#输出结果
{'姓名': '王五', '年龄': '23', '宠物': '喵星人'}
brothers=DataFrame(result["兄弟"],columns=['姓名','年龄'])
brothers
#输出结果
image.png
1.6 解析HTML
from lxml.html import parse#专门用于处理html的模块
import urllib.request#打开和浏览url中内容
parsed=parse(urllib.request.urlopen('https://ask.julyedu.com/explore/'))#解析url
doc=parsed.getroot()#获取根元素
doc
#输出结果
<Element html at 0x7fd43865c590>
links=doc.findall('.//a')#正则表达式
links[15:20]
#输出结果
[<Element a at 0x7fd4386a7fb0>,
<Element a at 0x7fd4386a7e90>,
<Element a at 0x7fd4386a7dd0>,
<Element a at 0x7fd4386a7d10>,
<Element a at 0x7fd4386a7cb0>]
lnk=links[19]
lnk
lnk.get('href')
print(lnk.text_content())#文本内容
#输出结果
全部问题
urls=[lnk.get('href') for lnk in doc.findall('.//a')]
urls[-10:]
#输出结果
['https://www.cnzz.com/stat/website.php?web_id=1259748782',
'https://www.julyedu.com',
'https://www.julyedu.com/help/index/about',
'https://www.julyedu.com/help/index/join',
'http://weibo.com/askjulyedu',
'javascript:',
'https://tianchi.aliyun.com',
'https://cloud.tencent.com/developer/edu',
'https://www.aidaxue.com/?ch=qyzx',
'https://www.epubit.com']
spans=doc.findall('.//span')
len(spans)
#输出结果
132
def _unpack(spans):
return [val.text_content() for val in spans]
contents=_unpack(spans)
for content in contents:
print(content)
questions=doc.findall('.//h4')#问题标签
len(questions)
#输出结果
50
contents=_unpack(questions)
for content in contents:
print(content)
1.7 解析XML
XML是一种结构化、层级化的数据格式,最适合体现XML的数据结构就是树
!cat '/opt/jupyter_file/dataset/数据获取与分析/Performance_MNR.xml'
from lxml import objectify#lxml.objectify主要用于处理以数据为中心的文档,可以根据叶子节点所含的内容自动推断数据类型。
path='/opt/jupyter_file/dataset/数据获取与分析/Performance_MNR.xml'
parsed=objectify.parse(open(path))
root=parsed.getroot()
data=[]
skip_fields=['PARENT_SEQ','INDICATOR_SEQ','DESIRED_CHANGE','DECIMAL_PLACES']
for elt in root.INDICATOR:#返回一个用于产生各个XML元素的生成器
el_data={}
for child in elt.getchildren():
if child.tag in skip_fields:
continue
el_data[child.tag]=child.pyval#pyval获取内容也可以用text
data.append(el_data)
perf=DataFrame(data)
perf
二、其他格式的数据
1、二进制格式的数据
#存储速度快、文件小
#pandas库pd.read_pickle操作读取pickle数据与.to_pickle()永久储存数据
frame=pd.read_csv('/opt/jupyter_file/dataset/数据获取与分析/data1.csv')
frame
frame.to_pickle('/opt/jupyter_file/dataset/数据获取与分析/frame_pickle')
pd.read_pickle('/opt/jupyter_file/dataset/数据获取与分析/frame_pickle')
2、使用HDF5格式
一个HDF5文件是一种存放两类对象的容器:dataset和group. Dataset是类似于数组的数据集,而group是类似文件夹一样的容器,存放dataset和其他group。在使用h5py的时候需要牢记一句话:groups类比词典,dataset类比Numpy中的数组。
store=pd.HDFStore('/opt/jupyter_file/dataset/数据获取与分析/mydata.h5')
store['obj1']=frame
store['obj1_col']=frame['a']
store
#输出结果
<class 'pandas.io.pytables.HDFStore'>
File path: /opt/jupyter_file/dataset/数据获取与分析/mydata.h5
store['obj1']
3、HTML与API交互
import requests
url='https://api.github.com/repos/pydata/pandas/milestones/28/labels'
resp=requests.get(url)
resp
#输出结果
<Response [200]>
data[:5]
issue_labels=DataFrame(data)
issue_labels
三、数据库相关操作
3.1 sqlite数据库
import sqlite3
query="""
CREATE TABLE test(a varchar(20),
b varchar(20),
c real,
d integer);
"""
con=sqlite3.connect(':memory:')#连接服务
con.execute(query)#确认执行
con.commit()#提交
data=[('zhangsan','China',1.25,6),
('lisi','America',2.6,3),
('wangwu','Japan',1.7,5)]
stmt="INSERT INTO test values(?,?,?,?)"
con.executemany(stmt,data)#执行多条记录
con.commit()
cursor=con.execute('select * from test')
rows=cursor.fetchall()#游标,fetchall查询所有
rows
#输出结果
[('zhangsan', 'China', 1.25, 6),
('lisi', 'America', 2.6, 3),
('wangwu', 'Japan', 1.7, 5)]
cursor.description
#输出结果
(('a', None, None, None, None, None, None),
('b', None, None, None, None, None, None),
('c', None, None, None, None, None, None),
('d', None, None, None, None, None, None))
DataFrame(rows,columns=list(zip(*cursor.description))[0])#为了方便看
import pandas.io.sql as sql
sql.read_sql('select * from test',con)
3.2 MYSQL数据库
#coding=utf-8
import pymysql
conn=pymysql.connect(host='localhost',
port=3306,
user='root',
passwd='123456',
db='test')
cur=conn.cursor()
#创建数据表
# cur.execute("create table student(id int,name varchar(20),class varchar(20),age varchar(10))")
#插入一条数据
# cur.execute("insert into student values('2','Tom','3 year 2 class ',13)")
#修改查询条件的数据
# cur.execute("update student set class='3 year 1 class' where name='Tom'")
#查询所有数据
cur.execute("select * from test.student")
#删除查询条件的数据
# cur.execute("delete from student where age='9'")
cur.close()
conn.commit()
conn.close()
不小心执行了三遍插入操作
关于python对数据的获取与处理就讲到这里,下一篇我们讲解一下数据的可视化!