1. 程式人生 > >Python資料讀寫

Python資料讀寫

資料處理過程中常用到的資料檔案格式有txt,csv,excel,xml,資料庫。本文的應用物件是資料處理,所以我們關注的是結構化資料。至於基礎的文字讀寫不在本文的討論範圍。對於不同型別的資料,我們用到的工具也不同。

  1. txt,csv通常儲存關係型資料,也就是是可以用二維陣列表示。對於這一類資料,我們一般使用pandas讀寫。所以這裡介紹pandas內建的函式處理方法。
  2. excel也可以儲存關係型資料,但對比csv可以設計更復雜的結構。我們使用xlrd讀取,xlwt寫入。
  3. xml可以儲存多層級的資料,例如描述一個物件時需要多層次,多維度的資料。Python支援兩種機制——SAX和minidom。SAM是基於事件響應機制的,也就是順序讀取xml檔案,發現一個節點就會呼叫相關函式。而minidom是根據xml整個檔案建立一個樹形結構,然後提供遍歷搜尋的方法。我們這裡介紹minidom方法。
  4. 資料庫是管理資料的專業工具,特別適用於多人共享資料的場合。本文介紹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 資料庫