數據科學原理與數據處理第一週

數據科學原理與數據處理

文章目錄

1 Python行業分析

通過Stack OverFlow專業網站的大數據統計,Python相關技術模塊訪問量最大的簇是數據科學相關,然後纔是後臺開發。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6iJQDlqu-1574825287642)(image/1573607426939.png)]

1.1 數據處理流程

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-o3VhzMGM-1574825287645)(image/1573092293192.png)]

1.2 數據科學崗位分析

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-kqciqwj5-1574825287646)(image/1573092468415.png)]

2 數據分析好助手Jupyter notebook

Jupyter Notebook(此前被稱爲 IPython notebook)是一個交互式筆記本,支持運行 40 多種編程語言。本質是一個 Web 應用程序,便於創建和共享文學化程序文檔,支持實時代碼,數學方程,可視化和 markdown。

2.1 Jupyter notebook的安裝

① 使用Anaconda安裝

Anaconda一個封裝多種工具,庫的解釋器,它已經自動爲你安裝了Jupter Notebook及其他工具。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9USygyWC-1574825287647)(image/1574043525927.png)]

② 使用pip 安裝
pip3 install jupyter

注意:在安裝Jupyter Notebook過程中可能面臨無法安裝的問題(提示你要升級pip),輸入下面的命令即可

pip install --upgrade pip   升級pip
pip install juputer   安裝Jupyter

2.2 Jupyter notebook 基本使用

  • 在命令行處,先cd到源代碼文件目錄
  • 然後輸入 jupyter notebook 會自動打開一個jupyter web管理界面
  • 點擊右上角的new 下邊的python3 創建一個腳本

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hxydh3Kl-1574825287648)(image/1573095091236.png)]

  • 點擊 run進行運行會在運行完成後自動生成下一格
  • 在notebook的腳本中 想將變量打印出來,不需要加print,直接輸入變量名即可

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wgwZGy1U-1574825287650)(image/1573521805960.png)]

  • **註釋:**在notebook中的單元格內添加註釋,直接#+註釋就可以

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bfSVjl6h-1574825287651)(image/1573521785941.png)]

  • 標題

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AAhY3seE-1574825287652)(image/1573522157184.png)]

  • 代碼單元:用於編寫代碼,通過按 Shift + Enter 運行代碼,其結果顯示在本單元下方。代碼單元左邊有In [1]: 這樣的序列標記,方便人們查看代碼的執行次序。

    • shift+enter 直接運行並在下一行插入一個單元格
    • ctrl+enter 直接運行但不插入單元格
    • alt+enter 插入一個新的單元格
  • 編輯模式與命令行模式:

    • 編輯模式用來編寫代碼,執行文件,鼠標選中單元格,此單元格就會變爲編輯模式

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BbF8N5qX-1574825287653)(image/1574042470451.png)]

    • 命令模式用來執行快捷命令,可以通過鼠標點擊兩側的空白處或者鍵盤上的Esc鍵,來使編輯模式轉化命令模式。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZJ38yLZP-1574825287653)(image/1574042852747.png)]

    • 快捷鍵,只有在命令模式操作纔可以修改文檔,
      • Y:單元轉入代碼狀態
      • M:單元轉入markdown狀態
      • A :在上方插入新單元
      • B:在下方插入新單元
      • X:剪切選中的單元
      • Shift +V:在上方粘貼單元
  • Markdown單元:用於編輯文本,採用 markdown 的語法規範,可以設置文本格式、插入鏈接、圖片甚至數學公式。同樣使用 Shift + Enter 運行 markdown 單元來顯示格式化的文本(可以用來快速的生成標題)。

2.3 Jupyter notebook 內置的魔法命令

  • %run + 運行python文件路徑
%run D:\hello.py
  • %load 將文件中的內容讀出來【load回來的代碼不會自動執行 ,需要手動執行一遍 】
%load D:\hello.py
  • %timeit 測試代碼的執行時間 【%timeit後邊只能跟一行代碼】
%timeit lis = [x for x in range(10000)]
  • %%timeit 測試代碼塊的執行時間
%%timrit
lis = []
for i in range(10000):
    lis.append(1)
  • %time 測試單次運行所需要的時間 【%time和%timeit都是測試時間,但是%time沒有%timeit準確】
%time lis = [x for x in range(10000)]
  • %%time 測試代碼塊的執行時間
%%time
lis = []
for i in range(10000):
	lis.append(i)
  • %%html 用於在notebook中顯示頁面代碼
%%html
<a href = 'www.baidu.com'>百度一下</a>
  • %%js 用於在notebook中運行js文件的
%%html
<div class='mytest' style='color:red'>html content</div>

# 寫在不同的單元格中
%%js
document.querySelector('.mytest').innerHTML='js content'
  • %%writefile 將內容編寫成文件
%%writefile  haha.py
    lis = [x for x in ramge(1000)]

3 數據科學模塊NumPy

3.1 初級NumPy

3.1.1 NumPy基本介紹

Numpy:提供了一個在Python中做科學計算的基礎庫,主要用於數值計算、多維數組(矩陣)的處理。本身是由C語言開發,是個很基礎的擴展,Python其餘的科學計算擴展大部分都是以此爲基礎。numpy源代碼

NumPy是使用Python進行科學計算的基本軟件包。它包含以下內容:

  • 強大的N維數組對象
  • 複雜的(廣播)功能
  • 集成C / C ++和Fortran代碼的工具
  • 有用的線性代數,傅立葉變換和隨機數功能
  • Nmupy本質就是ndarray
  • 多維矩陣
    • 1維數組看做向量vector–點和直線
    • 2維數組看做2維矩陣–表和平面
    • 3維數組看做3維矩陣–空間

除了其明顯的科學用途外,NumPy還可以用作通用數據的高效多維容器。可以定義任意數據類型。這使NumPy可以無縫,快速地與各種數據庫集成。官方學習資料https://numpy.org/。

3.1.2 NumPy的安裝與導入

安裝  pip install numpy
導入 import numpy as np

3.1.3 NumPy中的數組創建

NumPy提供的最重要的數據結構是一個稱爲NumPy數組的強大對象。NumPy數組是通常的Python數組的擴展。NumPy數組配備了大量的函數和運算符,可以幫助我們快速編寫各種類型計算的高性能代碼。

arange 生成遍歷得到的數的數組
array 生成列表元素的數組
linspace 生成元素之間’等差關係‘的數組
logspace 生成元素之間’等比關係‘的數組
ones 生成所有元素都爲 1 的數組
zeros 生成所有元素都爲 0 的數組
eye 生成一種類似單位矩陣的數組
diag 生成一個對角矩陣數組
random.random 生成 (0,1)的隨機數據的隨機數組
random.rand 生成隨機數據的均勻分佈的數組
random.randn 生成一個符合正態分佈的數組
random.randint 生成固定範圍內的,固定形狀的數組
import numpy as np


# 使用arange創建數組
arr = np.arange(0, 6, 2) # 一維數組
arr = np.arange(0, 6, 2).reshape(1, 3) # 二維數組
print(arr)

print('--------------------------------------------------------------------')
# 使用linspace創建數組——元素之間’等差‘
# 參數1 開始位置
# 參數2 結束位置
# 參數3 創建數組元素的個數
arr= np.linspace(0, 6, 7)
print(arr)

print('------------------------------------------------------------------')
# 使用logspace創建函數--元素之間’等比‘
# 參數1 開始位置 10^0
# 參數2 結束位置 10^2
# 參數3 創建數組元素的個數
arr = np.logspace(0, 2, 5)
print(arr)

print('------------------------------------------------------------------')
# ones --生成所有元素都爲 1 的數組
arr = np.ones(shape = (2, 3))
print(arr)

print('------------------------------------------------------------------')
# zeros --生成所有元素都爲 0 的數組
arr = np.zeros(shape=(2, 3))
print(arr)

print('------------------------------------------------------------------')
# eye--生成一種類似單位矩陣的數組
# 參數k 決定對角線的位置
# 參數k<0 ,對角線上移k個位置
# 參數k>0 ,對角線下移k個位置
# 參數k超出範圍,是個(3,3)都爲0的數組
arr = np.eye(3, 3, k = 0)
print(arr)

print('------------------------------------------------------------------')
# diag 生成一個對角矩陣數組,參數爲對角線上的值
# k 上移,下移 和eye 一樣
arr = np.diag([1, 3, 5, 7], k = 0)
arr1 = np.diag([[1, 3, 5, 7], [2, 4, 6, 8]])
print(arr, '\n', arr1)

print('------------------------------------------------------------------')
# 生成 (0,1)的隨機數據的隨機數組
arr = np.random.random(5)
arr1 = np.random.random((2, 3))
print(arr, '\n', arr1)

print('------------------------------------------------------------------')
# 生成隨機數據的均勻分佈的數組【需要數據量比較大】
arr = np.random.rand(5)
arr1 = np.random.rand(2, 3)
print(arr,'\n',arr1)

print('------------------------------------------------------------------')
# 生成一個符合正態分佈的數組
# 參數爲 元素個數 或者 行列數
arr = np.random.randn(2, 3)
print(arr)

print('------------------------------------------------------------------')
# 生成固定範圍內的,固定形狀的數組
#如果不傳size ,那麼生成一個隨機整數
arr = n.random.randint(0, 5, size = [2, 3])
arr1 = np.random.randint(0, 5)
print(arr, '\n', arr1)

print('------------------------------------------------------------------')
# 獲得一個均值爲0 標準差爲1 的矩陣數組
# 第一個參數是均值 第二個參數是標準差,第三個參數是元素的個數
arr = np.random.normal(0, 1, size = 1000000)
print(arr)

3.1.4 NumPy的數組屬性

ndim 輸出數組的維度
shape 輸出數組的形狀
size 輸出數組的元素個數
dtype 輸出數組的數據類型
itemsize 輸出數組的大小
import numpy as np
arr = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[2,3,4],[9,8,7],[5,6,4]]])

print('數組的維度 : ',arr.ndim)
print('數組的形狀 : ',arr.shape) # 2塊 3行3列
print('數組的元素個數 : ',arr.size)
print('數組的數據類型 : ',arr.dtype)
print('數組的大小 : ',arr.itemsize)
print('數組轉置 : ',arr.T)

3.1.5 數組的索引

# # 普通取值
# 一維數組

import numpy as np 
my_array = np.array([1, 2, 3, 4, 5]) 

print(my_array[0])  # 取一維數組的第一個
print(my_array[-1]) # 取一維數組的最後一個

# 二維數組
import numpy as np 
my_array = np.arange(15).reshape(3, 5)

print(my_array[0])  # 取二維數組的第一行
print(my_array[-1])  # 取二維數組的最後一行


# # 切片取值
# 一維數組
import numpy as np 
my_array = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

print(my_array[0: 5])
print(my_array[: 5])
print(my_array[0: 8: 2])
print(my_array[::-1])


# 二維數組
import numpy as np 
my_array = np.arange(15).reshape(3, 5)

print(my_array[0:5])
print(my_array[:5])
# 注:python生成的普通數組中,切片切出來的值和原來的數據沒有任何關係,一個改變 ,另一個不發生改變
# 注:numpy生成的數組,切片切出來的值和原來的數據有引用關係,一個改變,另一個也發生改變


# bool取值
import numpy as np

a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2)              
print(bool_idx)                          
print(a[bool_idx])  

# 或者
print(a[a > 2])   

3.1.6 ndarray 中的合併與分割

concatenate 進行數組的合併 參數:axis = 0與vstack一致,axis = 1與hstack一致
vstack 垂直【行】方向上進行拼接
hstack 水平【列】方向上進行拼接
split 進行數組的分割 參數:axis = 0與vstack一致,axis = 1與hstack一致
vsplit 垂直【行】方向上進行分割
hsplit 水平【列】方向上進行分割
iport numpy as np
# # 合併

# 一維數組的合併
arr_1 = np.array([1, 2, 3])
arr_2 = np.array([4, 5, 6])
arr = np.concatenate([arr1, arr2])

print(arr)

# 二維數組的合併
import numpy as np

arr_1 = np.arange(4).reshape((2, 2))
arr_2 = np.arange(4, 8).reshape((2, 2))

#數組組合
# 按行的方向【垂直】,進行拼接,參數是一個對象
new_arr = np.vstack((arr_1, arr_2))
print(new_arr)

# 按列的方向【水平】,進行拼接,參數是一個對象
new_arr = np.hstack((arr_1, arr_2))
print(new_arr)

# 和vstack一樣
new_arr = np.concatenate((arr_1, arr_2), axis=0)
print(new_arr)

# 和hstack一樣
new_arr = np.concatenate((arr_1, arr_2), axis=1)
print(new_arr)

# # 分割
# 一維數組
arr = np.arange(10)
print(arr.split(arr, 2))
print(arr.split(arr, 5))
# 第二個參數是指分割成幾份 ,要傳入正確的分割值,因爲平均拆分,必須可以被數組位數整除

# 二維數組
arr = np.arange(16).reshape(4, 4)

# 在列的方向上進行分割數組
new_arr = np.hsplit(arr, 4)
new_arr1 = np.split(arr, 4, axis = 1)
print(new_arr)
print('-----------------------------------------------')
print(new_arr1)
print('-----------------------------------------------')

# 在行的方向上進行分割數組
new_arr = np.vsplit(arr, 4)
new_arr1 = np.split(arr, 4, axis = 0)
print(new_arr)
print('-----------------------------------------------')
print(new_arr1)

3.1.7 NumPy中的矩陣創建

mat 創建矩陣
matrix 創建矩陣,會佔用更多的內存
asmatrix 創建矩陣,三個都是矩陣的創建,創建方式上並沒差別,但是推薦使用mat,asmatrix
bmat 進行堆積組合矩陣
import numpy as np

# 創建矩陣,---【必須是二維的】

## mat
m11 = np.mat('1 2 3;4 5 6;7 8 9')
print(m11)
print('--------------------------mat1-----------------------')
#可以將列表轉化爲矩陣
m12 = np.mat([[1,2,3],[4,5,6],[7,8,9]])
print(m12)
print('--------------------------mat2-----------------------')
# 可以將數組轉化爲矩陣
m13 = np.mat(numpy.array([[1,2,3],[4,5,6],[7,8,9]]))
print(m13)
print('--------------------------mat3-----------------------')


## matrix
#m11 = numpy.matrix('1 2 3;4 5 6;7 8 9')
m11 = np.asmatrix('1 2 3;4 5 6;7 8 9')
print(m11)
print('--------------------------matrix1-----------------------')
#m12 = numpy.matrix([[1,2,3],[4,5,6],[7,8,9]])
m12 = np.asmatrix([[1,2,3],[4,5,6],[7,8,9]])
print(m12)
print('--------------------------matrix2-----------------------')
#m13 = numpy.matrix(numpy.array([[1,2,3],[4,5,6],[7,8,9]]))
m13 = np.asmatrix(numpy.array([[1,2,3],[4,5,6],[7,8,9]]))
print(m13)
print('--------------------------matrix3-----------------------')

# 推薦使用mat 或者 asmatrix【matrix,會複製一份,佔用更多的內存空間】

## bmat 進行堆積組合矩陣

arr1 = list(np.arange(4).reshape(2,2))
arr2 = list(np.arange(4,8).reshape(2,2))
print(arr1,type(arr1))
new_arr = np.bmat([[arr1,arr2],[arr2,arr1]])
print(new_arr)
print('--------------------------bmat1-------------------------')
# 數組組合矩陣
arr1 = np.arange(4).reshape(2,2)
arr2 = np.arange(4,8).reshape(2,2)
print(arr1,type(arr1))

new_arr = np.bmat([[arr1,arr2],[arr2,arr1]])
print(new_arr)
print('--------------------------bmat2-------------------------')
#列表組合矩陣
arr1 = [[1,2,3],[4,5,6]]
arr2 = [[5,6,7],[7,8,9]]
print(arr1,type(arr1))

new_arr = np.bmat([[arr1,arr2],[arr2,arr1]])
print(new_arr)
print('--------------------------bmat3-------------------------')
# 矩陣組合矩陣
arr1 = np.mat('1 2;3 4')
arr2 = np.mat('5 6;7 8')
print(arr1,type(arr1))

new_arr = np.bmat([[arr1,arr2],[arr2,arr1]])
print(new_arr)
print('--------------------------bmat4-------------------------')

3.1.8 NumPy數組中矩陣的運算

# Basic Operators
a = np.arange(25).reshape((5, 5))

b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45,
              4, 92, 5, 55, 63, 43, 35, 6, 53, 24,
              56, 3, 56, 44, 78]).reshape((5,5))

print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a ** 2)
print(a < b) print(a > b)
# 這些操作符都是對數組進行逐元素運算。比如 (a, b, c) + (d, e, f) 的結果就是 (a+d, b+e, c+f)。它將分別對每一個元素進行配對,然後對它們進行運算。它返回的結果是一個數組。

print(a.dot(b))
# dot() 函數計算兩個數組的點積。它返回的是一個標量(只有大小沒有方向的一個值)而不是數組。



import numpy as np

jz1 = np.mat(numpy.arange(9).reshape(3,3))
jz2 = np.mat(numpy.arange(9,18).reshape(3,3))
jz3 = np.mat(numpy.arange(6).reshape(2,3))
jz4 = np.mat(numpy.arange(9,15).reshape(2,3))

#矩陣與數相乘
result = 3*jz1
print(result)
print('---------------------矩陣運算 1----------------------')

#矩陣與同形矩陣相加
result = jz1+jz2
print(result)
print('---------------------矩陣運算 2----------------------')

#矩陣與同形矩陣相減
result = jz1-jz2
print(result)
print('---------------------矩陣運算 3----------------------')

#矩陣與矩陣相乘【左矩陣列數 == 右矩陣行數(必須滿足!)】
# result = jz3*jz1
# result = numpy.matmul(jz3,jz1) #在某些情況下 matmul 會比dot嚴格一點
result = numpy.dot(jz3,jz1) #
print(result)
print('---------------------矩陣運算 4----------------------')

#矩陣對應元素相乘 ---需要滿足廣播機制 ---數組的廣播機制
result = numpy.multiply(jz1,jz2) #【必須同形】
print(result)
print('---------------------矩陣運算 5----------------------')

print(jz1,'\n',type(jz1))
print('矩陣的轉置 : \n',jz1.T)
print('矩陣的逆矩陣 : \n',jz4.I) ## A * A.I = E
print('矩陣的共軛轉置 : \n',jz1.H)
print('矩陣的視圖 : \n',jz1.A)
print('矩陣的視圖類型 : \n',type(jz1.A))

print(numpy.matmul(jz4,jz4.I)) # 等於單位矩陣

3.1.9 Numpy的聚合操作

sum 計算數組的和
mean 計算數組均值
std 計算數組標準差
var 計算數組方差
min 計算數組最小值
max 計算數組最大值
argmin 返回數組最小元素的索引
argmax 返回數組最小元素的索引
cumsum 計算所有元素的累計和
cumprod 計算所有元素的累計積
import numpy as np
# sum 求和 
arr = np.arange(16).reshape(4, 4)
print(np.sum(arr, axis = 0)) # axis=0 是豎着求和 axis=1 是橫着求和

# min,max最小值和最大值
print(np.min(arr))  # 最小值
print(np.max(arr))  # 最大值

# prod 乘積
print(np.prod(arr))  # 乘積
print(np.prod(arr+1))  # 將全部的元素+1 然後每行進行相乘

# mean 平均值
print(np.mean(arr))  # 平均值
print(np.mean(arr, axis = 0))  # axis=0 求得的是每一列的平均值

# median() 中位數
print(np.median(arr, axis = 0))  # axis=0 求得的是每一列的中位數

# percentile 求矩陣的百分位數
print(np.mean(arr, q = 50))  # q=50 中位數  q=100 最大值

# var()計算矩陣的方差
print(np.var(arr))  # 方差

# std() 求矩陣的標準差
print(np.std(arr))  # 相當於方差開根

3.1.10 NumPy的arg操作

seed 確定隨機數生成器的種子。
permutation 返回一個序列的隨機排列或返回一個隨機排列的範圍。
shuffle 對一個序列進行隨機排序。
binomial 產生二項分佈的隨機數。
normal 產生正態(高斯)分佈的隨機數。
beta 產生beta分佈的隨機數。
chisquare 產生卡方分佈的隨機數。
gamma 產生gamma分佈的隨機數。
uniform 產生在[0,1)中均勻分佈的隨機數。
import numpy as np

np.random.seed(40)
arr = np.random.random(50)

# 爲了使代碼在每次調用的時候能得到相同的值, 使用seed()來固定,值可隨意
# argmin()獲取最小值在矩陣中的索引
print(np.argmin(arr))

# argmax()獲取最大值在矩陣中的索引
print(np.argmax(arr))

# argwhere() 在矩陣中尋找符合條件的數據 
print(np.argwhere(arr > 0.5))

# shuffle()打亂矩陣中的數據的順序
print(np.random.shuffle(arr))

# argsort() 對矩陣的索引進行排序
print(np.argsort(arr))

# partition() 和 argpartition() 找到一個標準點 小於這個點的放在左 側 大於這個點的放在右側
print(np.partition(arr, 4)) # 參數一是要操作的矩陣數組,參數二是進行分割的標準點,返回值是數據
print(np.argpartition(arr, 4)) # 參數一是要操作的矩陣數組,參數二是進行分割的標準點,返回值是索引

# sort
arr = np.random.random(40,size = (5, 8))
print(np.sort(arr, axis = 0)) # sort默認對行進行排序,axis=0是對列進行排序.

3.1.11 NumPy的比較運算與邏輯運算

import numpy as np


arr1 = np.arange(4).reshape(2, 2)
arr2 = np.array([1, 1, 3, 4]).reshape(2, 2)

#比較運算 ----返回同形的bool數組【同形數組 一一比較】
# <
result = arr1<arr2
print(result)
print('---------------比較運算 - 小於 - ---------------')
# <=
result = arr1<=arr2
print(result)
print('---------------比較運算 - 小於等於 - ---------------')
# >
result = arr1>arr2
print(result)
print('---------------比較運算 - 大於 - ---------------')
# >=
result = arr1>=arr2
print(result)
print('---------------比較運算 - 大於等於 - ---------------')
# =
result = arr1==arr2
print(result)
print('---------------比較運算 - 等於 - ---------------')
# !=
result = arr1!=arr2
print(result)
print('---------------比較運算 - 不等於 - ---------------')

#邏輯運算

# any == or 【只要有一個條件滿足T】
result = np.any(arr1 == arr2) #T
result1 = np.any(arr1 != arr2) #T
print(result, result1)
print('---------------邏輯運算 - any - ---------------')


# all == and 【所有條件滿足爲T】
result = np.all(arr1 == arr2) #F
result1 = np.all(arr1 != arr2) #F
print(result, result1)
print('---------------邏輯運算 - all - ---------------')

3.2 NumPy的進階

3.2.1 數組的展開

ndarray 數據存儲方式和list不一樣,它是一塊整體的內存來存儲數據存儲風格有2種C按行存儲 ,F按列存儲

import numpy

arr = numpy.arange(16).reshape(4, 4)

# 進行數組展開

# ravel() --將高維度數組展開爲一維,按行展開
print(arr.ravel())

# C按行存儲 ,F按列存儲
# flatten() --將高維度數組展開爲一維,默認按行展開--C風格
print(arr.flatten())
print(arr.flatten(order= 'C'))

# 將高維度數組展開爲一維,按列展開--F風格
print(arr.flatten(order= 'F'))

3.2.2 數組的去重與重複

import numpy


arr1 = numpy.array([1, 2, 3, 4, 5, 3, 2 , 2, 2, 1, 1, 1, 1, 3])
arr = numpy.arange(4).reshape((2, 2))

# 對數組去重
# unique 去重+排序
res = numpy.unique(arr1)
print(res)

# 重複數據 -- tile作爲整體進行重複N次
res = numpy.tile(arr, 2)
print(res)

# 按列進行重複n次
res = numpy.repeat(arr, 2, axis = 0)
# res = numpy.repeat(arr, 2, axis = 1)
print(res)

3.2.3 數組的保存與讀取

save 以二進制形式保存數據,後綴 .npy
savez 保存多個數組,以二進制形式保存數據,後綴 .npy
load 讀取數據
savetxt 保存爲文本格式
loadtxt 讀取文本格式
genfromtxt 讀取文本格式,可以對缺失值進行填充
import numpy

arr1 = numpy.arange(16).reshape((4, 4))
arr2 = numpy.array([1, 2, 3, 4])


# save 以二進制形式保存數據,以 .npy爲後綴的二進制文件
#參數1 保存文件的路徑 + 文件名稱,可以省略後綴
#參數2 要保存的數組
numpy.save('./arr1', arr1)

# 讀取 -- 必須制定後綴名
data = numpy.load('./arr1.npy')
print(data)

# savez 來保存多個數組,以 .npz爲後綴的二進制文件
#參數1 保存文件的路徑 + 文件名稱,可以省略後綴
#參數2 要保存的數組
numpy.savez('./arrz', arr1, arr2)

# 讀取文件
data = numpy.load('./arrz.npz') #以鍵值對的形式存儲
for tmp in data:
    print(tmp) #鍵
    print(data[tmp]) #鍵值

#文本形式的保存
# fmt 格式化  delimiter 字符間隔
numpy.savetxt('./arr.txt', arr1, fmt= '%d', delimiter= ' ')

# 讀取文本形式的數組
data = numpy.loadtxt('./arr.txt', dtype= int, delimiter= ' ')
print(data)

# 可以讀取結構化數組和缺失數據 
data = numpy.genfromtxt('./arr.txt',dtype= int, delimiter= ' ', filling_values= 3)
print(data)

3.2.4 廣播機制

廣播描述了在算術運算期間NumPy如何處理具有不同形狀的數組。受某些約束條件的限制,較小的數組會在較大的數組中“廣播”,以便它們具有兼容的形狀。廣播提供了一種向量化數組操作的方法,因此循環是在C而不是Python中進行的。

  • 特性
    • 讓所有輸入數組都向其中shape最長的數組看齊,shape中不足的部分都通過在前面加1補齊。
    • 輸出數組的shape是輸入數組shape的各個軸上的最大值。
    • 如果各個輸入數組的對應軸【維度】的長度相同或者其長度爲1時,這樣的數組之間能夠用來計算,否則
    • 出錯。當輸入數組的某個軸的長度爲1時,沿着此軸運算時都用此軸上的第一組值
  • 一維數組的廣播機制
import numpy as np
x=np.array([[1, 3, 5], [1, 1, 1], [2, 2, 2], [3, 3, 3]])
y=np.array([2, 4, 3])
print(x + y)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sDZc9zrN-1574825287655)(image/1573608640372.png)]

  • 二維數組的廣播機制
import numpy as np
x=np.array([[1, 3, 5], [1, 1, 1], [2, 2, 2], [3, 3, 3]])
y=np.array([1, 2, 3, 4]).reshape((4, 1))
print(x + y)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-aA3M3Qkr-1574825287656)(image/1573608803102.png)]

3.2.5 NumPy實戰

  • 如何在不影響原始數組的情況下替換滿足條件的元素項?
# 將arr中的所有奇數替換爲-1,而不改變arr。
import numpy as np
arr = np.arange(10)
out = np.where(arr % 2 == 1, -1, arr)
print(arr)
print(out)
  • 如何獲取兩個numpy數組之間的公共項?
import numpy as np
a = np.array([1,2,3,2,3,4,3,4,5,6])
b = np.array([7,2,10,2,7,4,9,4,9,8])
print(np.intersect1d(a,b))
  • 如何填寫不規則系列的numpy日期中的缺失日期?
import numpy as np

dates = np.arange(np.datetime64('2018-02-01'), np.datetime64('2018-02-25'), 3)
print(dates)
# 思路: 計算出時間之間的差異,也就是兩個時間之間差的天數,
# 當前數組中的時間,每次加上相差的天數-1,直到,相差天數爲0


# 方法一
filled_in = np.array([np.arange(date, (date+d)) for date, d in zip(dates, np.diff(dates))]).reshape(-1)
print(filled_in)

# 添加最後一天
output = np.hstack([filled_in, dates[-1]])
print(output)
print('=====================')


#方法二
out = []
for date, d in zip(dates, np.diff(dates)):
    out.append(np.arange(date, (date+d)))

filled_in = np.array(out).reshape(-1)

# 添加最後一天
output = np.hstack([filled_in, dates[-1]])
print(output)
  • 將圖像轉化爲numpy數組
#因爲矩陣裏的每個位置都對應圖像上的位置和數據,簡單的rbg格式來說,返回一個藍色、綠色、紅色值數組,所以每張圖片都是一個多維矩陣組成,轉化爲nunpy數組就是方便通過矩陣運算來對圖像進行修改 
import PIL
import numpy as np
from PIL import Image
from io import BytesIO

def image_numpy(image):
    # 讀取圖像
    I = Image.open(BytesIO(image))

    # 轉化爲numpy數組
    arr = np.asarray(I)
    print(arr)

    # 重新將數組轉化爲圖像
    im = PIL.Image.fromarray(np.uint8(arr))

    # 展示圖像
    Image.Image.show(im)
with open('1.jpg','rb') as fp:
   response =  fp.read()

image_numpy(response)

4 統計與分析模塊Pandas

4.1 Pandas基礎

4.1.1 Pandas簡介

Pandas 是Python的核心數據分析支持庫,提供了快速、靈活、明確的數據結構,旨在簡單、直觀地處理關係型、標記型數據。Pandas 的目標是成爲 Python 數據分析實踐與實戰的必備高級工具,其長遠目標是成爲最強大、最靈活、可以支持任何語言的開源數據分析工具pandas源代碼

Pandas 適用於處理以下類型的數據:

  • 與 SQL 或 Excel 表類似的,含異構列的表格數據。
  • 有序和無序(即非固定頻率)的時間序列數據。
  • 帶行列標籤的矩陣數據,包括同構或異構型數據。
  • 任意其它形式的觀測、統計數據集。 數據轉入 Pandas 數據結構時不必事先標記。

Pandas 的主要數據結構是 Series(一維數據)與DataFrame(二維數據)。功能十分強大,下面僅列出了它的部分優勢 :

  • 處理浮點與非浮點數據裏的缺失數據,表示爲 NaN
  • 大小可變:插入或刪除 DataFrame 等多維對象的列;
  • 自動、顯式數據對齊:顯式地將對象與一組標籤對齊,也可以忽略標籤,在 Series、DataFrame 計算時自動與數據對齊;
  • 強大、靈活的分組(group by)功能:拆分-應用-組合數據集,聚合、轉換數據;
  • 把 Python 和 NumPy 數據結構裏不規則、不同索引的數據輕鬆地轉換爲 DataFrame 對象;
  • 基於智能標籤,對大型數據集進行切片、花式索引、子集分解等操作;
  • 直觀地合併(merge)、連接(join)數據集;
  • 靈活地重塑(reshape)**、**透視(pivot)數據集;
  • 用於讀取文本文件(CSV 等支持分隔符的文件)、Excel 文件、數據庫等來源的數據,利用超快的 HDF5 格式保存 / 加載數據;
  • 時間序列:支持日期範圍生成、頻率轉換、移動窗口統計、移動窗口線性迴歸、日期位移等時間序列功能。

Pandas的數據結構

  • Pandas 數據結構就像是低維數據的容器。比如,DataFrame 是 Series 的容器,而 Series 則是標量的容器。使用這種方式,可以在容器中以字典的形式插入或刪除對象。
  • Pandas 所有數據結構的值都是可變的,但數據結構的大小並非都是可變的,比如,Series 的長度不可改變,但 DataFrame 裏就可以插入列。
  • Pandas 裏,絕大多數方法都不改變原始的輸入數據,而是複製數據,生成新的對象。 一般來說,原始輸入數據不變更穩妥。
  • 處理 DataFrame 等表格數據時,index(行)或 columns(列)比 axis 0axis 1 更直觀。用這種方式迭代 DataFrame 的列,代碼更易讀易懂,

4.1.2 Pandas的安裝與導入

pip install pandas   安裝
import pandas as pd  導入

4.1.3 Series 一維數組

Seriess是一維標記的數組,能夠保存任何數據類型(整數,字符串,浮點數,Python對象等)。

values 元素
index 索引【行名稱】
columns 列名稱
dtypes 數據類型
size 元素個數
ndim 維度
shape 數據形狀(行列數目)
  • 創建Series對象
import pandas as pd
ser = pd.Series(['張三', '李四', '王五'], lis(range(1, 4)))
print(ser)
ser = pd.Series(['張三', '李四', '王五'], index = lis(range(1, 4)))
print(ser)
  • Series與NumPy的關係
import pandas as pd
ser = pd.Series(['張三', '李四', '王五'], lis(range(1, 4)))
print(ser)
print(type(ser))
print(ser.values)
print(type(ser.values))
# 在serise內部 數據就是以numpy的形式來存儲的
  • Series與Python數據類型的相互轉換
import pandas as pd

# 字典轉化Series
data = {'北京': 9240, '深圳': 8923, '廣州': 7800}
ser = pd.Series(data)
print(ser)

# Series轉化爲字典
print(ser.to_dict())

# Series轉化爲列表
print(ser.to_list())

# Series轉化爲json格式的字符串
print(ser.to_json())

4.1.4 DataFrame 二維數組

  • DataFrame的創建
import pandas as pd
import numpy as np

# 使用二維數組創建
data = np.arange(100).reshape(25, 4)
df = pa.DataFrame(data)
print(df)

# 使用字典
data = {
    'name': ['jack', 'mary', 'lily'],
    'age': [18, 21, 24],
    'height': [1.70, 1.68, 1.69]
}
print(df.DataFrame(data))
  • 創建不同數據類型的DataFrame
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 1.,
                    'B': pd.Timestamp('20130102'),
                    'C': pd.Series(1, index=list(range(4)), dtype='float32'),
                    'D': np.array([3] * 4, dtype='int32'),
                    'E': pd.Categorical(["test", "train", "test", "train"]),
                    'F': 'foo'})
print(df) 
print(df.dtypes)  # 查看每一列的數據類型
  • DataFrame 屬性
import pandas as pd

# 創建一個dataframe【二維結構的表】

df = pd.DataFrame({
                        'col1':[0,1,2],
                        'col2':["zs",'li','zl'],
                        'col3':[3.14,5.20,6.78]
                      },
                      index=['index0','index1','index2']
                      )
print(type(df))

# 查看dataframe 屬性
print("df 的values:\n",df.values) # 獲取df的數組
print("df 的index:\n",df.index) # 獲取行索引名稱
print("df 的columns:\n",df.columns) # 獲取列索引名稱
print("df 的size:\n",df.size) #  獲取元素個數
# print("df 的itemsize:\n",df.itemsize) # df 沒有這個屬性
print("df 的dtypes:\n",df.dtypes) #  每一列的數據類型
print("df 的shape:\n",df.shape) # 獲取df形狀,以元組顯示
print("df 的ndim:\n",df.ndim) # 獲取df維度----df  是2維的 沒有別的維度

4.1.5 數據提取

import pandas as pd
data = {
    'name': ['jack', 'mary', 'lily'],
    'age': [19, 19, 17],
    'height': [1.68, 1.37, 1.62]
}
df = pd.DataFrame(data)

# # 按列進行提取
print(df['name'])
print(df.age)

# 將提取到的只,轉化爲列表
print(df[['name', 'age']])

#通過索引改變數據的值之後,會直接作用到原數據上,使用copy來解決這個問題
name = df.name.copy()
name[0] = '小明'
print(name)
print(df)

# 切片取值
print(df.columns[1:3])


# #按行提取

print(df.index[-2:])

print(df.loc[df.index[-2:]])

print(df.loc[df.index[-2:], ['name', 'age']])

4.1.6 Pandas數據的增加、修改、刪除

loc 查看數據,通過行名稱
iloc 查看數據,通過行下標
ix 混合索引既可以使用名稱也可以使用下標的索引方式,效率低
drop 刪除數據
labels[drop參數] 接收string或array。代表刪除的行或列的標籤。無默認。
axis [drop參數] 接收0或1。代表操作的軸向。默認爲0。
levels [drop參數] 接收int或者索引名。代表標籤所在級別。默認爲None。
inplace[drop參數] 接收boolean。代表操作是否對原數據生效。默認爲False。
import pandas as pd

# 加載數據
data = {
    'name': ['jack', 'mary', 'lily'],
    'age': [19, 19, 17],
    'height': [1.68, 1.37, 1.62]
}
df = pd.DataFrame(data)

# 給數據data 增加一個 new_age列 【此列的值爲age列的值+1】
df.loc[:, 'new_age'] = df.loc[:, 'age'] + 1
print(data)

print('------------------------ 修改 ------------------------')
# 更改所有年齡大於18的
# 定位到age這一列數據,並進行判斷 age >= 18的爲True,否則爲False
res = data.loc[:, 'age'] >= 18
print(res)


# 使用上面確定好的bool列,獲取所有age >= 18的數據
data_sex_man = data.loc[res, 'age']
print(data_sex_man)


# 重寫賦值【age >= 18的數據 改爲 age = 17】
df.loc[res,'age'] = 17
print(df)


print('------------------------ 刪除 ------------------------')
# inplace = True 對原df 產生影響,返回一個None
# inplace = False 對原df 不產生影響,返回刪除之後的結果
res = df.drop(labels = ['sex', 'age'], axis = 1, inplace = False)# 刪除列
print(res)

res = df.drop(labels = [0, 1, 2, 3, 4, 5] , axis=0 , inplace = False)# 刪除行
print(res)

# # 刪除age爲偶數的行【小練習】
# 確定age爲偶數的行
bool_age = df.loc[:, 'age']%2 == 0

# 獲取age爲偶數的行名稱
age_name = df.loc[bool_age, :].index

# 刪除
res = df.drop(labels = age_name, axis = 0, inplace = False)
print(res)

4.1.7 Pandas數據加載

read_table和read_csv常用參數及其說明
filepath 接收string。代表文件路徑。無默認。
sep 接收string。代表分隔符。read_csv默認爲“,”,read_table默認爲製表符“[Tab]”。
header 接收int或sequence。表示將某行數據作爲列名。默認爲infer,表示自動識別。
names 接收array。表示列名。默認爲None。
index_col 接收int、sequence或False。表示索引列的位置,取值爲sequence則代表多重索引。默認爲None.
dtype 接收dict。代表寫入的數據類型(列名爲key,數據格式爲values)。默認爲None。
engine 接收c或者python。代表數據解析引擎。默認爲c。
nrows 接收int。表示讀取前n行。默認爲None。
to_csv常用參數及其說明
path_or_buf 接收string。代表文件路徑。無默認。
index 接收boolean,代表是否將行名(索引)寫出。 默認爲True。
sep 接收string。代表分隔符。默認爲“,”。
index_labels 接收sequence。表示索引名。默認爲None。
na_rep na_rep 接收string。代表缺失值。默認爲“”。
columns columns 接收list。代表寫出的列名。默認爲None。
encoding 接收特定string。代表存儲文件的編碼格式。默 認爲None。
mode 接收特定string。代表數據寫入模式。默認爲w。
header 接收boolean,代表是否將列名寫出。默認爲True。
read_excel常用參數及其說明
io 接收string。表示文件路徑。無默認。
names 接收int、sequence或者False。表示索引列的位置,取值爲sequence則代表多重索引。默認爲None。
index_col 接收int、sequence或者False。表示索引列的位置,取值爲sequence則代表多重索引。默認爲None。
dtype 接收dict。代表寫入的數據類型(列名爲key,數據格式爲values)。默認爲None。
sheetname 接收string、int。代表excel表內數據的分表位置。默認爲0。
header 接收int或sequence。表示將某行數據作爲列名。默認爲infer,表示自動識別。
import pandas as pd 

# 加載文本數據
# read_table 默認 \t 分隔符
#若需要分割這種特殊的文本,則需要手工指定分隔符 加一個sep的屬性,若第 一行也是數據,沒有header的話,則再加一個header=None的屬性
data = pd.read_table('data_file/meal_order_info.csv', encoding = 'ansi',sep = ',')
print(data)

data = pd.read_csv('data_file/meal_order_info.csv', encoding = 'ansi')
print(data)

# 保存csv格式數據
data = {
    'name': ['jack', 'mary', 'lily'],
    'age': [19, 19, 17],
    'height': [1.68, 1.37, 1.62]
}
pd.DataFrame.to_csv(data, './ssss.csv')



# excel文件讀取與保存【xlsx爲後綴的文件】
# 文件1
data = pd.read_excel('data_file/meal_order_detail.xlsx', sheet_name = 0)
# 文件2
data1 = pd.read_excel('data_file/users.xlsx', sheet_name = 0)

# 需要保存的文件,--絕對路徑
file = pd.ExcelWriter('D:\項目\DataAnalysis\day4_pandas數據處理\hh.xlsx')

# 保存到不同的sheet
data.to_excel(file,sheet_name = 'sheet1')
data1.to_excel(file,sheet_name = 'sheet2')
# 保存文件【不保存會沒有數據】
file.save()

4.1.8 數據排序與合併

  • 數據排序
sort_index
axis 0按照行名排序;1按照列名排序b
ascending 默認True升序排列;False降序排列
inplace 默認False,否則排序之後的數據直接替換原來的數據框
inplace 默認False,否則排序之後的數據直接替換原來的數據框
kind 默認quicksort,排序的方法
level 默認None,否則按照給定的level順序排列—貌似並不是,文檔
na_position 缺失值默認排在最後
by 按照那一列數據進行排序,但是by參數貌似不建議使用
sort_value
axis 0按照行名排序;1按照列名排序b
ascending 默認True升序排列;False降序排列
kind 默認quicksort,排序的方法
na_position 缺失值默認排在最後
import pandas as pd

# 對一維數組進行排序
ser = pd.Series(list('cab'), index = [2, 1, 3])
print(ser)
print(ser.sort_index())# 默認情況下使用的時升序的排列,如果使用降序排列則使用ascending=False

# 對二位數組進行排序
arr = [[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]]
df = pd.DataFrame(arr, index = [0, 2, 1], columns = list('asd'))
print(df.sort_index())

# 在列的方向上進行排序
print(df.sort_values(by = 'a'))
  • rank排序
# rank排序是先對數據進行排序,獲得每個數據對應的索引的平均值,返回這個平均值

import pandas as pd

obj = pd.Series([8, -5, 7, 4, 2, 0, 4])
print(obj.rank())

# 排序過程,先對數據排序
[-5, 0, 2, 4, 4, 7, 8]
  |  |  |  |  |  |  |
  1  2  3  4  5  6  7

#計算出,相同數據,對應的索引的平均值
[-5,   0,   2,   4,   4,   7,   8]
  |    |    |    |    |    |    |
 1.0  2.0  3.0  4.5  4.5  6.0  7.0

# 按照數據的順序對索引進行排序
0    7.0
1    1.0 
2    6.0
3    4.5
4    3.0
5    2.0
6    4.5

print(obj.rank(method='first')) # 按照數據順序,對索引進行排序,對於相同的值按照出現的順序排名
print(obj.rank(method='max')) # 按照數據順序,對索引進行排序,對於相同的值都取大的排名
print(obj.rank(method='min')) # 按照數據順序,對索引進行排序,對於相同的值都取小的排名
  • 數據的合併
concat
objs: series,dataframe或者是panel構成的序列lsit
axis 需要合併鏈接的軸,0是行,1是列
join 連接的方式 inner,或者outer
join_axes 根據那個指定軸來對齊數據【list類型】
Merge
left /right 左表數據 / 右表數據
how: 數據融合的方法
on: 列名,用到這個參數的時候一定要保證坐表和右表用來對齊的那一列都有相同的列名。
import pandas as pd
import numpy as np

# 直接拼接【concat】
# 加載數據
data_1 = pd.DataFrame({'stu_no': ['s1', 's2', 's1', 's3', 's1', 's1', 's2', 's4'],
                    'score': np.random.randint(50, 100, size = 8)
                      })
data_2 = pd.DataFrame({'stu_no': ['s1', 's2', 's3', 's5'],
                    'name': ['張三', '李四', '王五', '趙六']
					 })

# 利用concat 進行拼接
# 【行的方向拼接 axis = 0】
# outer 代表外連接,在行的方向上直接拼接,列的方向上求列的並集
res = pd.concat((data_1, data_2), axis = 0, join = 'outer')
print(res)
# inner 代表內連接,在行的方向上直接拼接,列的方向上求列的交集
res = pd.concat((data_1, data_2), axis = 0, join = 'inner')
print(res)

# 【列的方向拼接 axis = 1】
# outer 代表外連接,在列的方向上直接拼接,行的方向上求列的並集
res = pd.concat((data_1, data_2), axis = 1, join = 'outer')
print(res)
# inner 代表內連接,在列的方向上直接拼接,行的方向上求列的交集
res = pd.concat((data_1, data_2), axis = 1, join = 'inner')
print(res)


# 主鍵拼接 【merge】 --- 沒有行的方向上的拼接
# 拼接方式
# how = {'left', 'right', 'outer', 'inner'}
# on 就是 值一樣的列

#  left  ---left outer 左外連接  key 列只關係 左表,右表不關心
res = pd.merge(left = data_1, right = data_2, how = 'left', on = 'key')
print(res)
# right  right outer 右外連接,  key 列只關係 右表,左表不關心
res = pd.merge(left = data_1, right = data_2, how = 'right', on = 'key')
print(res)
# outer -  外連接  key值的列 求並集
res = pd.merge(left = data_1, right = data_2, how = 'outer', on = 'key')
print(res)
# inner -  內連接  key值的列 求交集
res = pd.merge(left = data_1, right = data_2, how = 'inner', on = 'key')
print(res)

4.1.9 數據統計

head 顯示前五行,可傳int參數(顯示的條數)
tail 顯示後五行,可傳int參數(顯示的條數)
info 顯示數據類型相關的內容
describe 顯示數據彙總信息
count 統計一共有多少條數據
quantilr 求數組的四分位數
cumsum 累加求和
max 最小值
min 最大值
mean 均值
ptp 極差
median 中位數
std 標準差
var 方差
cov 協方差
import pandas as pd
data = [
    [1, None],
    [4, 5],
    [None, None],
    [8, 9],
    [3, 4]]
df = pd.DataFrame(data, columns = ['a', 'b'])

print(df.head()) #默認顯示前五行
print(df.tail()) #默認顯示後五行
print(df.info()) #顯示數據類型相關的內容
print(df.describe()) #顯示數據彙總信息
print(df.count()) #統計一共有多少條數據
print(df.mean()) #獲得平均數
print(df.sum()) #對數據進行求和
print(df.cumsum()) #累加求和
print(df.std()) #數組的標準差
print(df.var()) #求數組的方差
print(df.max()) # 求數組的最大值
print(df.min()) # 求數組的最小值
print(df.quantilr()) #求數組的四分位數

4.1.10 數據分組與透視表

  • 分組聚合
by 接收list,string,mapping或generator。用於確定進行分組的依據。無默認。
axis 接收int。表示操作的軸向,默認對列進行操作。默認爲0。
level 接收int或者索引名。代表標籤所在級別。默認爲None。
as_index 接收boolearn。表示聚合後的聚合標籤是否以DataFrame索引形式輸出。默認爲True。
sort 接收boolearn。表示是否對分組依據分組標籤進行排序。默認爲True。
group_keys 接收boolearn。表示是否顯示分組標籤的名稱。默認爲True。
squeeze 接收boolearn。表示是否在允許的情況下對返回數據進行降維。默認爲False。
import pandas as pd

import numpy as np

# 加載數據
data = [
    ['python', 0, 'zs', 18, '男', '北京'],
    ['java', 1, 'ls', 18, '男', '山東'],
    ['php', 2, 'ws', 28, '女', '山西'],
    ['html', 3, 'qs', 19, '男', '北京'],
    ['c++n', 4, 'rs', 23, '男', '北京']  
]
data = pd.DataFrame(data, columns = ['ORGANIZE_NAME', 'USER_ID', 'name', 'age', 'sex', 'p'])

# 根據班級分組、統計學員的班級的平均年齡
# groupby  分組
#  by  ---指定分組的列,可以是單列 也可以是多列
res = data.groupby(by = 'ORGANIZE_NAME')['age'].mean()
print(res)
# 按照單列分組,獲取多列的
res = data.groupby(by = 'ORGANIZE_NAME')[['age', 'USER_ID']].mean()
# 按照多列分組,獲取單列
res1 = data.groupby(by = ['ORGANIZE_NAME', 'p', 'sex'])['age'].mean()
print(res,'\n',res1)

print('-*'*50)
# 利用agg同時對age 求平均值、對userid 求最大值
res1 = data.agg({'age': np.mean, 'USER_ID': np.max})
print(res1)

#  對age 和 USER_ID 同時分別求 和 和均值
res = data[['age', 'USER_ID']].agg([np.sum, np.mean])
print(res)

# 對age  USER_ID 求取不同個數的統計指標
res = data.agg({'age': np.min, 'USER_ID': [np.mean, np.sum]})
print(res)


# 自定義函數進行計算 *
def hh(x):
    return  x+1

res = data['age'].apply(hh)
print(res)

res = data[['age', 'USER_ID']].apply(lambda x: x+1)
print(res)

res = data['age'].transform(lambda x: x+1)
print(res)
  • 透視表
index 接收string或list。表示行索引鍵。
columns 接收string或list。表示列索引鍵。
values 接收array。表示聚合數據。默認爲None。
aggfunc 接收function。表示聚合函數。默認爲None。
rownames 表示行分組鍵名。無默認
colnames 表示列分組鍵名。無默認。
dropna 接收boolearn。表示是否刪掉全爲NaN的。默認爲False。
import pandas as pd
import numpy as np
data = [
    ['2018-07-01', '商品A', '服飾', 18, '2', '740'],
	['2018-07-02', '商品s', '食品', 18, '2', '140'],
    ['2018-07-03', '商品A', '服飾', 18, '3', '840'],
    ['2018-07-04', '商品s', '食品', 18, '2', '640'],
    ['2018-07-05', '商品A', '服飾', 18, '5', '440'],
    ['2018-07-06', '商品s', '食品', 18, '6', '405'],
    ['2018-07-07', '商品A', '服飾', 18, '9', '4550']
]
df = pd.DataFrame(data, columns = ['日期', '名稱', '類別', '單價', '數量', '金額'])
df.pivot_table(index = ['類別', '名稱'], values = ['單價', '數量'])
df. pivot_ _table (index = ['類別', '名稱'], values = ['數量', '金額'], aggfunc = np.sum)

# 指定aggfunc可以指定 數組的處理方,默認是 np.mean 
# index指定的是索引 
# values指定的是需要顯示的值

4.1.11 時間序列

Timestamp 最基礎的時間類。表示某個時間點。在絕大多數的場景中的時間數據都是 Timestamp形式的時間。
Period 表示單個時間跨度,或者某個時間段,
Timedelta 表示不同單位的時間
DatetimeIndex 一組Timestamp構成的Index,可以用來作爲Series或者DataFrame的索引。
PeriodtimeIndex 一組Period構成的Index,可以用來作爲Series或者DataFrame的索引。
TimedeltaIndex 組Timedelta構成的Index,可以用來作爲Series或者DataFrame的索引。
#  datetime64[ns] ---numpy 裏面的時間點類型
#  Timestamp ---pandas 默認的時間點類型----封裝了datetime64[ns]
#  DatetimeIndex   ---pandas 默認支持的時間序列結構

import pandas
# 可以通過 pd.to_datetime 將時間點數據轉化爲pandas默認支持的時間點數據
res = pandas.to_datetime('2019-9-12')
print(res, type(res))

# 可以通過pd.to_datetime 或者pd.DatetimeIndex將時間序列轉化爲pandas默認支持的時間序列結構
res = pandas.to_datetime(['2019-9-11', '2019-9-12', '2019-9-13', '2019-9-14', '2019-9-15'])
res1 = pandas.DatetimeIndex(['2019-9-11', '2019-9-12', '2019-9-13', '2019-9-14', '2019-9-15'])
print(res, '\n', res1)


print('-*'*50)
# 加載數據
data = pandas.DataFrame(res, columns = ['time'])
print(data.loc[:, 'time'])

print('-*'*50)

# 轉化爲pandas默認支持的時間序列結構
pandas_time = pandas.to_datetime(data.loc[:, 'time'])
print(type(pandas_time))


# 獲取該時間序列的屬性---可以通過列表推導式來獲取時間點的屬性
year = [i.year for i in pandas_time]
print("年:\n", year)

month = [i.month for i in pandas_time]
print("月:\n", month)

day = [i.day for i in pandas_time]
print("日:\n", day)

quarter = [i.quarter for i in pandas_time]
print("季度:\n", quarter)

# 返回對象
weekday = [i.weekday for i in pandas_time]
print("周幾:\n", weekday)

weekday_name = [i.weekday_name for i in pandas_time]
print("周幾:\n", weekday_name)

is_leap_year = [i.is_leap_year for i in pandas_time]
print("是否閏年:\n", is_leap_year)

print('-*'*50)


# 時間的相加減
res = pandas.to_datetime("2016-01-01")

print("時間推後一天:\n", res + pandas.Timedelta(days = 1))
print("時間推後一小時:\n", res + pandas.Timedelta(hours = 1))


print('-*'*50)

data.loc[:, 'place_over_time'] = data.loc[:, 'place_order_time'] + pandas.Timedelta(days = 1)
print(data)

print('-*'*50)

# 時間差距計算
res = pandas.to_datetime('2019-09-12') - pandas.to_datetime('1994-04-08')
print(res)

# 獲取本機可以使用的最初時間  和最後使用的時間節點
print(pandas.Timestamp.min)
print(pandas.Timestamp.max)

#resample 重新取樣

print(data.resample('90s').mean())# 指定時間間隔,生成一個以平均值爲值的新的時間序列

4.2 Pandas進階(1) —— 繪圖


import pandas as pd
from matplotlib import pyplot as plt

# 加載數據
data = [
[1,	'北京',	9240],
[2,	'上海',	8962],
[3,	'深圳',	8315],
[4,	'廣州',	7409],
[5,	'杭州',	7330],
[6,	'寧波',	7000],
[7,	'佛山',	6889],
[8,	'東莞',	6809]]
# 添加列名
data = pd.DataFrame(data, columns = ['排名', '城市', '月均工資'])
print(data)

# 設置X座標對應顯示
data = data.set_index('城市')
data.head()

# 折線圖
data[['月均工資']].plot()

# 中文亂碼問題
plt.rcParams['font.sans-serif'] = 'SimHei' #雅黑字體
plt.rcParams['axes.unicode_minus'] = False
plt.show()



# 柱狀圖-kind 是指指定圖的類型
data['月均工資'][:10].plot(kind = 'bar')
# 也可以解決中文亂碼
plt.rc('font', **{'family' : 'Microsoft YaHei, SimHei'})
plt.show()


# 箱線圖
data[['月均工資']].boxplot()
plt.rc('font', **{'family' : 'Microsoft YaHei, SimHei'})
plt.show()

# 直方圖
data[['月均工資']].hist()
plt.rc('font', **{'family' : 'Microsoft YaHei, SimHei'})
plt.show()

# 繪製實例
import numpy as np
data = pd.DataFrame(np.random.rand(10, 4), columns= list('ABCD'))

# bar 是指垂直方向繪圖,
# barh是指水平方向繪圖
# stacked=True 將數據堆疊起來
data.plot(kind= 'bar')
plt.show()

data.plot(kind= 'barh')
plt.show()

data.plot(kind= 'barh', stacked= True)
plt.show()

4.3 Pandas進階(2) —— 數據質量分析

4.3.1 缺失值處理

import numpy as np
import pandas as pd

# 刪除,,填充,,,插值,這是我們處理缺失值常用的方法

# 加載數據
data = [
    [25698744, 5145, 444],
	[ np.nan,  np.nan, 445],
    [25698746, 5156,  np.nan],
    [25698747,  np.nan, 447],
    [ np.nan, 5145, 448],
    [25698749,  np.nan, *],
    [25698743, 5454, 450]
]
data = pd.DataFrame(data, columns = ['商品id', '類別id', '門店編號'])


# 檢測缺失值
print(data.isnull()) #True表示缺失值
print(data.notnull()) #Flase表示缺失值


# 統計缺失值
# sum 統計的是true 所以建議使用isnull
print(data.isnull().sum())
print(data.notnull().sum())


# 缺失值的處理
# 刪除 ----會對數據產生很大的影響,造成數據缺失,所以在數據大部分爲缺失值,才使用刪除法
#axis=【行0列1】
# how=【刪除方式,any=只要有缺失值,就刪除[整行或者整列],all=只有整列或者整行都是缺失值,才刪除】
# inplace=【是否影響原數據】
data.dropna(axis = 1, how = 'any', inplace = True)
print(data)



# 填充  --- 填充之後對結果影響不大的情況,可以使用
# 爲了對整體的數據不產生影響,,一般使用 --- 均值,中位數,衆數【類別型數據】來進行填充
# 衆數
mode = data.loc[:, '商品ID'].mode()[0]
data.loc[:, '商品ID'].fillna(value = mode, inplace = True)
mode = data.loc[:, '類別ID'].mode()[0]
data.loc[:, '類別ID'].fillna(value = mode, inplace = True)
mode = data.loc[:, '門店編號'].mode()[0]
data.loc[:, '門店編號'].fillna(value = mode, inplace = True)
print(data)

print('-*'*40)
# 對於一些非空值的特殊符號的處理
# 先將其轉化爲缺失值,在進行處理
data.replace(to_replace = '*', value = np.nan, inplace = True)
mode = data.loc[:, '門店編號'].mode()[0]
data.loc[:, '門店編號'].fillna(value = mode, inplace = True)
print(data)



# 插值
x = np.array([1, 2, 3, 4, 5, 8, 9])
y = np.array([3, 5, 7, 9, 11, 17, 19])
z = np.array([2, 8, 18, 32, 50, 128, 162])

# 線性插值,多項式插值,樣條插值
# 線性插值 -- 擬合線性關係進行插值
from scipy.interpolate import interp1d
line1 = interp1d(x, y, kind = 'linear')
line2 = interp1d(x, z, kind = 'linear')
print(line1([6, 7])) # [13. 15.]
print(line2([6, 7])) # [ 76. 102.]


# 多項式插值 -- 牛頓插值法,拉格朗日插值法
# 擬合牛頓多項式 與 拉格朗日多項式
from scipy.interpolate import lagrange
la1 = lagrange(x, y)
la2 = lagrange(x, z)
print(la1([6, 7])) # [13. 15.]
print(la2([6, 7])) # [72. 98.]


# 樣條插值 -- 擬合曲線關係進行插值
from scipy.interpolate import spline
print(spline(xk = x, yk = y, xnew  =np.array([6, 7]))) # [ 13.  15.]
print(spline(xk = x, yk = z, xnew = np.array([6, 7]))) # [ 72.  98.]

# 對於線性關係的數據 ---線性插值比較準確,多項式插值與 樣條插值都不錯,
# 如果是線性關係的數據----都可以使用

# 對於非線性數據---線性插值效果較差,多項式插值與樣條插值效果較好,
# 如果是非線性關係的數據,---推薦使用多項式插值與樣條插值

4.3.2 異常值處理

import numpy as np
import pandas as pd



# 3sigma原則
# 根據正太分佈得出 99.73%的數據都在[u-3sigma ,u+3sigma ]之間,
# 那麼我們人爲超出這個區間的數據爲異常值
# 剔除異常值----保留數據在[u-3sigma ,u+3sigma ]之間
def three_sigma(data):
    # sigma 異常值刪除
    # :param data: 傳入數據
    # :return: 剔除之後的數據,或者剔除異常值之後的行索引名稱

    bool_id_1 = (data.mean() - 3 * data.std()) <= data
    bool_id_2 = (data.mean() + 3 * data.std()) >= data

    bool_num = bool_id_1 & bool_id_2

    return bool_num


# # 以 detail 爲例 展示以amounts 進行異常值剔除,查看detail結果
# 加載數據
data = [
    [25698744, 5145, 444],
	[ np.nan,  np.nan, 445],
    [25698746, 5156,  446],
    [25698747,  np.nan, 447],
    [ np.nan, 5145, 448],
    [25698749,  np.nan, 9744000000],
    [25698743, 5454, 490],
    [25698743, 5454, 451],
    [25698743, 5454, 454],
    [25698743, 5454, 455],
    [25698743, 5454, 456],
    [25698743, 5454, 453],
    [25698743, 5454, 453],
    [25698743, 5454, 457],
    [25698743, 5454, 457],
    [25698743, 5454, 458]
]

data = pd.DataFrame(data, columns = ['商品id', '類別id', '門店編號'])
print(data.shape)


# 調用函數 進行detail中amount的異常值剔除
bool_num = three_sigma(data.loc[:, '門店編號'])

# 獲取正常的detail
detail = data.loc[bool_num, :]
print(detail.shape)




# 箱線圖分析

# qu %75的數
# ql %25的數
# 1.5 可以稍微調整,,一般使用1.5
# iqr = qu - ql
# 上限:qu + 1.5*iqr
# 下限 :ql - 1.5*iqr

def box_analysis(data):
    '''
    進行箱線圖分析,剔除異常值
    :param data: series
    :return: bool數組
    '''

    qu = data.quantile(0.75)
    ql = data.quantile(0.25)

    iqr = qu - ql

    # 上限
    up = qu + 1.5 * iqr
    # 下限
    low = ql - 1.5 * iqr

    # 進行比較運算
    bool_id_1 = data <= up
    bool_id_2 = data >= low

    bool_num = bool_id_1 & bool_id_2

    return bool_num

bool_num = box_analysis(data.loc[:, '門店編號'])
detail = detail.loc[bool_num, :]
print(detail.shape)

4.3.3 標準化數據

import numpy as np
import pandas as pd

#  標準化數據的目的:將數據轉化爲同一量級,避免量級對結果產生不利的影響
# 數據轉化的三種方式


# 1, 離差標準化 --- (x-min)/ (max-min)
# 將數據轉化爲【0,1】之間
# 容易受到異常點的影響
def deviation(data):
    '''
    離差標準化
    :param data: 傳入數據
    :return: 標準化之後的數據
    '''
    data = (data-data.min()) / (data.max()-data.min())
    return data



# 2,標準差標準化  --- (x-mean)/std
# 轉化完成的數據 - 將數據轉化到標準差爲1,均值爲0的一種狀態
# 容易受到異常值的影響
def stand_sca(data):
    '''
    標準差標準化
    :param data: 傳入數據
    :return: 標準化之後傳出的數據
    '''
    data = (data-data.mean()) / data.std()
    return data


# 3, 小數定標標準化 --- x/10^k
# k -- lg(|x|.max())在向上取整【lg是以10爲低的對數函數】
# 通過移動小數點來使得數據轉化到【-1,1】之間
def desc_sca(data):
    '''
    小數定標標準化
    :param data: 傳入的數據
    :return: 標準化之後的數據
    '''
    data = data / (10**np.ceil(np.log10(data.abs().max())))
    return data


# 加載數據 驗證標準化
data = [
    [25698744, 5145, 444],
	[ np.nan,  np.nan, 445],
    [25698746, 5156,  446],
    [25698747,  np.nan, 447],
    [ np.nan, 5145, 448],
    [25698749,  np.nan, 9744000000],
    [25698743, 5454, 490],
    [25698743, 5454, 451],
    [25698743, 5454, 454],
    [25698743, 5454, 455],
    [25698743, 5454, 456],
    [25698743, 5454, 453],
    [25698743, 5454, 453],
    [25698743, 5454, 457],
    [25698743, 5454, 457],
    [25698743, 5454, 458]
]

data = pd.DataFrame(data, columns = ['商品id', '類別id', '門店編號'])

# 離查標準化
res = deviation(data.loc[:, '門店編號'])
print(res)
print('*-'*40)
# 標準差標準化
res = stand_sca(data.loc[:, '門店編號'])
print(res)
print('*-'*40)
# 小數定標標準化
res = desc_sca(data.loc[:, '門店編號'])
print(res)

# 方法總結:
# 離差標準化方法簡單,便於理解,標準化後的數據限定在[0, 1]區間內。
# 標準差標準化受到數據分佈的影響較小。
# 小數定標標準化方法的適用範圍廣,並且受到數據分佈的影響較小,相比較於前兩種方法而言該方法適用程度適中。

5 數據可視化Matplotlib與Seaborn

5.1 Matplotlib 基礎

Matplotlib是一個Python 2D繪圖庫,它以多種硬拷貝格式和跨平臺的交互式環境生成出版物質量的圖形。Matplotlib 嘗試使容易的事情變得更容易,使困難的事情變得可能。你只需幾行代碼就可以生成圖表、直方圖、功率譜、條形圖、誤差圖、散點圖等。

  • rc參數

pyplot 使用 rc 配置文件來自定義圖形的各種默認屬性,被稱爲 rc 配置或 rc 參數

lines.inewidth 線條寬度 取0-10之間的數值,默認爲1.5。
lines. linestyle 線條樣式 可取 _ __ _. :四種。
lines.marker 線條上點的形狀 可取o D h . , 等
lines.markersize 點的大小 取0-10之間的數值

5.1.1 散點圖

散點圖是指在數據分析中,數據點在直角座標系平面上的分佈圖,參數:

x,y 表示x軸和y軸對應的數據
s 指定點的大小
c 指定點的顏色
marker 表示繪製的點的類型
alpha 接收0-1的小數。表示點的透明度
import numpy as np
from matplotlib import pyplot as plt

# 創建畫布
plt.figure()

# 繪圖

# 構建 x 與 y 座標
x = np.arange(1, 6)

y = np.random.randn(5)

# 繪製散點圖---比折線圖嚴格,x,y維數必須一致
# s  點的大小,可以傳一個,也可以傳一個數組,會從前往後依次使用大小
# c  點的顏色 ,可以傳一個,也可以傳一個array,會從前往後依次使用大小
# marker  點的形狀---,只能傳一個字符串"*"
# alpha  --透明度

plt.scatter(x, y, s = [20, 30, 40, 50, 60, 70], c = ['r', 'g', 'pink', 'y', 'r'], marker = '*',alpha = 1)

plt.show()

5.1.2 折線圖

是一種將數據點按照順序連接起來的圖形,參數

x,y 接收array。表示x軸和y軸對應的數據。無默認
color 接收特定string。指定線條的顏色。默認爲None
linestyle 接收特定string。指定線條類型。默認爲“-”
marker 接收特定string。表示繪製的點的類型。默認爲None
alpha 接收0-1的小數。表示點的透明度。默認爲None
import numpy as np
from matplotlib import pyplot as plt


# # 創建畫布
plt.figure(figsize = (10, 6), dpi = 80)


#支持中文,支持負號:
plt.rcParams['font.sans-serif'] = 'SimHei' #雅黑字體
plt.rcParams['axes.unicode_minus'] = False
# 更多線性、顏色參考網址:
# https://www.cnblogs.com/darkknightzh/p/6117528.html


#準備座標
x = np.arange(-2 * numpy.pi, 2 * numpy.pi, 0.1)

y1 = np.sin(x)
y2 = np.cos(x)

# 獲取座標軸對象
ax = plt.gca()

# 去除上邊 和 右邊的座標邊框
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# 指定的x軸綁定到y軸的某個點上
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))


#繪圖
#常用RC參數設置:
#color 線的顏色
#linestyle  線性
#linewidth 線寬
#marker  點的形狀
#markersize  點的大小
#markerfacecolor 點的填充顏色
#markeredgecolor 點的邊緣顏色

plt.plot(x, y1, color = 'r', linestyle = ':', linewidth = 1.2, marker = "*", markersize = 4, markerfacecolor = 'r', markeredgecolor = 'b')
plt.plot(x, y2)

#修飾圖片【建議全部放在繪圖之後】
#增加標題
plt.title('sin/cos曲線圖')

# 添加縱,橫軸標題
plt.xlabel('X')

plt.ylabel('Y', rotation = 0,horizontalalignment = 'right',verticalalignment = 'top')

# 增加圖例
# loc 圖例位置
plt.legend(['sinx', 'cosx'],loc = 1)


# 設置縱橫座標的刻度
yticks = np.arange(-1.1, 1.1, 0.5) 
xticks= np.arange(-6.6, 6.6, 1)

plt.xticks(xticks)
plt.yticks(yticks)

# 保存圖片
plt.savefig('sinx,cosx曲線圖.png')

# # 圖片顯示
plt.show()

5.1.3 柱狀圖

是一種以長方形的長度爲變量的統計圖表

left 表示x軸數據。
height 表示x軸所代表數據的數量。
width 接收0-1之間的float。指定圖寬度
color 接收特定string或者包含顏色字符串的array
from matplotlib import pyplot as plt

x = ['Q1', 'Q2', 'Q3', 'Q4']
y = [10, 30, 20, 60]

# # 創建畫布
plt.figure(figsize = (10, 6), dpi = 80)

#支持中文,支持負號:
plt.rcParams['font.sans-serif'] = 'SimHei' #雅黑字體
plt.rcParams['axes.unicode_minus'] = False

# rect 是用來接收4個矩陣的變量,裏邊包含了4個矩陣的值
rect = plt.bar(x, y, color = 'g', width = 0.3)

# ind 是指各個矩陣對應的y軸上的值
# get_X可以取出柱子在x上的位置
# get_height() 可以取出柱子的高度
# text()傳入x軸 y軸座標 在對應的位置寫入相應的ind的值若位置稍微有點偏移,
# 那麼可以相應的對_X _Y加0-1 任何一個數值
for ind, item in enumerate(rect):
    _x = item.get_x() + 0.1
    _y = item.get_height() + 0.1
    plt.text(_x, _y, y[ind])

#增加標題
plt.title('柱狀圖')

# 增加網格
plt.grid(True)

# 展示圖片
plt.show()

5.1.4 餅圖

餅圖顯示一個數據系列中各項的大小與各項總和的比例。

x 接收array。表示用於繪製圖的數據。
autopct 指定數值的顯示方式
explode 指定項離餅圖圓心爲n個半徑
pctdistance 指定每一項的比例和距離餅圖圓心n個半徑
labels 指定每一項的名稱。默認
labeldistance 指定每一項的名稱和距離餅圖n個半徑
color 表示餅圖顏色
radius 表示餅圖的半徑
from matplotlib import pyplot as plt

x = ['Q1', 'Q2', 'Q3', 'Q4']
y = [10, 30, 20, 60]
# 基礎圖
plt.pie(y, labels = x)
plt.show()
# 增加比例
plt.axes(aspect = 1)
plt.pie(y, labels = x, autopct = '%2.f%%')
plt.show()
# 突出其中的一塊
plt.axes(aspect = 1)
plt.pie(y, labels = x, autopct = '%2.f%%', explode = [0.2, 0, 0, 0], shadow=True)
plt.show()

5.1.5 直方圖

一種統計報告圖,由一系列高度不等的縱向條紋或線段表示數據分佈的情況。

rwidth 接收0-1之間的float。指定圖寬度
color 接收特定string或者包含顏色字符串的array
alpha 透明度
bins 柱子個數
import numpy as np
from matplotlib import pyplot as plt


np.random.seed(100)
data = np.random.normal(9000, 3000, size = 300)
data = data[data>=5000]
len(data)

plt.hist(data)
plt.show()
# color 指定的是條形的顏色 rwidth 是指 條形的寬度, 默認爲1 alpha 是指透明度
plt.hist(data, color = 'g', rwidth = 0.6 , alpha = 0.6)
plt.show()
# bins代表柱子個數
plt.hist(data, color = 'g', rwidth = 0.6 , alpha = 0.6, bins = 20)
plt.show()

"""
直方圖 與柱狀圖 區別
直方圖:---數據的分佈情況,橫軸是數據範圍,縱軸是落在範圍內的頻數,適用於大數據
柱狀圖:---統計類別數據的數量,橫軸是數據的類別,縱軸是類別的頻數,適用於少量數據,而且類別不宜過多
"""

5.1.6 箱線圖

一種用作顯示一組數據分散情況資料的統計圖。

x 表示用於繪製箱線圖的數據
positions 表示圖形位置
notch 表示中間箱體是否有缺口
widths 表示每個箱體的寬度
sym 指定異常點形狀。
labels 指定每一個箱線圖的標籤
vert 表示圖形是橫向縱向
meanline 表示是否顯示均值線
import numpy as np
from matplotlib import pyplot as plt


data = np.arange(1, 10)


# 繪製簡單的箱線圖
plt.boxplot(data)
plt.show()

# whis: 指定上下邊界 四分位距離, 默認1.5倍四分位差
# 黃線代表的 是中位數
# 黃線上邊的這條線 是上4分位數,下邊的是下四分位數
# 異常值,即上 圖的圓圈
plt.boxplot(data, whis = 3)
plt.show()

# showmeans=True 將均值顯示出來
# meanline=True將均值所在的那條線顯示出來
# showbox=False 盒子消失,默認爲True
plt.boxplot(data , showmeans = True, meanline = True)
plt.show()

5.1.7 子圖


from matplotlib import pyplot as plt
##  子圖

# 注意:其中各個參數也可以用逗號,分隔開。
# 第一個參數代表子圖的行數;第二個參數代表該行圖像的列數; 第三個參數代表每行的第幾個圖像。
# 另外:fig, ax = plt.subplots(2,2),其中參數分別代表子圖的行數和列數,
# 一共有 2x2 個圖像。函數返回一個figure圖像和一個子圖ax的array列表。
plt.subplot(2, 1, 1)
plt.subplot(2, 1, 2)
plt.show()

plt.subplot(3, 1, 1)
plt.subplot(3, 1, 2)
plt.subplot(3, 1, 3)
plt.show()

plt.subplot(2, 2, 1)
plt.subplot(2, 2, 2)
plt.subplot(2, 2, 3)
plt.subplot(2, 2, 4)

plt.subplot(2, 2, 1)
plt.subplot(2, 2, 2)
plt.subplot(2, 1, 2)

# 子圖應用,需要在哪個表格中添加數據 就在哪個表格下邊寫
import pandas as pd
data = [
[1,	'北京',	9240],
[2,	'上海',	8962],
[3,	'深圳',	8315],
[4,	'廣州',	7409],
[5,	'杭州',	7330],
[6,	'寧波',	7000],
[7,	'佛山',	6889],
[8,	'東莞',	6809]]

data = pd.DataFrame(data, columns = ['排名', '城市', '月均工資'])

# 中文亂碼問題
plt.rc('font', **{'family' : 'Microsoft YaHei, SimHei'})

plt.subplot(2, 2, 1)

plt.subplot(2, 2, 1)
plt.plot(data['城市'], data['月均工資'])
plt.show()


#城市與月工資關係圖
data.index = data['城市']
data = data.set_index('城市')
# 第一行第二塊
plt.subplot(2, 2, 2)
plt.bar(data.index, data['月均工資'])
plt.show()


# 月工資
data[['月均工資']].hist()

# 子圖一
plt.subplot(2, 2, 1)
plt.plot(data.index, data['月均工資'])

# 子圖二
plt.subplot(2, 2, 2)
plt.bar(data.index, data['月均工資'])

# 子圖三
plt.subplot(2, 1, 2)
plt.bar(data.index, data['月均工資'])
plt.show()

5.1.8 matplotlib顏色 —— cmap

cmap也就是colormap,可以理解爲接受一個數值,輸出一個指定的顏色的字典。我們可以很方便的給多組數據自動分配色彩,下面是一些cmap的參數。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-a1GxZDsn-1574825287658)(image/1574069367585.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-K6VSbtxp-1574825287658)(image/1574069405037.png)]

在代碼中使用cmap。

import matplotlib.pyplot as plt
import numpy as np

n = 1024  # data size
X = np.random.normal(0, 1, n)  # 每一個點的X值,平均數是0,方差是1
Y = np.random.normal(0, 1, n)  # 每一個點的Y值

# 這裏我們每個點的顏色和該點的X值+Y值的和相關
color = X + Y

# 使用我們上面說的灰度圖 【我們在使用時,直接copy下面的代碼就可以了,只要改變你需要參數】
cmap = plt.get_cmap('brg')
# cmap = plt.cm.Greys #也可以這麼寫
# 利用normlize來標準化顏色的值
norm = plt.Normalize(vmin=-3, vmax=3)

# 散點圖
plt.scatter(X, Y, s=75, alpha=0.5, c=color, cmap=cmap, norm=norm)

plt.xlim(-1.5, 1.5)
plt.xticks(())  # ignore xticks
plt.ylim(-1.5, 1.5)
plt.yticks(())  # ignore yticks

plt.show()

5.1.9 總結

主要是二維圖像的繪圖,也可以繪製少量的三維圖像matplotlib源代碼1 matplotlib源代碼2
1.折線圖,在時間間隔相等的情況下,查看數據的變化與趨勢
2.柱狀圖,有條形不等的柱子表示數據的分佈情況,在不同時間和不同條件下查看兩個或者兩個以上的值
4.分箱圖,表示數據的分佈和堆疊情況,或者使用顏色的深淺表示數據的大小
5.散點圖,數據點在直角座標系中的分佈情況,因變量隨自變量的變化趨勢,分類算法中對不同數據進行區分
6.並狀圖,每一項大小和總和中的比例,對比分析中使用
7.直方圖,表示數據的分佈情況,x數據類型,y分佈情況
8.箱線圖,用於數據清理,對於上下邊界以外的值標記成異常

5.2 Matplotlib 進階 —— Seaborn

Seaborn其實是在matplotlib的基礎上進行了更高級的封裝,從而使得作圖更加容易,在大多數情況下使用seaborn就能做出很具有吸引力的圖。所以說Seaborn是matplotlib的補充,而不是替代物。

**Seaborn 框架旨在以數據可視化爲中心來挖掘與理解數據。它提供的面向數據集製圖函數,主要是對行列索引和數組的操作,包含對整個數據集進行內部的語義映射與統計整合,以此生成富於信息的圖表。**版本【0.9.0】

5.2.1 安裝SeaBorn與繪圖

pip install seaborn

Seaborn 要求原始數據的輸入類型爲 pandas 的 Dataframe 或 Numpy 數組,畫圖函數有以下幾種形式:

sns.圖名(x='X軸 列名', y='Y軸 列名', data=原始數據df對象)
sns.圖名(x='X軸 列名', y='Y軸 列名', hue='分組繪圖參數', data=原始數據df對象)
sns.圖名(x=np.array, y=np.array[, ...])

5.2.2 主題風格與顯示格式

  • seaborn的五種主題風格
    • darkgrid(灰色網格)
    • whitegrid(白色網格)
    • dark(黑色)
    • white(白色)
    • ticks(十字叉)
sns.set_style("dark")   # 通過此方式來修改格
  • 子圖風格

當需要畫子圖,但是想讓子圖有不同風格時,可以用with域

s = pd.Series(np.random.randn(1000))
with sns.axes_style('darkgrid'):
    plt.subplot(211)
    plt.hist(s)
with sns.axes_style('white'):
    plt.subplot(212)
    plt.hist(s)
  • 圖形大小

    • paper-圖形相對較大【精度較大】,默認,
    • talk-次之
    • poster - 最小
sns.set_context('paper')

5.2.3 繪圖

  • 直方圖,折線圖與密度圖
# 我們在分析一組數據時,首先要看的就是變量的分佈規律,而直方圖則提供了簡單快速的方式,在 Seaborn 中可以用 distplot() 實現。

import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

# 生成1000個點的符合正態分佈的隨機數
s1 = pd.Series(np.random.randn(1000))

# hist直方圖,kde折線圖,均默認爲True,rug是在最下方顯示出頻率情況[密度圖],默認爲False
sns.distplot(s1, hist= True, kde= True, rug= True)

# 表示等分爲20份的效果,同樣有label等等參數
bins = 20

# shade表示線下顏色爲陰影,color表示顏色是紅色
sns.kdeplot(s1, shade= True, color= 'r')
  • 柱狀圖
#利用矩陣條的高度反映數值變量的集中趨勢,使用 barplot() 實現。
import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

y = pd.Series(np.arange(12, 22, 2))
x = pd.Series(np.arange(5))

#x,y標識軸座標,orde顯示順序,color顏色
sns.barplot(x, y, order= [3, 1, 4, 2, 0], color= 'r')
  • 計數圖
# 顯示每個類別中的具體觀察數量時,countplot 很容易實現,比較類似我們在 Excel 等軟件中應用的條形圖。
import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

data = [
    [25698744, 5145, 446],
    [454445,  54, 445],
    [25698746, 5156,  446],
    [25698747,  44, 447],
    [44, 5145, 448],
    [25698749,  4554, 940],
    [25698743, 5454, 490],
    [25698743, 5454, 454],
    [25698743, 5454, 454],
    [25698743, 5454, 455],
    [25698743, 5454, 456],
    [25698743, 5454, 454],
    [25698743, 5454, 453],
    [25698743, 5454, 457],
    [25698743, 5454, 457],
    [25698743, 5454, 457]
]

data = pd.DataFrame(data, columns = ['商品id', '類別id', '店鋪編號'])
print(data.shape)

titanic=data['店鋪編號']

sns.countplot(titanic)
  • 散點圖
# 散點圖可以顯示觀察數據的分佈,描述數據的相關性,
import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

# 構造數據
ar=np.random.randn(20, 4)

# 添加列名
df=pd.DataFrame(ar, columns= ['a', 'b', 'c', 'd'])
print(df)
# 以a,b列的數據繪圖,
# hue:對輸入數據進行分組的序列,使用不同顏色對各組的數據加以區分
# style 點的形狀
# 分組的序列的數據量必須與繪圖的數據量相同,否則,繪圖不完整【缺少數據】
df['e']=pd.Series(['one','one','one','one','one','one','two','two','two','two','two','two','two','two','three','three','three','three','three','three'])
sns.scatterplot(df['a'], df['b'], hue= df['e'], style= df['e'])
  • 箱線圖
# boxplot(箱線圖)是一種用作顯示一組數據分散情況的統計圖。它能顯示出一組數據的最大值、最小值、中位數、上下四分位數以及異常值。

import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline


# 構造數據
ar=np.random.randn(20,4)
df=pd.DataFrame(ar,columns=['a','b','c','d'])


# 設置圖片大小
plt.figure(figsize=(12,8))

# 子圖一
with sns.axes_style('dark'):
    plt.subplot(221)
    sns.boxplot(data = df['c'])
# 子圖二
with sns.axes_style('darkgrid'):
    plt.subplot(222)
    sns.boxplot(data = df['b'])
  • 小提琴圖
# 小提琴圖其實是箱線圖與核密度圖的結合,箱線圖展示了分位數的位置,小提琴圖則展示了任意位置的密度,通過小提琴圖可以知道哪些位置的密度較高

import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

# 構造數據
ar=np.random.randn(20,4)
df=pd.DataFrame(ar,columns=['a','b','c','d'])

# 設置圖片大小
plt.figure(figsize=(12,8)) 
# 子圖一
with sns.axes_style('darkgrid'):
    plt.subplot(221)
    sns.violinplot(data= df['b'], inner= None) # 不顯示中間的線
    # 將點的分佈顯示到圖中
    sns.swarmplot(data= df['b'], color= 'white') # 散點是白色
# 子圖二
with sns.axes_style('dark'):
    plt.subplot(222)
    sns.violinplot(data= df['c'], color= 'white') # 圖的底色爲白色
  • 迴歸圖
#Seaborn 中利用 regplot() 來進行迴歸,確定線性關係,
import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

# 構造圖形
plt.figure(figsize=(12, 8)) 
#加載數據 tips爲內置數據
tips = sns.load_dataset("tips")

# x爲總花費,y爲小費,data爲數據集
sns.regplot(x= "total_bill",y="tip", data= tips)
  • 熱力圖
import numpy as np  
import pandas as pd
import seaborn as sns  
import matplotlib.pyplot as plt 
# 如果Jupyter顯示不出圖像加上
%matplotlib inline

# 構造數據,
data = np.random.rand(100, 100)
# 繪圖  center可以改變色值
sns.heatmap(data, center= 1)


# 載入內置數據集
flights = sns.load_dataset('flights')
flights.head()

# pivot() 可以將dataframe轉換爲行列式矩陣 並指定每個元素的存儲值
flights = flights.pivot(index= 'month', columns= 'year',  values= 'passengers')
# 圖片大小
plt.figure(figsize=(10, 6))

# fmt設置字體模式  linewidth設置每個小方格的間距 線寬,cmap修改顏色模式
sns.heatmap(flights, fmt= 'd', linewidths= .5, cmap= 'YlGnBu')

5.2.4 總結

數據可視化一般是通過較底層的 Matplotlib 庫和較高層的 Seaborn 庫實現的,seaborn封裝了matplotlib,所以

seaborn通過更少的代碼,實現更加使用的圖。seaborn源代碼

6 項目實戰 — 服務器日誌分析

日誌分析源代碼

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 加載數據
df = pd.read_csv('./log.txt', header = None, sep = '\t')
df.head()

# 列名添加
df.columns = ['id', 'api', 'count', 'res_time_sum', 'res_time_min', 'res_time_max', 'res_time_avg', 'interval', 'created_at']

# 隨機採樣,多次執行,數據不一樣,看大概
df.sample(5) 

# 查看內存佔用空間
df.info() 

# 優化內存, 指定axis,指定刪除一列
df['api'].describe()
df = df.drop('api', axis = 1) 


df['created_at'].describe()


df[(df.created_at >= '2019-05-01') & (df.created_at < '2019-05-02')]
# 當前索引
df.index

# 設置索引
df.index = df['created_at']

# 轉化爲pd時間序列
df.index = pd.to_datetime(df.created_at)

# 篩選繪圖數據
df.interval.unique()
df = df.drop(['id', 'interval'], axis = 1)
df.head()

df['count'].hist()  # 初步分析count,直方圖
plt.show()

# 表示接口調用分佈情況,大部分都在10次以內  ,反映出每分鐘調用的次數分佈情況
df['count'].hist(bins = 30)
plt.show()

# 切出一天的數據,繪製一天時段的接口調用情況
df['2019-5-1']['count'].plot()
plt.show()

# 凌晨時間無人訪問, 下午2,3點第一個訪問高峯,晚上,8,9點,第二個訪問高峯
# 用count重採樣,用一個小時進行採樣,沒那麼多數據點了,圖像比較平滑
df2 = df['2019-5-1']
df2 = df2[['count']].resample('1H').mean()
df2['count'].plot()
plt.show()


## 折線圖和直方圖, 可以看到業務的高峯時段在什麼地方, 分不清具體時間,繪製柱狀圖
plt.figure(figsize = (10, 3))  # 單位是英寸
df2['count'].plot(kind = 'bar')
plt.xticks(rotation = 60)  # 文字旋轉角度
plt.show()


# 分析有沒有異常時段,訪問接口過於頻繁,可能就是黑客潮水攻擊
df['2019-5-1'][['count']].boxplot(showmeans = True, meanline = True)
plt.show()

df[df['count'] > 20]

# 某一天的響應時間,平均響應時間
df['2019-5-1']['res_time_avg'].plot()
df['2019-5-1'][['res_time_avg']].boxplot()
df2 = df['2019-5-1']
df2[df['res_time_avg'] > 1000] 
# 2019-05-01 00:34:48	1	1694.47	1694.47	1694.47	1694.0	2019-05-01 00:34:48 定義爲異常值
df['2019-5-1'][['res_time_sum',	'res_time_min',	'res_time_max',	'res_time_avg']].plot()
plt.show()

# 業務高峯時段 下午2-3點,晚上7-8點,響應時間都是上升的
data = df['2019-5-1'].resample('20T').mean()
data[['res_time_sum',	'res_time_min',	'res_time_max',	'res_time_avg']].plot()
plt.show()

## 每天的情況都差不多,下面看看週末和平常是不是一樣的
df['2019-5-1' : '2019-5-10']['count'].plot()
plt.show()

 # 0 代表星期一,  1 代表星期二 ,  5,6分別代表週六和週日 查看數據
df['2019-5-2'].index.weekday 
df['weekday'] = df.index.weekday
df.head(2)

# 判斷是否是週末 ,是不是5,6
df['weekend'] = df['weekday'].isin({5, 6})
df.head(5)
# 對weekend 進行分組, 對count列 求平均值
df.groupby('weekend')['count'].mean()


# 週末調用平均次數多,7.57,  
# 週末哪個時段調用次數比較高
df.groupby(['weekend', df.index.hour])['count'].mean()

# 週末和非週末,具體時間對比, 繪製成圖形,否則不直觀
df.groupby(['weekend', df.index.hour])['count'].mean().plot()
plt.show()

# 週末和非週末數據疊加
df.groupby(['weekend', df.index.hour])['count'].mean().unstack(level = 0)
df.groupby(['weekend', df.index.hour])['count'].mean().unstack(level = 0).plot()
plt.show()
發佈了5 篇原創文章 · 獲贊 162 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章