Python數據分析基礎ReadingDay5_sqlite3

reading Foundations for Analysis with Python Day 5

《Python數據分析基礎》封面

這篇筆記開始記錄數據庫的內容,會用兩篇筆記分別講述Python內置的sqlite3和MySQL。 我們已經有了txt、csv以及Excel等文件格式,上面2篇筆記也分別實踐了csv和Excel的讀寫和處理操作,還是挺方便的,那么為什么要用數據庫存數據呢?我的理解是相對于文件系統,數據庫整體結構化、共享性高、冗余度小,并且基于DBMS(數據庫管理系統)有很好的數據安全性、完整性、并發控制和恢復能力。

還有一個說法我覺得挺好:

Excel很容易遇到瓶頸,隨著業務的發展,分析師接觸的數據會越來越多。對大部分人的電腦,超過十萬條數據,已經會影響性能。何況大數據時代就是不缺數據,這時候就需要學習數據庫了。--來自秦路的數據分析系列文章

那么什么是數據庫呢?

所謂數據庫是長期存儲在計算機內、有組織可共享的數據集合。--《數據庫系統概論》(第三版).薩師煊.高等教育出版社

本篇筆記先簡單講了什么是數據庫,然后用Python3提供的sqlite3庫建立內置的數據庫,通過比較具體的應用場景講對數據庫的增加、修改和查詢數據。數據庫部分會有兩篇筆記,下一篇會講MySQL的連接和處理。相對來說,這部分的內容可能有一定的門檻,需要一定的先驗知識,比較注重實踐。完整地閱讀《Python數據分析基礎》的第4章會有更大的收獲。

目錄

  • 結構化查詢語言SQL
  • sqlite3創建數據庫
  • 批量增加數據
  • 更新表中記錄

結構化查詢語言SQL

SQL(Structured Query Language) 是用于訪問和處理數據庫的標準的計算機語言,最常用的操作是增刪改查。SQL和編程語言不同,它不區分大小寫,一般的書為了區別都是使用大寫作為SQL的關鍵字,這篇筆記也是這樣。要進一步實踐SQL的語句可以參考w3school的教程,或者干脆去仔細閱讀《SQL必知必會》。

sqlite3創建數據庫

sqlite3是Python3內置的庫,它可以使我們創建內存數據庫。這就是說我們可以使用 Python 代碼直接創建一個數據庫和其中充滿數據的表,而不用下載安裝專門的數據庫軟件。這篇筆記先是用這種方式實踐數據庫操作,下一篇會講用Python操作MySQL,到時候需要額外安裝MySQL。

#sqlite3創建、增加、查詢數據。下面幾段代碼基本也用到了這部分的框架
import sqlite3

con = sqlite3.connect(':memory:') # 創建SQLite3內存數據庫
query = """CREATE TABLE sales
                (customer VARCHAR(20), 
                 product VARCHAR(40),
                 amount FLOAT,
                 date DATE);"""
con.execute(query) #執行query 句子的內容
con.commit()

# 在表中插入幾行數據 
data = [('Richard Lucas', 'Notepad', 3.30, '2014-01-02'),
        ('Jenny Kim', 'Binder', 3.15, '2014-03-15'),
        ('Svetlana Crow', 'Printer', 251.15, '2014-02-03'),
        ('Stephen Randolph', 'Computer', 629.60, '2014-02-20')]
statement = "INSERT INTO sales VALUES(?, ?, ?, ?)"
con.executemany(statement, data)
con.commit()

# 查詢sales表中的所有內容
cursor = con.execute("SELECT * FROM sales")
rows = cursor.fetchall()

row_counter = 0
for row in rows: # 計算查詢結果中行的數量 
    print(row)
    row_counter += 1
print('Number of rows:',row_counter) #輸出

輸出:

('Richard Lucas', 'Notepad', 3.3, '2014-01-02')
('Jenny Kim', 'Binder', 3.15, '2014-03-15')
('Svetlana Crow', 'Printer', 251.15, '2014-02-03')
('Stephen Randolph', 'Computer', 629.6, '2014-02-20')
Number of rows: 4

上面的代碼先是導入了sqlite3庫,并且是在內存中創建的數據庫,如果需要把該數據庫持久化,則將第二句的':memory:'改為'文件夾路徑/新數據庫名稱.db'。query是一個SQL命令,其作用是創建一個名為 sales 的表,并且有4個字段(字段類似于Excel的列,記錄類似于Excel的行),之后使用連接對象的 execute()方法執行包含在變量 query 中的 SQL 命令,創建一個表叫 sales 。 commit() 保存上面的修改。之后分別是用SQL進行增加數據和查詢。
execute() 方法運行一條 SQL 命令,并將命令結果賦給一個光標對象 cursor。光標對象有若干方法,例如,execute、executemany、fetchone、fetchmany 和 fetchall。fetchall() 方法能取出(或者說返回)結果集中的所有行。
如果熟悉SQL語言上面的代碼比較容易理解。如果對SQL完全不了解建議看一些其他教程進行學習。即使不是專門做數據分析的崗位,有越來越多的產品和運營被要求使用SQL。而且從Excel到SQL是技能樹的提升,因此建議看到這篇筆記的同學能抽些時間去了解SQL。

批量增加數據

通過手動改data列表來個性化數據庫中的數據挺繁瑣的,如果我們有保存了大量數據的csv或Excel文件怎么辦呢?解決辦法就是用前面學過的csv讀取方法讀取csv到列表里,再增加到數據庫里。Excel文件可以轉為csv再用前面的方法,或者直接讀取Excel中的數據到dataframe里,再寫入數據庫。

下面代碼的功能是向表中插入 CSV 文件中的數據,然后展示表中的數據。

def csvDataToDB(input_file):
    import csv
    import sqlite3

    con = sqlite3.connect('Suppliers.db') #建庫
    c = con.cursor()
    create_table = """CREATE TABLE IF NOT EXISTS Suppliers
                    (Supplier_Name VARCHAR(20), 
                    Invoice_Number VARCHAR(20),
                    Part_Number VARCHAR(20),
                    Cost FLOAT,
                    Purchase_Date DATE);"""
    c.execute(create_table)  #執行create_table中的SQL語句
    con.commit()

    # 向Suppliers表中插入csv文件中的數據
    file_reader = csv.reader(open(input_file, 'r'), delimiter=',')
    header = next(file_reader, None)
    for row in file_reader:
        data = []
        for column_index in range(len(header)):
            data.append(row[column_index])
            
        c.execute("INSERT INTO Suppliers VALUES (?, ?, ?, ?, ?);", data)
    con.commit()

    # 通過查詢輸出Suppliers表
    output = c.execute("SELECT * FROM Suppliers")
    rows = output.fetchall()
    for row in rows[:5]:
        output = []
        for column_index in range(len(row)):
            output.append(str(row[column_index]))
        print(output)

in_f='supplier_data.csv'
csvDataToDB(in_f)  #調用

輸出:

['Supplier X', '001-1001', '2341', '$500.00', '1/20/14']
['Supplier X', '001-1001', '2341', '$500.00', '1/20/14']
['Supplier X', '001-1001', '5467', '$750.00', '1/20/14']
['Supplier X', '001-1001', '5467', '$750.00', '1/20/14']
['Supplier Y', '50-9501', '7009', '$250.00', '1/30/14']

上面代碼的思路就是創建了一個數據庫叫Suppliers.db,然后用SQL語句添加了5個字段,之后用我們熟悉的csv庫讀取數據到列表data里,使用循環和glob的話,可以將該讀取功能擴展到任意數目的文件,在循環中寫入數據庫,最后通過查詢語句查看表中的內容,書中提示在加入的行太多時,不建議再輸出來看,我覺得輸出前面5行(5條記錄)是比較好的展示,這個改一下代碼的循環條件就好。

更新表中記錄

上面說完了增加數據形成新的記錄,SQL的操作增/刪/改/查中,也是很重要的內容,有時候,我們不需要向數據表中加載新數據,而是需要更新表中已有的行,因此用到了UPDATE 語句。

def updateDBrow(input_file):
    #輸入參數:需要讀取的csv文件路徑
    import csv
    import sqlite3

    con = sqlite3.connect(':memory:')
    query = """CREATE TABLE IF NOT EXISTS sales
                (customer VARCHAR(20), 
                    product VARCHAR(40),
                    amount FLOAT,
                    date DATE);"""
    con.execute(query)
    con.commit()

    # 向表中插入幾行數據 
    data = [('Richard Lucas', 'Notepad', 2.50, '2014-01-02'),
            ('Jenny Kim', 'Binder', 4.15, '2014-01-15'),
            ('Svetlana Crow', 'Printer', 155.75, '2014-02-03'),
            ('Stephen Randolph', 'Computer', 679.40, '2014-02-20')]
    for tuple in data:
        print(tuple)
    statement = "INSERT INTO sales VALUES(?, ?, ?, ?)"
    con.executemany(statement, data)
    con.commit()

    # 讀取CSV文件并更新特定的行 
    file_reader = csv.reader(open(input_file, 'r'), delimiter=',')
    header = next(file_reader, None)
    for row in file_reader:
        data = []
        for column_index in [3,4,1]:
            data.append(float(row[column_index][1:])) if column_index==3 else data.append(row[column_index])
            
        #print(data)
        con.execute("UPDATE sales SET amount=?, date=? WHERE customer=?;", data)
    con.commit()

    # 查詢sales表并顯示出來
    cursor = con.execute("SELECT * FROM sales")
    rows = cursor.fetchall()
    for row in rows[:3]:
        output = []
        for column_index in range(len(row)):
            output.append(str(row[column_index]))
        print(output)

in_f='supplier_data.csv'
updateDBrow(in_f)

輸出:

('Richard Lucas', 'Notepad', 2.5, '2014-01-02')
('Jenny Kim', 'Binder', 4.15, '2014-01-15')
('Svetlana Crow', 'Printer', 155.75, '2014-02-03')
('Stephen Randolph', 'Computer', 679.4, '2014-02-20')
['Richard Lucas', 'Notepad', '2.5', '2014-01-02']
['Jenny Kim', 'Binder', '4.15', '2014-01-15']
['Svetlana Crow', 'Printer', '155.75', '2014-02-03']

刪除特定的記錄

上面用代碼分別說明了創建數據庫、增加數據、修改數據、查詢和顯示數據,書中就這樣開始講到MySQL了,沒有講到刪除特定的數據,刪除某一記錄用到DELETE語句,下面給出一個簡單的示例:

#刪除符合條件的記錄
def deleteDataRow():
    import csv
    import sqlite3

    con = sqlite3.connect(':memory:') #同樣創建一個數據庫
    query = """CREATE TABLE IF NOT EXISTS sales
                (customer VARCHAR(20), 
                    product VARCHAR(40),
                    amount FLOAT,
                    date DATE);"""
    con.execute(query)
    con.commit()

    # 向表中插入幾行數據 
    data = [('Richard Lucas', 'Notepad', 4.50, '2014-01-02'),
            ('Jenny Kim', 'Binder', 2.15, '2014-01-15'),
            ('Svetlana Crow', 'Printer', 151.75, '2014-02-03'),
            ('Stephen Randolph', 'Computer', 679.40, '2014-02-20')]
    
    statement = "INSERT INTO sales VALUES(?, ?, ?, ?)"
    con.executemany(statement, data)
    con.commit()

    # 查詢sales表并顯示出來
    cursor = con.execute("SELECT * FROM sales")
    rows = cursor.fetchall()
    for row in rows:
        output = []
        for column_index in range(len(row)):
            output.append(str(row[column_index]))
        print(output)
    
    #c_del = con.cursor()
    con.execute("DELETE FROM sales WHERE product<10;")

    # 查詢sales表并顯示出來
    print('====after DELETE:====')
    cursor = con.execute("SELECT * FROM sales")
    rows = cursor.fetchall()
    for row in rows:
        output = []
        for column_index in range(len(row)):
            output.append(str(row[column_index]))
        print(output)
deleteDataRow()

輸出:

['Richard Lucas', 'Notepad', '4.5', '2014-01-02']
['Jenny Kim', 'Binder', '2.15', '2014-01-15']
['Svetlana Crow', 'Printer', '151.75', '2014-02-03']
['Stephen Randolph', 'Computer', '679.4', '2014-02-20']
====after DELETE:====
['Richard Lucas', 'Notepad', '4.5', '2014-01-02']
['Jenny Kim', 'Binder', '2.15', '2014-01-15']
['Svetlana Crow', 'Printer', '151.75', '2014-02-03']
['Stephen Randolph', 'Computer', '679.4', '2014-02-20']

從上面的系列代碼可以看到,sqlite3實現數據庫常用操作的代碼還是很簡潔的,下一篇筆記會講MySQL的內容。對文件操作不太熟悉文件操作可以參考之前關于csv讀取以及Excel文件讀取的筆記。
本篇筆記的GitHub同步項目于readingForDS。(pandas是很有用的工具,需要多練習來掌握)。關于本系列筆記有任何建議歡迎留言討論。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容