美文网首页
python数据载入、存储及文件格式

python数据载入、存储及文件格式

作者: 弦好想断 | 来源:发表于2020-04-21 15:56 被阅读0次

    将表格型数据读取为DataFrame对象是pandas的重要特征,read_csv和read_table可能是后期我们使用最多的函数。


    从一个小型的逗号分隔文本文件(CSV)开始:

    !type ex1.csv
    a,b,c,d,message
    1,2,3,4,hello
    5,6,7,8,world
    9,10,11,12,foo
    with open('ex1.csv') as f:
        lines = [x.rstrip() for x in f]#删除 string 字符串末尾的指定字符(默认为空格)
    lines
    ['a,b,c,d,message', '1,2,3,4,hello', '5,6,7,8,world', '9,10,11,12,foo']
    df = pd.read_csv('ex1.csv')#读取逗号分隔文件
    df
        a   b   c   d   message
    0   1   2   3   4   hello
    1   5   6   7   8   world
    2   9   10  11  12  foo
    

    header = None参数允许自动分配默认列名,也可以自己指定列名:

    pd.read_csv('ex2.csv',names = ['a','b','c','d','message'])
        a   b   c   d   message
    0   1   2   3   4   hello
    1   5   6   7   8   world
    2   9   10  11  12  foo
    

    假设你想要message列成为返回DataFrame的索引,你可以指定位置4的列为索引,或将‘message’传给参数index_col:

    names = ['a','b','c','d','message']
    pd.read_csv('ex2.csv',names = names,index_col = 'message')
            a   b   c   d
    message                 
    hello   1   2   3   4
    world   5   6   7   8
    foo     9   10  11  12
    

    如果你想从多个类中形成一个分层索引,需要传入一个包含序列号或列明名的列表:

    !type csv_mindex.csv
    key1,key2,value1,value2
    one,a,1,2
    one,b,3,4
    one,c,5,6
    one,d,7,8
    two,a,9,10
    two,b,11,12
    two,c,13,14
    two,d,15,16
    parsed = pd.read_csv('csv_mindex.csv',index_col = ['key1','key2'])
    parsed
            value1  value2
    key1 key2       
    one   a     1   2
          b     3   4
          c     5   6
          d     7   8
    two   a     9   10
          b     11  12
          c     13  14
          d     15  16
    

    在某些情况下,一张表的分隔符并不是固定的,使用空白或其他方式来分隔字段。考虑如下文本文件:

    list(open('ex3.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']
    

    当字段是以多种不同数量的空格分开时,可以向read_csv传递一个正则表达式作为分隔符。本例中,正则表达式为\s+,因此我们可得

    pd.read_csv('ex3.txt',sep = '\s+')#由于列名的数量比数据的列数少一列,因此read_csv推断第一列应当作为DataFrame的索引
                    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
    

    可以在read_csv中使用skiprows来跳过第一行、第三行和第四行,传入参数skiprows = [0,2,3]。


    在尝试大文件之前,我们可以先对pandas的显示设置进行调整,使之更为紧凑。

    pd.options.display.max_rows = 10#最大显示行数为10行
    

    如果你只想读取一小部分行,可以指明要读取的行数nrows:
    为了分块读入文件,可以指定chunksize作为每一块的行数,read_csv返回的TextParser对象允许你根据chunksize遍历文件。

    #例如,我们可以遍历ex6.csv,并对'key'列聚合获得计数值:
    tot = pd.Series([])
    for piece in chunker:
        tot = tot.add(piece['key'].value_counts(),fill_value = 0)
    tot = tot.sort_values(ascending = False)
    tot[:10]
    X    210.0
    E    207.0
    O    197.0
    L    196.0
    Q    193.0
    F    187.0
    H    182.0
    K    180.0
    V    178.0
    J    175.0
    dtype: float64
    

    TextParser对象还具有get_chunk方法,允许你按照任意大小读取数据块

    a = pd.read_csv('ex6.csv',chunksize=1000)
    a.get_chunk(size=4000)#省去文件中前400行,只显示4000行以后的内容,并按1000行分块显示
    for x in a:
        print(x)
    

    将数据写入文本格式

    使用DataFrame的to_csv方法,可以将数据导出为逗号分隔的文件。
    当然,其他的分隔符也是可以的,(写入到sys.stdout时,控制台中打印的中文结果)
    sys模块可以实现程序与python解释器交互,提供一系列变量或函数在python运行时的环境。sys.stdout指的是标准输出。
    缺失值在输出时以空字符串出现,也可以使用na_rep参数对缺失值进行标注

    import sys
    data.to_csv(sys.stdout,sep='|',na_rep = 'NULL')
    |something|a|b|c|d|message
    0|one|1|2|3.0|4|NULL
    1|two|5|6||8|world
    2|three|9|10|11.0|12|foo
    

    默认行和列的标签都会被写入,不过传入index = False,header = False二者也都可以禁止写入。

    json数据

    JSON已经成为Web浏览器和其他应用间通过HTTP请求发送数据的标准格式它是一种比CSV等表格文本形式更为自由的数据形式。
    json非常接近与有效的Python代码,处理它的空值null合一起其他细小差异(例如不允许列表末尾的逗号)之外。json对象中所有的键都必须是字符串,基本类型是字典,列表、字符串、数字、布尔值和空值。
    将JSON字符串转换为Python形式,使用Python的内置模块json的json.loads方法:

    import json
    result = json.loads(obj)
    result
    {'name': 'Wes',
     'place_lived': ['United States', 'Spain', 'Germany'],
     'pet': None,
     'siblings': [{'name': 'Scott', 'age': 30, 'pets': ['Zeus', 'Zuko']},
      {'name': 'Katie', 'age': 38, 'pets': ['Sixes', 'Stache', 'Cisco']}]}
    

    另一方面,json.dumps可以将Python对象转换为JSON

    asjson = json.dumps(result)
    asjson
    '{"name": "Wes", "place_lived": ["United States", "Spain", "Germany"], "pet": null, "siblings": [{"name": "Scott", "age": 30, "pets": ["Zeus", "Zuko"]}, {"name": "Katie", "age": 38, "pets": ["Sixes", "Stache", "Cisco"]}]}'
    

    将JSON对象或对象列表转换为DataFrame或其他数据结构。
    比较方便的方式是将字典构成的列表(之前是json对象)传入DataFrame构造函数,并选出数据字段的子集。

    siblings = pd.DataFrame(result['siblings'],columns = ['name','age'])
    siblings
        name    age
    0   Scott   30
    1   Katie   38
    

    pandas.read_json 的默认选项是假设JSON数组中的每个对象是表里的一行,将数据导出为json,一种办法是对Series或DataFrame使用to_json方法。

    XML和HTML:网络抓取

    pandas的内建函数read_html函数可以使用lxml和Beautiful Soul等库将HTML中的表自动解析为DataFrame对象。
    pandas.read_html函数有很多选项,默认情况下,它会搜索并尝试解析所有包含在<table>标签中的表格型数据,返回的结果是DataFrame对象的列表。
    XML是另一种常用的结构化数据格式,它使用元数据支持分层,嵌套数据。XML和XTML结构类似,但是XML更通用。
    使用lxml从更为通用的XML格式解析数据:

    #使用lxml.objectify,我们可以解析这个文件,并用getroot来获得对XML文件的根节点的引用
    from lxml import objectify
    path = 'mta_perf/Performance_MNR.xml
    parsed = objectify.parse(open(path))
    root = parsed.getroot()
    data = []
    skip_field = ['PARENT_SEQ','INDICATOR_SEQ','DESIRED_CHANGE','DECIMAL_PLACES']
    #root.INDICATOR返回一个用于产生各个XML元素的生成器。
    for elt in root.INDICATOR:
        el_data = {}
        for child in elt.getchildren():
            if child.tag in skip_field:
                continue
            el_data['child.tag'] = child.pyval
        data.append(el_data)
    #最后将包含字典的列表转换为DataFrame
    perf = pd.DataFrame(data)
    perf.head()
        child.tag
    0   96.9
    1   95
    2   96.9
    3   98.3
    4   95.8
    

    child.tag返回的是xml文件每行中的第一个值,child.pyval返回的是第二个(也就是中间的)值。
    XML 数据还可以更复杂,每个标签也可以包含元数据。考虑一个HTML连接标签,也是有效的XML:

    from io import StringIO
    tag = '<a href = "http://www.google.com">Google</a>'
    root = objectify.parse(StringIO(tag)).getroot()
    root
    <Element a at 0x2a8b112bd48>
    root.get('href')
    'http://www.google.com'
    root.text
    'Google'
    

    这里StringIO的概念:在内存中读写str,参考:https://blog.csdn.net/lucyxu107/article/details/82728266

    二进制格式

    使用Python内建的pickle序列化模块进行二进制操作是存储数据(也成为序列化)最高效、最方便的方式之一。pandas拥有一个to_pickle方法可以将数据以pickle格式写入硬盘

    frame = pd.read_csv('ex1.csv')
    frame
        a   b   c   d   message
    0   1   2   3   4   hello
    1   5   6   7   8   world
    2   9   10  11  12  foo
    rame.to_pickle('frame_pickle')
    #可以直接使用内建的pickle读取文件中pickle化的对象,或更方便地使用pandas.read_pickle做上述操作
    pd.read_pickle('frame_pickle')
        a   b   c   d   message
    0   1   2   3   4   hello
    1   5   6   7   8   world
    2   9   10  11  12  foo
    

    pickle仅被推荐作为短期的存储格式。问题在于pickle很难确保格式的长期有效性。

    HDF5格式

    HDF5是一个广受好评的文件格式,用于存储大量的科学数组数据。HDF5中的“HDF”代表分层数据格式。每个HDF5文件可以存储多个数据集并支持元数据。
    与更简单的格式相比,HDF5支持多种压缩模式的即时压缩,使得重复模式的数据可以更高效的存储。HDF5适用于处理不适合在内存中存储的超大型数据,可以使你高效的读写大型数组的一小块。
    尽管你可以通过PyTables和h5py等库直接访问HDF5文件,但pandas提供了一个高阶的接口,可以简化Series和DataFrame的存储。
    HDFStore类像字典一样工作并处理低级别细节:

    frame = pd.DataFrame({'a':np.random.randn(100)})
    store = pd.HDFStore('mydata.h5')
    store['obj1'] = frame
    store['obj1_col'] = frame['a']
    store
    <class 'pandas.io.pytables.HDFStore'>
    File path: mydata.h5
    #包含在HDF5文件中的对象可以使用相同的字典型API进行检索:
    store['obj1'].shape()
    (100,1)
    

    HDFStore支持两种存储模式,‘fixed’和‘table’。后者速度更慢,但支持一种特殊语法的查询操作

    store.put('obj2',frame,format = 'table')
    store.select('obj2',where = ['index>=10 and index <= 15'])
        a
    10  -0.518309
    11  0.198280
    12  0.488141
    13  -0.711851
    14  -0.709542
    15  0.754240
    store.close()
    

    put是store['obj2']=frame 方法的显示版本,但允许我们设置其他选项,如存储格式。

    #pandas.read_hdf函数是这些工具的快捷方法
    frame.to_hdf('my_data.h5','obj3',format = 'table')
    pd.read_hdf('my_data.h5','obj3',where =['index<5'] )
        a
    0   -1.260942
    1   1.297276
    2   -0.125102
    3   0.211125
    4   0.731398
    

    !!HDF5并不是数据库,它是一种适合一次写入多次读取的数据集。尽管数据可以在嗯和实践添加到文件中,但如果多个写入者持续写入,文件可能会损坏。

    读取Microdoft Excel文件

    pandas也支持通过ExcelFile类或pandas.read_excel函数来读取存储在Excel文件中的表格型数据。
    使用ExcelFile时,通过将xls或xlsx的路径传入,生成一个实例

    xlsx = pd.ExcelFile('ex1.xlsx')
    #存储在表中的数据可以通过pandas.read_excel读取到DataFrame中
    pd.read_excel(xlsx,'Sheet1')
       Unnamed: 0  a   b   c   d   message
    0   0   1   2   3   4   hello
    1   1   5   6   7   8   world
    2   2   9   10  11  12  foo
    #如果你读取的是含有多个表的文件,生成ExcelFile更快,但你也可以更简洁地将文件名传入pandas.read_excel:
    frame = pd.read_excel('ex1.xlsx','Sheet1')
    frame
       Unnamed: 0  a   b   c   d   message
    0   0   1   2   3   4   hello
    1   1   5   6   7   8   world
    2   2   9   10  11  12  foo
    #如需将pandas数据写入到Excel格式中,你必须生成一个ExcelWriter,然后使用pandas对象的to_excel方法将数据写入  
    writer = pd.ExcelWriter('ex2.xlsx')
    frame.to_excel(writer,'Sheet1')
    writer.save()
    #你也可以直接将文件路径传入to_excel,避免直接调用ExcelWriter:
    frame.to_excel('ex2.xlsx')
    

    与Web API交互

    有多种方式可以利用Python来访问API,我推荐简单易用的方式是使用requests包

    要获取GitHub上最新的30条关于pandas的问题,我们使用附加库requests发送一个HTTP GET请求

    import numpy as np
    import pandas as pd
    from pandas import Series,DataFrame
    import requests
    url = 'https://api.github.com/repos/pandas-dev/pandas/issues'
    resp = requests.get(url)
    resp
    输出#<Response [200]>
    #Response(响应)对象的json方法将返回一个包含解析为本地Python对象的json字典
    data = resp.json()
    data[0]['title']
    "`The default of the 'keep_tz' keyword in DatetimeIndex.to_series will change to True in a future release.`"
    #data中的每个元素都是一个包含DitHub问题页面上的所有数据的字典(除注释外)
    #我们可以直接将data传给DataFrame,并提取感兴趣的字段
    issues = pd.DataFrame(data,columns=['number','title','labels','state'])
    issues.head()
        number  title                                             labels    state
    0   28083   `The default of the 'keep_tz' keyword in Datet...   []  open
    1   28082   Change `randn` to `np.random.randn` in v0.10.0...   [{'id': 134699, 'node_id': 'MDU6TGFiZWwxMzQ2OT...   open
    2   28081   REF: separate bloated test  []  open
    3   28080   BUG: Series[int] + datetime64 should raise  []  open
    4   28079   API: flex comparisons DataFrame vs Series inco...   [{'id': 35818298, 'node_id': 'MDU6TGFiZWwzNTgx...   open
    5   28078   Auto backport of pr 28074 on 0.25.x     []  open
    

    与数据库交互

    ...

    相关文章

      网友评论

          本文标题:python数据载入、存储及文件格式

          本文链接:https://www.haomeiwen.com/subject/orcuihtx.html