一文搞定Numpy&Pandas
簡單來說,Numpy就是用來進行矩陣計算的,而Pandas則基於Numpy,豐富並簡化了Numpy的操作
Numpy
基礎操作
import numpy as np array = np.array([[1, 2, 3], [2, 3, 4]], dtype=np.int) #dtype即元素資料型別 a = np.zeros((3, 4))# 3行4列的零矩陣 vec = np.arange(10, 20)# 從10到20的向量 mat_range = np.arange(12).reshape((3, 4))# 從10到20的3行4列的矩陣 vec_line = np.linspace(1, 10, 3)# 從1到10分為3個元素的向量,使得相鄰元素差值一致 print(array.ndim)# 維度 print(array.shape)# (2, 3) print(array.size)# 元素個數 print(array.dtype) b = a.copy() # 深拷貝
基礎運算
a = np.array([10, 20, 30, 40]).reshape((2, 2)) b = np.arange(4).reshape((2, 2)) print(a.T) # 矩陣轉置 c = 10 * np.sin(a)# 對a每個元素求sin再乘10 print(b < 3)# 所有元素比較 [ TrueTrueTrue False] c = a*b# 對應元素相乘 c = np.dot(a, b)# 矩陣乘法 rand = np.random.random((2, 4))# 隨機矩陣 print(np.sum(a, axis=0))# 行相加,axis理解為shape的索引 np.min(rand) np.max(rand)
基礎運算(二)
a = np.arange(2, 14).reshape((3, 4)) b = np.random.random((3, 4)) print(a) print(np.argmax(a))# 返回最大值索引 print(np.argmin(a)) print(np.average(a))# 平均值 print(np.cumsum(a))# 字首和 print(np.diff(a))# 一階差分 print(np.nonzero(a)) print(np.clip(a, 5, 9))# 將元素限制在[5,9]
索引和迭代
a = np.arange(3, 15).reshape((3, 4)) print(a[2, 1])# 第二行第一列元素 print(a[:, 1])# 第一列元素 for row in a: print(row) for col in a.T: print(col) for item in a.flat:# 遍歷每個元素 print(item)
合併和分割
a = np.array([1, 1, 1]) b = np.array([2, 2, 2]) print(a[:, np.newaxis])# 把1維的行向量變成2維列向量 print(np.vstack((a, b)))# 上下合併 print(np.hstack((a, b)))# 左右合併 a = np.arange(12).reshape((3, 4)) print(np.split(a, 2, axis=1))# 縱向等分為2部分 print(np.array_split(a, 3, axis=1))# 縱向不等分為3部分
Pandas
如果說numpy相當於一個list,那麼Pandas就相當於一個dict
簡單來說,當資料的維度比較大的時候,單純地通過numpy中的數字索引來訪問元素顯得有些意義不明,我們希望給某一行,某一列甚至某個單元的元素一個名稱,簡化操作的同時豐富每一行的程式碼的語義和可讀性,這就是Pandas
基本操作
在學習基本操作之前,我們必須明確的一點是:
一般來說,使用矩陣組織資料的是以行為單元的,什麼意思呢?就是多組結構一致的資料往往表現在矩陣裡是多行。因此從列的角度看每一列是多組資料的同一型別資料。這也是為什麼在Pandas裡行方向的labels稱作index,因為它跟一般意義的索引沒有本質區別,都是表示資料的序號
Pandas中最常用的兩種資料型別是:Series和DataFrame
import pandas as pd import numpy as np s = pd.Series([1, 3, 6, 7, 44, np.nan, 3.4], index=[7]*7)# 相當於一維的ndarray加上標籤 data = pd.DataFrame(np.arange(12).reshape( (3, 4)), index=np.arange(3), columns=['a', 'b', 'c', 'd']) # 相當於矩陣加上行標籤和列標籤,index表示行標籤,columns表示列標籤 print(data.index)# 行labels print(data.columns)# 列labels print(data.values) print(data.describe())# 按列輸出統計資料 data = data.sort_index(axis=0, ascending=False)# 對行labels排序,從大到小 data = data.sort_values(by='a', axis=0)# 指定列labels按行排序
資料選擇及更改
dates = pd.date_range('20190329', periods=6) df = pd.DataFrame(np.arange(24).reshape((6, 4)), index=dates, columns=['a', 'b', 'c', 'd']) print(df['a'], df.a, sep='\n')# 輸出標籤為'a‘的列 print(df[0:3], df['20190329':'20190331'], sep='\n')# 輸出前三行資料 print(df.loc['20190329']) print(df.loc[:, ['a', 'b']])# loc基於標籤名 print(df.iloc[3:5, 1:3])# iloc基於行列的絕對數字(index) print(df[df.a > 8])# 篩選出a大於8的行 # 更改資料 df.iloc[2, 2] = 111 df.loc['20190329', 'b'] = 333 df.a[df.a > 4] = 0# 把大於4的a列賦值為0 df['f'] = np.nan# 動態新增新列
處理丟失資料
dates = pd.date_range('20190329', periods=6) df = pd.DataFrame(np.arange(24).reshape((6, 4)), index=dates, columns=['a', 'b', 'c', 'd']) df.iloc[0, 1] = np.nan df.iloc[1, 2] = np.nan print(df.fillna(value=0))# 填充nan為0 print(df.dropna(axis=0, how='any'))# 丟失存在nan的行 print(df.isnull())# nan的位置為True,其餘為False print(np.any(df.isnull()) == True)# 判斷整個矩陣是否存在nan
簡單IO
data = pd.read_csv('data.csv', sep=',') pd.to_pickle(data, 'data.pickle') data = pd.read_pickle('data.pickle')
合併
import pandas as pd import numpy as np # concat df1 = pd.DataFrame(np.ones((3, 4))*0, columns=['a', 'b', 'c', 'd']) df2 = pd.DataFrame(np.ones((3, 4))*1, columns=['a', 'b', 'c', 'd']) df3 = pd.DataFrame(np.ones((3, 4))*2, columns=['a', 'b', 'c', 'd']) print(df1, df2, df3, sep='\n\n') res = pd.concat([df1, df2, df3], axis=0, ignore_index=True, join='inner')# 按行合併(即縱向),index重新計算 # inner模式刪去非公共的列標籤對應的列,outer則會保留,同時用nan填充 res = res.append(pd.Series([0, 1, 2, 3], index=[ 'a', 'b', 'c', 'd']), ignore_index=True)# 新增一個Series # 基於key的合併請參考merge函式,和sql中的內外連線非常相似,此處不贅述各引數的用法,需要時查詢文件即可 pd.merge()