第一章 資料分析和Numpy基礎
1.1資料分析
1.1.1資料
談到資料我們首先要明白什麼是資料,資料是我們通過觀察、實驗或計算得出的結果。使我們對現象的一種描述,用于表示客觀事物的未經加工的原始素材。此處所談的資料是指結構化的資料,而不是散亂、毫無章法的資料。在進行資料處理的時候我們還需要關心資料的類型,常見的資料類型包括以下幾種:
- 表格型資料,每一列通常包含不同的類型資料。
- 多元數組。
- 均勻或者非均勻數組。
- 由鍵位相關聯的多張資料表格。
在實際應用中,資料通常會進行一種轉換,轉換成一種更适合分析、模組化的模式,也可以提取資料中的特征進行分析。
1.1.2資料存儲類型
通路資料時一切的開始,即資料的輸出輸入是使用其他工具的第一步。資料的輸入輸出通常由一下幾種類型,讀取文本檔案及硬碟上其他更高效格式的檔案、和資料庫交換資料、與網絡資源進行互動。
.csv
、
.xlsx
、
.txt
這三種格式的檔案是文本資料常用的存儲類型,之後我們會更進一步的讨論這三種格式的檔案的讀取、處理、和存儲。
1.2Numpy基礎
1.2.1Numpy簡介
NumPy 是一個 Python 包。 即 “Numeric Python”。 它是一個由多元數組對象和用于處理數組的例程集合組成的庫。Numeric,即NumPy 的前身,是由Jim Hugunin開發的。他也開發了另一個包Numarray,它擁有一些額外的功能。 2005年,Travis Oliphant通過将 Numarray 的功能內建到 Numeric 包中來建立 NumPy 包。
NumPy 通常與SciPy(Scientific Python)和Matplotlib(繪圖庫)一起使用。 這種組合廣泛用于替代 MatLab,是一個流行的技術計算平台。 但是,Python 作為 MatLab 的替代方案,現在被視為一種更加現代和完整的程式設計語言。在資料分析領域我們主要關心的内容為:
- 常見的高速、組合算法,例如sort、mean、sum等。
- 高效的描述性統計和聚合。
- 對資料進行清理、構造子集、過濾、變換以及快速向量化計算。
盡管Numpy提供了一定的資料操作基礎,但還是應該将其視為pandas的基礎,而不是一個獨立的資料分析庫,核心原因是它無法對常見的時間序列類型進行有效的操作。
Numpy的重要性還展現在一下幾個方面:
- Numpy在内部将資料存儲在連續的記憶體塊上,這跟Python内建的資料結構是不同的。
- Numpy的算法庫使用C語言寫的,是以在操作資料記憶體時,不必進行資料類型檢查等操作,其數組使用的記憶體量也小于其他内建序列。
- Numpy可以不寫循環就進行全數組複雜計算。
1.2.2ndarray的建立
N維數組對象-ndarray是Numpy核心特征之一,是一個快速、靈活的同類大型資料集容器,該數組允許你使用類似标量的操作在整個資料上進行資料操作。
ndarray 内部由以下内容組成:
- 一個指向資料(記憶體或記憶體映射檔案中的一塊資料)的指針。
- 資料類型或 dtype,描述在數組中的固定大小值的格子。
- 一個表示數組形狀(shape)的元組,表示各次元大小的元組。
- 一個跨度元組(stride),其中的整數指的是為了前進到目前次元下一個元素需要"跨過"的位元組數。
方法1:
array()
方法,array方法的介紹如下:
numpy.array(object, dtype = None, copy = True, order = None, subok = >False, ndmin = 0)
參數1:object:指定數組或嵌套的數列
參數2:dtype:指定數組元素的資料類型,可選
參數3:copy:指定對象是否需要複制,可選
參數4:order:指定建立數組的樣式,C為行方向,F為列方向,A為任意方向(預設)
參數5:subok:指定預設傳回一個與基類類型一緻的數組
參數6:ndmin:指定生成數組的最小次元
正确示例1:傳遞一個非嵌套清單對象,生成一個一維數組。
#初始化資料,傳遞一個非嵌套清單對象,生成一個一維數組。
data = range(10)
arr = np.array(data)
--------------------------------------------------------------------------
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
正确示例2:傳遞一個嵌套清單對象,生成一個多元數組。
#初始化資料,傳遞一個嵌套清單對象,生成一個多元數組。
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(data)
--------------------------------------------------------------------------
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
正确示例3:傳遞一個非嵌套清單對象,同時指定最小次元,同樣也可以生成一個多元數組。
#初始化非嵌套數資料,指定ndmin參數,成一個多元數組。
data = range(10)
arr = np.array(data, ndmin=2)
--------------------------------------------------------------------------
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
正确示例4:傳遞一個非嵌套清單對象,生成一個一維數組。同時傳遞
dtype=complex
,指定元素類型為複數。
#初始化資料,傳遞dtype參數,指定元素類型
data = range(10)
arr = np.array(data, dtype=complex)
--------------------------------------------------------------------------
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 5.+0.j, 6.+0.j, 7.+0.j,
8.+0.j, 9.+0.j])
正确示例5:傳遞一個嵌套清單對象,生成一個多元數組。同時傳遞dtype參數
[('a',np.int32),('b', complex)]
,指定a副本元素類型為整數型,b副本元素類型為複數型。
#初始化資料,傳遞一個非套清單對象,傳遞dtype參數,指定a副本元素類型為整數型,b副本元素類型為複數型。
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(data, dtype=([('a',np.int32),('b', complex)]))
--------------------------------------------------------------------------
array([[(1, 1.+0.j), (2, 2.+0.j), (3, 3.+0.j)],
[(4, 4.+0.j), (5, 5.+0.j), (6, 6.+0.j)],
[(7, 7.+0.j), (8, 8.+0.j), (9, 9.+0.j)]],
dtype=[('a', '<i4'), ('b', '<c16')])
使用
arr[名稱]
通路不同的副本。
arr['a']
--------------------------------------------------------------------------
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr['b']
--------------------------------------------------------------------------
array([[1.+0.j, 2.+0.j, 3.+0.j],
[4.+0.j, 5.+0.j, 6.+0.j],
[7.+0.j, 8.+0.j, 9.+0.j]])
錯誤示例1:傳遞一個不規則嵌套清單對象。會給出warning,并且建立結果不是多元數組而是一維數組,且是數組元素類型是清單。
#錯誤示例,傳遞不規則嵌套清單
data = [[1, 2, 3], [4, 5, 6, 12], [7, 8, 9, 10, 11]]
arr = np.array(data)
--------------------------------------------------------------------------
VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
array([list([1, 2, 3]), list([4, 5, 6, 12]), list([7, 8, 9, 10, 11])],
dtype=object)
方法2:
np.zeros()
方法,zeros()方法介紹如下。
numpy.zeros(shape, dtype=None, order=‘C’)
作用:生成指定形狀的0矩陣
參數1:shape:元組型,指定矩陣形狀
參數2:dtype:指定數組所需的資料類型,例如’ numpy.int8 '。預設是“numpy.float64”
參數3:order:指定以何種模式存儲多元資料,‘C’:行模式 ‘F’:列模式
正确示例1:傳遞一個整數,生成一維數組,即
zero = np.zeros(m)
或者
zero = np.zeros((m,))
#傳遞一個整數,生成一維數組1,np.zeros(m)
zero = np.zeros(5)
--------------------------------------------------------------------------
array([0., 0., 0., 0., 0.])
#傳遞一個整數,生成一維數組2,zero = np.zeros((m,))
zero = np.zeros((5,))
--------------------------------------------------------------------------
array([0., 0., 0., 0., 0.])
正确示例2:傳遞一個元祖,生成多元數組,即
zero = np.zeros((m, n))
#傳遞一個整數,生成多元數組
zero = np.zeros((5,5))
--------------------------------------------------------------------------
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
方法3:
np.empty()
方法,empty方法介紹如下。
作用:傳回給定形狀和類型的新數組,而無需初始化條目。
empty(shape, dtype=None, order=‘C’)
參數1:dtype:元組型或整型,指定空數組形狀
參數2:dtype:指定資料類型
參數3:order:指定行優先還是列優先
傳回值1:ndarray對象
正确示例1:empty方法和zeros方法使用的方式是一緻的,在此不再贅述,隻是給出示例。
#empty方法,傳遞一個元組
np.empty([2, 2])
--------------------------------------------------------------------------
array([[ -9.74499359e+001, 6.69583040e-309],
[ 2.13182611e-314, 3.06959433e-309]])
ps1:empty方法的初始化值是随機的,不是0,是以比zeros方法速度快,但是要更加注意值的問題。
ps2:使用array方法時傳遞嵌套清單時,預設情況下每一個子清單作為一行,可以傳遞order參數進行修改。
1.2.3ndarray的轉換
内建類型的資料不光可以轉換稱為ndarray,也可以進行逆轉換。
方法1:
arr.tolist()
轉換為清單。
#資料轉換,轉換為清單
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(data)
list = arr.tolist()
--------------------------------------------------------------------------
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
方法2:
arr.tobytes()
轉換為位元組對象。
#資料轉換,轉換為位元組對象
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(data)
bytes = arr.tobytes()
--------------------------------------------------------------------------
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00'
ps1:轉換方法都是傳回一個新的對象,而不是在原視圖上進行操作。
1.2.4ndarray的切片和索引
不管是索引還是切片其核心目标都是找出符合要求的資料子集,簡單來說就是用正确的方式表示出其子集。
1.2.4.1按行索引
方法1:
arr[行号,:]
。
正确示例:傳遞行号,索引一行。
#初始化資料,按行索引方法1,傳遞行号,索引單行
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr[0, :]
--------------------------------------------------------------------------
array([1, 2, 3])
方法2:
arr[行号][:]
。
正确示例:傳遞行号,索引一行。
#初始化資料,按行索引方法2,傳遞行号,索引單行
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr[0][:]
--------------------------------------------------------------------------
array([1, 2, 3])
ps1:arr[行,列]方法不能直覺的展示次元資訊,arr[行号][:]更能直覺的展示有幾個次元。
1.2.4.2按列索引
方法1:
arr[:, 列号]
。
正确示例:傳遞列号,索引一列。
#初始化資料,按列索引方法1,傳遞列号,索引單列
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr[:, 0]
--------------------------------------------------------------------------
array([1, 4, 7])
錯誤示例:使用
arr[:][列号]
索引一列,該語句不會索引出第一列,而是這個數組的第一個元素。因為這個語句可以了解為先
arr_new=arr[:]
複制一個新的數組,再
arr_new[0]
調用其第一個元素,故不能使用該方法索引列。
#錯誤示例,索引的是第一個元素
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr[:][0]
--------------------------------------------------------------------------
array([1, 2, 3])
ps1:說行列其實并不準确,更應該稱呼axis=0,axis=1,或者次元1、次元2。
1.2.4.3單值索引
方法1:
arr[行,列]
或者
arr[行][列]
。
正确示例:傳遞兩個整數,索引單值。
#按單值索引方法1-1
arr[0, 0]
--------------------------------------------------------------------------
1
#按單值索引方法1-1
arr[0][0]
--------------------------------------------------------------------------
1
1.2.4.4多行/列索引
方法1:
arr[行1:行2,列1:列2]
。
正确示例1:傳遞行1、行2、列1、列2索引多行/列。
#傳遞行列各兩個參數,索引多行、列
arr[0:2, 0:1]
--------------------------------------------------------------------------
array([[1],
[4]])
正确示例2:傳遞行1、列1、列2索引多行/列。
#傳遞行1、列1、列2索引多行/列
arr[0:, 0:1]
--------------------------------------------------------------------------
array([[1],
[4],
[7]])
正确示例3:傳遞行2、列1索引多行/列。
#傳遞行2、列1索引多行/列
arr[:2, 1:]
--------------------------------------------------------------------------
array([[2, 3],
[5, 6]])
錯誤示例1:使用
arr[行1:行2][列1:列2]
,上面這句話相當于先
arr_new=arr[行1:行2, :]
再
result=arr_new[新行1:新行2, :]
,最後的結果result相當于做了兩次多行索引。
arr[0:2][1:]
--------------------------------------------------------------------------
array([[4, 5, 6]])
ps1:多行索引時,不是非得傳遞4個參數,不傳遞:後面的參數a:表示從a開始到結尾,不傳遞:前面的參數:a表示從開頭到a-1截止,:則表示整體從開始到結束
1.2.4.5條件索引
方法1:
arr[condition]
。
正确示例:傳遞一個能周遊所有元素的函數作為條件對數組進行篩選。
#使用條件數組進行篩選
arr[arr < arr.mean()] = 0
--------------------------------------------------------------------------
array([[0, 0, 0],
[0, 5, 6],
[7, 8, 9]])
1.2.4.6布爾索引
布爾索引也可以了解為是條件索引一種,隻是一個使用條件,一個使用同形狀的布爾數組作為篩子,篩選出所有位置為True的值,示例如下:
#初始化布爾數組
bool_arr = np.random.randn(9).reshape((3, 3))
bool_arr = bool_arr>0
--------------------------------------------------------------------------
array([[False, True, True],
[False, False, False],
[ True, True, False]])
#使用布爾數組進行篩選
arr[bool_arr] = 0
--------------------------------------------------------------------------
array([[1, 0, 0],
[4, 5, 6],
[0, 0, 9]])
1.2.4.7神奇索引
在Numpy中神奇索引指的是使用整數數組進行資料索引的方式。
方法1:
arr[[行1,行2, 行3...][列1, 列2, 列3]]
元素兩兩對應索引資料,表示列的子清單可以不傳,如果隻有一個字清單将被認為是行清單。
正确示例:傳遞兩行兩列索引2個值。
arr[[2, 0], [2, 1]]
--------------------------------------------------------------------------
array([9, 2])
1.2.5ndarray的指派
除了建立的時候進行指派,所有的索引都可以成為指派的一種方式,即
arr[索引]=Values
。在此不再贅述索引過程,單純給出除布爾索引以外的索引指派相關示例。
#初始化資料
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(data)
--------------------------------------------------------------------------
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
正确示例1:按行指派。
#按行指派
arr[0] = [10, 10, 10]
--------------------------------------------------------------------------
array([[10, 10, 10],
[ 4, 5, 6],
[ 7, 8, 9]])
正确示例2:按列指派。
#按列指派
arr[:, 0] = [10, 10, 10]
--------------------------------------------------------------------------
array([[10, 2, 3],
[10, 5, 6],
[10, 8, 9]])
正确示例3:單值指派。
#單值指派
arr[0, 0] = 10
--------------------------------------------------------------------------
array([[10, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
正确示例4:多行、列指派。
arr[0:2, :] = [[10, 10, 10], [10, 10, 10]]
--------------------------------------------------------------------------
array([[10, 10, 10],
[10, 10, 10],
[ 7, 8, 9]])
正确示例4對比示例:指派的時候要注意形狀問題,長度相等并不能直接指派。
arr[0:2, :] = np.arange(6)
--------------------------------------------------------------------------
ValueError: could not broadcast input array from shape (6) into shape (2,3)
正确示例5:條件指派。
arr[arr < arr.mean()] = 10
--------------------------------------------------------------------------
array([[10, 10, 10],
[10, 5, 6],
[ 7, 8, 9]])
正确示例6:神奇索引指派。
arr[[2, 0], [2, 1]] = [10, 10]
--------------------------------------------------------------------------
array([[ 1, 10, 3],
[ 4, 5, 6],
[ 7, 8, 10]])