首頁 > 軟體

python數學建模之Numpy 應用介紹與Pandas學習

2022-07-03 18:01:18

Numpy學習

1 Numpy 介紹與應用

1-1Numpy是什麼

NumPy 是一個執行速度非常快的數學庫,一個開源的的python科學計算庫,主要用於陣列、矩陣計算,包含:

一個強大的N維陣列物件 ndarray廣播功能函數整合 C/C++/Fortran 程式碼的工具線性代數、傅立葉變換、亂數生成等功能 1-2 為什麼選擇Numpy

對於同樣的數值計算任務,使用Numpy比直接編寫原生python程式碼的優點有:

程式碼更簡潔:

Numpy直接以陣列、矩陣為粒度計算並且支撐大量的數學函數,而Python需要用for迴圈從底層實現

 效能更高效:

Numpy的陣列儲存效率和輸入輸出計算效能,比Python使用List或者巢狀List好很多

注意:Numpy的資料儲存和Python原生的List是不一樣的
加上Numpy的大部分程式碼都是C語言實現的,這是Numpy比純Python程式碼高效的原因

相關學習、程式碼如下:須提前安裝好Numpy、pandas和matplotlib

Numpy終端安裝命令:pip install numpy
Pandas終端安裝命令:pip install pandas
Matplotlib終端安裝過命令:pip install matplotlib

# @Software : PyCharm
# Numpy是Python各種資料科學類庫的基礎庫
# 比如:Pandas,Scipy,Scikit_Learn等
# Numpy應用:
'''
NumPy 通常與 SciPy(Scientific Python)和 Matplotlib(繪相簿)一起使用, 這種組合廣泛用於替代 MatLab,是一個強大的科學計算環境,有助於我們通過 Python 學習資料科學或者機器學習。
SciPy 是一個開源的 Python 演演算法庫和數學工具包。
SciPy 包含的模組有最佳化、線性代數、積分、插值、特殊函數、快速傅立葉變換、訊號處理和影象處理、常微分方程求解和其他科學與工程中常用的計算。
Matplotlib 是 Python 程式語言及其數值數學擴充套件包 NumPy 的視覺化操作介面。它為利用通用的圖形化使用者介面工具包,如 Tkinter, wxPython, Qt 或 GTK+ 嚮應用程式嵌入式繪圖提供了應用程式介面(API)。

'''
# 安裝 NumPy 最簡單的方法就是使用 pip 工具:
# pip3 install --user numpy scipy matplotlib
# --user 選項可以設定只安裝在當前的使用者下,而不是寫入到系統目錄。
# 預設情況使用國外線路,國外太慢,我們使用清華的映象就可以:
# pip install numpy scipy matplotlib -i.csv https://pypi.tuna.tsinghua.edu.cn/simple
# 這種pip安裝是一種最簡單、最輕量級的方法,當然,這裡的前提是有Python包管理器
# 如若不行,可以安裝Anaconda【目前應用較廣泛】,這是一個開源的Python發行版
# 安裝Anaconda地址:https://www.anaconda.com/
# 安裝驗證
# 測試是否安裝成功
from numpy import *     # 匯入 numpy 庫
print(eye(4))           # 生成對角矩陣
# 檢視版本:
import numpy as np
print(np.__version__)
# 實現2個陣列的加法:
# 1-原生Python實現
def Py_sum(n):
    a = [i**2 for i in range(n)]
    b = [i**3 for i in range(n)]
    # 建立一個空列表,便於後續儲存
    ab_sum = []
    for i in range(n):
        # 將a、b中對應的元素相加
        ab_sum.append(a[i]+b[i])
    return ab_sum
# 呼叫實現函數
print(Py_sum(10))
# 2-Numpy實現:
def np_sum(n):
    c = np.arange(n) ** 2
    d = np.arange(n) ** 3
    return c+d
print(np_sum(10))
# 易看出使用Numpy程式碼簡潔且執行效率快
# 測試1000,10W,以及100W的執行時間
# 做繪圖對比:
import pandas as pd
# 輸入資料
py_times = [1.72*1000, 202*1000, 1.92*1000]
np_times = [18.8, 14.9*1000, 17.8*10000]

# 建立Pandas的DataFrame型別資料
ch_lxw = pd.DataFrame({
    'py_times': py_times,
    'np_times': np_times    # 可加逗號
})
print(ch_lxw)
import matplotlib.pyplot as plt
# 線性圖
print(ch_lxw.plot())
# 柱狀圖
print(ch_lxw.plot.bar())
# 簡易箱線圖
print(ch_lxw.boxplot)

plt.show()

線性圖執行效果如下:

柱狀圖執行效果如下:

2 NumPy Ndarray 物件

NumPy 最重要的一個特點是其 N 維陣列物件 ndarray,它是一系列同型別資料的集合,以 0 下標為開始進行集合中元素的索引。

ndarray 物件是用於存放同型別元素的多維陣列,其中的每個元素在記憶體中都有相同儲存大小的區域。ndarray 物件採用了陣列的索引機制,將陣列中的每個元素對映到記憶體塊上,並且按照一定的佈局對記憶體塊進行排序(行或列)

ndarray 內部由以下內容組成:

  • 一個指向資料(記憶體或記憶體對映檔案中的一塊資料)的指標;
  • 資料型別或 dtype,描述在陣列中的固定大小值的格子;
  • 一個表示陣列形狀(shape)的元組,表示各維度大小的元組;
  • 一個跨度元組(stride),其中的整數指的是為了前進到當前維度下一個元素需要"跨過"的位元組數。

相關學習、程式碼如下:

'''
建立一個 ndarray 只需呼叫 NumPy 的 array 函數即可:
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
引數說明:

名稱	描述
object	表示陣列或巢狀的數列
dtype	表示陣列元素的資料型別,可選
copy	表示物件是否需要複製,可選
order	建立陣列的樣式,C為行方向,F為列方向,A為任意方向(預設)
subok	預設返回一個與基礎類別型別一致的陣列
ndmin	指定生成陣列的最小維度
'''
# ndarray 物件由計算機記憶體的連續一維部分組成,並結合索引模式,將每個元素對映到記憶體塊中的一個位置。
# 記憶體塊以行順序(C樣式)或列順序(FORTRAN或MatLab風格,即前述的F樣式)來儲存元素

# 學好Numpy,便於後期對Pandas的資料處理
# 1:一維
import numpy as np
lxw = np.array([5, 2, 0])
print(lxw)
print()
# 2: 多於一個維度
import numpy as np
lxw2 = np.array([[1, 5, 9], [5, 2, 0]])
print(lxw2)
print()
# 3: 最小維度
import numpy as np
lxw3 = np.array([5, 2, 0, 1, 3, 1, 4], ndmin=2)     # ndmin: 指定生成陣列的最小維度
print(lxw3)
print()
# 4: dtype引數
import numpy as np
lxw4 = np.array([3, 3, 4, 4], dtype=complex)        # dtype: 陣列元素的資料型別[complex 複數】
print(lxw4)

3 Numpy 資料型別

numpy 支援的資料型別比 Python 內建的型別要多很多,基本上可以和 C 語言的資料型別對應上,其中部分型別對應為 Python 內建的型別.

常用 NumPy 基本型別:

名稱  描述
bool_ :【布林型資料型別(True 或者 False)】
int_ : 【預設的整數型別(類似於 C 語言中的 long,int32 或 int64)】
intc :【與 C 的 int 型別一樣,一般是 int32 或 int 64】
intp :【用於索引的整數型別(類似於 C 的 ssize_t,一般情況下仍然是 int32 或 int64)】
int8 :【位元組(-128 to 127)】
int16 :【整數(-32768 to 32767)】
int32 :【整數(-2147483648 to 2147483647)】
int64 :【整數(-9223372036854775808 to 9223372036854775807)】
uint8 :【無符號整數(0 to 255)】
uint16 :【無符號整數(0 to 65535)】
uint32 :【無符號整數(0 to 4294967295)】
uint64 :【無符號整數(0 to 18446744073709551615)】
float_ float64 :【型別的簡寫】
float16 :【半精度浮點數,包括:1 個符號位,5 個指數位,10 個尾數位】
float32 :【單精度浮點數,包括:1 個符號位,8 個指數位,23 個尾數位】
float64 :【雙精度浮點數,包括:1 個符號位,11 個指數位,52 個尾數位】
complex_ complex128: 【型別的簡寫,即 128 位複數】
complex64 :【複數,表示雙 32 位浮點數(實數部分和虛數部分)】
complex128 :【複數,表示雙 64 位浮點數(實數部分和虛數部分)】

相關學習、程式碼如下:

'''
# numpy 的數值型別實際上是 dtype 物件的範例,並對應唯一的字元,包括 np.bool_,np.int32,np.float32,等等。
'''
# Numpy 型別物件:
'''
dtype 物件是使用以下語法構造的:

numpy.dtype(object, align, copy)

object - 要轉換為的資料型別物件
align - 如果為 true,填充欄位使其類似 C 的結構體。
copy - 複製 dtype 物件 ,如果為 false,則是對內建資料型別物件的參照

'''
# 1: 使用標量型別
import numpy as np
lxw = np.dtype(np.int32)
print(lxw)
print()
# 2: int8, int16, int32, int64 四種資料型別可以使用字串 'i1', 'i2','i4','i8' 代替
import numpy as np
lxw2 = np.dtype('i8')       # int64
print(lxw2)
print()
# 3: 位元組順序標註
import numpy as np
lxw3 = np.dtype('<i4')      # int32
print(lxw3)
print()
# 4: 首先建立結構化資料型別
import numpy as np
lxw4 = np.dtype([('age', np.int8)])     # i1
print(lxw4)
print()
# 5: 將資料型別應用於 ndarray 物件
import numpy as np
lxw5 = np.dtype([('age', np.int32)])
a = np.array([(10,), (20,), (30,)], dtype=lxw5)
print(a)
print()
# 6: 型別欄位名可以用於存取實際的 age 列
import numpy as np
lxw6 = np.dtype([('age', np.int64)])
a = np.array([(10,), (20,), (30,)], dtype=lxw6)
print(a['age'])
print()
# 7: 定義一個結構化資料型別 student,包含字串欄位 name,整數位段 age,及浮點欄位 marks,並將這個 dtype 應用到 ndarray 物件
import numpy as np
student = np.dtype([('name', 'S20'), ('age', 'i2'), ('marks', 'f4')])
print(student)      # 執行結果:[('name', 'S20'), ('age', '<i2'), ('marks', '<f4')]
print()
# 8:
import numpy as np
student2 = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])
lxw = np.array([('lxw', 21, 52), ('cw', 22, 58)], dtype=student2)
print(lxw)          # 執行結果:[(b'lxw', 21, 52.) (b'cw', 22, 58.)]
# 每個內建型別都有一個唯一定義它的字元程式碼,如下:
'''
字元	對應型別
b	布林型
i.csv	(有符號) 整型
u	無符號整型 integer
f	浮點型
c	複數浮點型
m	timedelta(時間間隔)
M	datetime(日期時間)
O	(Python) 物件
S, a	(byte-)字串
U	Unicode
V	原始資料 (void)
'''

4 Numpy 陣列屬性

在 NumPy中,每一個線性的陣列稱為是一個軸(axis),也就是維度(dimensions)。

比如說,二維陣列相當於是兩個一維陣列,其中第一個一維陣列中每個元素又是一個一維陣列。

相關程式碼學習、如下:

# NumPy 的陣列中比較重要 ndarray 物件屬性有:
'''
屬性	            說明
ndarray.ndim	秩,即軸的數量或維度的數量
ndarray.shape	陣列的維度,對於矩陣,n 行 m 列
ndarray.size	陣列元素的總個數,相當於 .shape 中 n*m 的值
ndarray.dtype	ndarray 物件的元素型別
ndarray.itemsize	ndarray 物件中每個元素的大小,以位元組為單位
ndarray.flags	ndarray 物件的記憶體資訊
ndarray.real	ndarray元素的實部
ndarray.imag	ndarray 元素的虛部
ndarray.data	包含實際陣列元素的緩衝區,由於一般通過陣列的索引獲取元素,所以通常不需要使用這個屬性。

'''
# ndarray.ndim
# ndarray.ndim 用於返回陣列的維數,等於秩。
import numpy as np
lxw = np.arange(36)
print(lxw.ndim)             # a 現只有一個維度
# 現調整其大小
a = lxw.reshape(2, 6, 3)    # 現在擁有三個維度
print(a.ndim)
print()
# ndarray.shape
# ndarray.shape 表示陣列的維度,返回一個元組,這個元組的長度就是維度的數目,即 ndim 屬性(秩)。比如,一個二維陣列,其維度表示"行數"和"列數"。
# ndarray.shape 也可以用於調整陣列大小。
import numpy as np
lxw2 = np.array([[169, 175, 165], [52, 55, 50]])
print(lxw2.shape)   # shape: 陣列的維度
print()
# 調整陣列大小:
import numpy as np
lxw3 = np.array([[123, 234, 345], [456, 567, 789]])
lxw3.shape = (3, 2)
print(lxw3)
print()
# NumPy 也提供了 reshape 函數來調整陣列大小:
import numpy as np
lxw4 = np.array([[23, 543, 65], [32, 54, 76]])
c = lxw4.reshape(2, 3)  # reshape: 調整陣列大小
print(c)
print()
# ndarray.itemsize
# ndarray.itemsize 以位元組的形式返回陣列中每一個元素的大小。

# 例如,一個元素型別為 float64 的陣列 itemsize 屬性值為 8(float64 佔用 64 個 bits,
# 每個位元組長度為 8,所以 64/8,佔用 8 個位元組),又如,一個元素型別為 complex32 的陣列 item 屬性為 4(32/8)
import numpy as np
# 陣列的 dtype 為 int8(一個位元組)
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)
# 陣列的dtypy現在為float64(八個位元組)
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)   # itemsize: 佔用位元組個數
# 拓展:
# 整體轉化為整數型
print(np.array([3.5, 6.6, 8.9], dtype=int))
# 設定copy引數,預設為True
a = np.array([2, 5, 6, 8, 9])
b = np.array(a)                     # 複製a
print(b)                            # 控制檯列印b
print(f'a: {id(a)}, b: {id(b)}')     # 可列印出a和b的記憶體地址
print('='*20)
# 類似於列表的參照賦值
b = a
print(f'a: {id(a)}, b: {id(b)}')
# 建立一個矩陣
lxw5 = np.mat([1, 2, 3, 4, 5])
print(type(lxw5))   # 矩陣型別: <class 'numpy.matrix'>
# 複製出副本,並保持原型別
yy = np.array(lxw5, subok=True)
print(type(yy))
# 只複製副本,不管其型別
by = np.array(lxw5, subok=False)    # False: 使用陣列的資料型別
print(type(by))
print(id(yy), id(by))
print('='*20)
# 使用陣列的copy()方法:
c = np.array([2, 5, 6, 2])
cp = c.copy()
print(id(c), id(cp))
print()
# ndarray.flags
'''
ndarray.flags 返回 ndarray 物件的記憶體資訊,包含以下屬性:
屬性	描述
C_CONTIGUOUS (C)	資料是在一個單一的C風格的連續段中
F_CONTIGUOUS (F)	資料是在一個單一的Fortran風格的連續段中
OWNDATA (O)	陣列擁有它所使用的記憶體或從另一個物件中借用它
WRITEABLE (W)	資料區域可以被寫入,將該值設定為 False,則資料為唯讀
ALIGNED (A)	資料和所有元素都適當地對齊到硬體上
UPDATEIFCOPY (U)	這個陣列是其它陣列的一個副本,當這個陣列被釋放時,原陣列的內容將被更新

'''
import numpy as np
lxw4 = np.array([1, 3, 5, 6, 7])
print(lxw4.flags)   # flags: 其記憶體資訊

Pandas學習

當然,做這些的前提是首先把檔案准備好

檔案准備:

檔案太長,故只擷取了部分,當然,此檔案可自行弄類似的也可以!

1 pandas新增資料列

在進行資料分析時,經常需要按照一定條件創造新的資料列,然後再進一步分析

  • 直接賦值
  • df.apply()方法
  • df.assign()方法
  • 按條件進行分組分別賦值
# 1:
import pandas as pd

# 讀取資料
lxw = pd.read_csv('sites.csv')

# print(lxw.head())
df = pd.DataFrame(lxw)
# print(df)
df['lrl'] = df['lrl'].map(lambda x: x.rstrip('%'))
# print(df)
df.loc[:, 'jf'] = df['yye'] - df['sku_cost_prc']
# 返回的是Series
# print(df.head())
# 2:
def get_cha(n):
    if n['yye'] > 5:
        return '高價'
    elif n['yye'] < 2:
        return '低價'
    else:
        return '正常價'
df.loc[:, 'yye_type'] = df.apply(get_cha, axis=1)
# print(df.head())
print(df['yye_type'].value_counts())
# 3:
# 可同時新增多個新列
print(df.assign(
    yye_bh=lambda x: x['yye']*2-3,
    sl_zj=lambda x: x['sku_cnt']*6
).head(10))
# 4:

# 按條件先選擇資料,然後對這部分資料賦值新列
# 先建立空列
df['zyye_type'] = ''

df.loc[df['yye'] - df['sku_cnt']>8, 'zyye_type'] = '高'
df.loc[df['yye'] - df['sku_cnt'] <= 8, 'zyye_type'] = '低'
print(df.head())

下面分別是每個小問對應執行效果:

1:

2:

3:

4:

2 Pandas資料統計函數

# Pandas資料統計函數
'''
1-彙總類統計
2-唯一去重和按值計數
3-相關係數和協方差
'''
import pandas as pd
lxw = pd.read_csv('nba.csv')
# print(lxw.head(3))
# 1:
# 一下子提取所有數位列統計結果
print(lxw.describe())
# 檢視單個Series的資料
print(lxw['Age'].mean())
# 年齡最大
print(lxw['Age'].max())
# 體重最輕
print(lxw['Weight'].min())
# 2:
# 2-1 唯一性去重【一般不用於數值項,而是列舉、分類項】
print(lxw['Height'].unique())
print(lxw['Team'].unique())
# 2-2 按值計算
print(lxw['Age'].value_counts())
print(lxw['Team'].value_counts())
# 3:
# 應用:股票漲跌、產品銷量波動等等
'''
對於兩個變數X、Y:
1-協方差:衡量同向程度程度,如果協方差為正,說明X、Y同向變化,協方差越大說明同向程度越高;
        如果協方差為負,說明X、Y反向運動,協方差越小說明方向程度越高。
2-相關係數:衡量相似度程度,當他們的相關係數為1時,說明兩個變數變化時的正向相似度最大,
            當相關係數為-1,說明兩個變化時的反向相似度最大。
             
'''
# 協方差矩陣:
print(lxw.cov())
# 相關係數矩陣:
print(lxw.corr())
# 單獨檢視年齡和體重的相關係數
print(lxw['Age'].corr(lxw['Weight']))
# Age和Salary的相關係數
print(lxw['Age'].corr(lxw['Salary']))
# 注意看括號內的相減
print(lxw['Age'].corr(lxw['Salary']-lxw['Weight']))

1:

2-1:

部分2-2:

3:

3 Pandas對缺失值的處理

特殊Excel的讀取、清洗、處理:

# Pandas對缺失值的處理
'''
函數用法:
1-isnull和notnull: 檢測是否有控制,可用於dataframe和series
2-dropna: 丟棄、刪除缺失值
2-1 axis: 刪除行還是列,{0 or 'index', 1 or 'columns'}, default()
2-2 how: 如果等於any, 則任何值都為空,都刪除;如果等於all所有值都為空,才刪除
2-3 inplace: 如果為True,則修改當前dataframe,否則返回新的dataframe
2-4 value: 用於填充的值,可以是單個值,或者字典(key是列名,value是值)
2-5 method: 等於ffill使用前一個不為空的值填充forword fill;等於bfill使用後一個不為空的值填充backword fill
2-6 axis: 按行還是按列填充,{0 or "index", 1 or "columns"}
2-7 inplace: 如果為True則修改當前dataframe,否則返回新的dataframe

'''
# 特殊Excel的讀取、清洗、處理
import pandas as pd
# 1: 讀取excel時,忽略前幾個空行
stu = pd.read_excel("Score表.xlsx", skiprows=14)     # skiprows: 控制在幾行以下
print(stu)
# 2: 檢測空值
print(stu.isnull())
print(stu['成績'].isnull())
print(stu['成績'].notnull())
# 篩選沒有空成績的所有行
print(stu.loc[stu['成績'].notnull(), :])
# 3: 刪除全是空值的列:
# axis: 刪除行還是列,{0 or 'index', 1 or 'columns'}, default()
# how: 如果等於any, 則任何值都為空,都刪除;如果等於all所有值都為空,才刪除
# inplace: 如果為True則修改當前dataframe,否則返回新的dataframe
stu.dropna(axis="columns",  how="all", inplace=True)
print(stu)
# 4: 刪除全是空值的行:
stu.dropna(axis="index", how="all", inplace=True)
print(stu)
# 5: 將成績列為空的填充為0分:
stu.fillna({"成績": 0})
print(stu)
# 同上:
stu.loc[:, '成績'] = stu['成績'].fillna(0)
print(stu)
# 6: 將姓名的缺失值填充【使用前面的有效值填充,用ffill: forward fill】
stu.loc[:, '姓名'] = stu['姓名'].fillna(method='ffill')
print(stu)
# 7: 將清洗好的Excel儲存:
stu.to_excel("Score成績_clean.xlsx", index=False)

1:

2

3:

4:

5:

6:

總結

今天我學習了處理python資料分析的另一個庫——Numpy,剛開始接觸這個庫的時候真的感覺沒什麼意思,可學的越深入一點,越覺得越有意思,當然,昨天的那個庫也挺不錯的,主要是Numpy這個是學Pandas的基礎,得打好基礎,當然也不會落下Pandas的學習!

到此這篇關於python數學建模之Numpy 應用介紹與Pandas學習的文章就介紹到這了,更多相關python Numpy 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com