Pandas的介紹與基本使用

一、什麼是Pandas

當你們談論到數據分析時,說起最多的語言就是Python和SQL,而Python之因此適合作數據分析,就是由於他有不少強大的第三方庫來協助,pandas就是其中之一,它是基於Numpy構建的,正因pandas的出現,讓Python語言也成爲使用最普遍並且強大的數據分析環境之一。若是說沒有pandas的出現,目前的金融數據分析領域還應該是R語言的天下。html

二、Pandas能幹什麼

Pandas的主要功能:python

  • 具有對應其功能的數據結構DataFrame,Series
  • 集成時間序列功能
  • 提供豐富的數學運算和操做
  • 靈活處理缺失數據
  • .....

以上就是pandas能完成的一些基礎操做,固然並不徹底,下面就來看看pandas究竟是怎麼用的。數組

三、怎麼用Pandas

安裝方法:數據結構

pip install pandasapp

引用方法:dom

import pandas as pd函數

3.一、Series

Series是一種相似於一維數組的對象,由一組數據和一組與之相關的數據標籤(索引)組成。在數據分析的過程當中很是經常使用。學習

3.1.一、建立方法

第一種:
pd.Series([4,5,6,7,8])
執行結果:
0    4
1    5
2    6
3    7
4    8
dtype: int64
# 將數組索引以及數組的值打印出來,索引在左,值在右,因爲沒有爲數據指定索引,因而會自動建立一個0到N-1(N爲數據的長度)的整數型索引,取值的時候能夠經過索引取值,跟以前學過的數組和列表同樣
-----------------------------------------------
第二種:
pd.Series([4,5,6,7,8],index=['a','b','c','d','e'])
執行結果:
a    4
b    5
c    6
d    7
e    8
dtype: int64
# 自定義索引,index是一個索引列表,裏面包含的是字符串,依然能夠經過默認索引取值。
-----------------------------------------------
第三種:
pd.Series({"a":1,"b":2})
執行結果:
a    1
b    2
dtype: int64
# 指定索引
-----------------------------------------------
第四種:
pd.Series(0,index=['a','b','c'])
執行結果:
a    0
b    0
c    0
dtype: int64
# 建立一個值都是0的數組
-----------------------------------------------

對於Series,其實咱們能夠認爲它是一個長度固定且有序的字典,由於它的索引和數據是按位置進行匹配的,像咱們會使用字典的上下文,就確定也會使用Series測試

3.1.二、缺失數據

  • dropna() # 過濾掉值爲NaN的行
  • fillna() # 填充缺失數據
  • isnull() # 返回布爾數組,缺失值對應爲True
  • notnull() # 返回布爾數組,缺失值對應爲False
# 第一步,建立一個字典,經過Series方式建立一個Series對象

st = {"sean":18,"yang":19,"bella":20,"cloud":21}
obj = pd.Series(st)
obj
運行結果:
sean     18
yang     19
bella    20
cloud    21
dtype: int64
------------------------------------------
# 第二步
a = {'sean','yang','cloud','rocky'}  # 定義一個索引變量
------------------------------------------
#第三步
obj1 = pd.Series(st,index=a)
obj1  # 將第二步定義的a變量做爲索引傳入

# 運行結果:
rocky     NaN
cloud    21.0
sean     18.0
yang     19.0
dtype: float64
# 由於rocky沒有出如今st的鍵中,因此返回的是缺失值

經過上面的代碼演示,對於缺失值已經有了一個簡單的瞭解,接下來就來看看如何判斷缺失值url

一、
obj1.isnull()  # 是缺失值返回Ture
運行結果:
rocky     True
cloud    False
sean     False
yang     False
dtype: bool

二、
obj1.notnull()  # 不是缺失值返回Ture
運行結果:
rocky    False
cloud     True
sean      True
yang      True
dtype: bool

三、過濾缺失值 # 布爾型索引
obj1[obj1.notnull()]
運行結果:
cloud    21.0
yang     19.0
sean     18.0
dtype: float64

3.1.三、Series特性

import numpy as np
import pandas as pd
  • 從ndarray建立Series:Series(arr)
arr = np.arange(10)

sr = pd.Series(arr)  # ndarray建立Series
  • 與標量(數字)進行運算:sr * 2
srx = sr * 2  # 與標量(數字)進行運算
  • 兩個Series運算
sr * srx  # 兩個Series運算
  • 布爾值過濾:sr[sr>0]
sr[sr>3]  # 布爾值過濾
  • 統計函數:mean()、sum()、cumsum()
# 統計函數
sr.mean()
sr.sum()
sr.cumsum()

3.1.四、支持字典的特性

  • 從字典建立Series:Series(dic),
dic = {"A":1,"B":2,"C":3,"D":4,"E":5}

# 字典建立Series
dic_arr = pd.Series(dic)
  • In運算:'a'in sr、for x in sr
"A" in dic_arr
------------------------------
for i in dic_arr: 
    print(i)
  • 鍵索引:sr['a'],sr[['a','b','d']]
dic_arr[['A','B']]  # 鍵索引
  • 鍵切片:sr['a':'c']
dic_arr['A':'C']  # 鍵切片
  • 其餘函數:get('a',default=0)等
dic_arr.get("A",default=0)

3.1.五、整數索引

pandas當中的整數索引對象可能會讓初次接觸它的人很懵逼,接下來經過代碼演示:

sr = pd.Series(np.arange(10))
sr1 = sr[3:].copy()
sr1
運行結果:
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int32
# 到這裏會發現很正常,一點問題都沒有,但是當使用整數索引取值的時候就會出現問題了。由於在pandas當中使用整數索引取值是優先以標籤解釋的,而不是下標
sr1[1]

解決方法:

  • loc屬性 # 以標籤解釋
  • iloc屬性 # 如下標解釋
sr1.iloc[1]  # 如下標解釋

sr1.loc[3]  # 以標籤解釋

3.1.六、Series數據對齊

pandas在運算時,會按索引進行對齊而後計算。若是存在不一樣的索引,則結果的索引是兩個操做數索引的並集。

sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a',])
sr1 + sr2
運行結果:
a    33
c    32
d    45
dtype: int64
# 能夠經過這種索引對齊直接將兩個Series對象進行運算
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1 + sr3
運行結果:
a    33.0
b     NaN
c    32.0
d    45.0
dtype: float64
# sr1 和 sr3的索引不一致,因此最終的運行會發現b索引對應的值沒法運算,就返回了NaN,一個缺失值

將兩個Series對象相加時將缺失值設爲0:

sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1.add(sr3,fill_value=0)
運行結果:
a    33.0
b    14.0
c    32.0
d    45.0
dtype: float64
# 將缺失值設爲0,因此最後算出來b索引對應的結果爲14

靈活的算術方法:add,sub,div,mul

到這裏可能就會說了pandas就這麼簡單嗎,那咱們接下來一塊兒看看這個二維數組DataFraeme

3.二、DataFrame

DataFrame是一個表格型的數據結構,至關因而一個二維數組,含有一組有序的列。他能夠被看作是由Series組成的字典,而且共用一個索引。接下來就一塊兒來見識見識DataFrame數組的厲害吧!!!

3.2.一、建立方式

建立一個DataFrame數組能夠有多種方式,其中最爲經常使用的方式就是利用包含等長度列表或Numpy數組的字典來造成DataFrame:

第一種:
pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
# 產生的DataFrame會自動爲Series分配所索引,而且列會按照排序的順序排列
運行結果:
    one two
0   1   4
1   2   3
2   3   2
3   4   1

> 指定列
能夠經過columns參數指定順序排列
data = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame(data,columns=['one','two'])

# 打印結果會按照columns參數指定順序


第二種:
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
運行結果:
   one  two
a   1   2
b   2   1
c   3   3

以上建立方法簡單瞭解就能夠,由於在實際應用當中更可能是讀數據,不須要本身手動建立

3.2.二、查看數據

經常使用屬性和方法:

  • index 獲取行索引
  • columns 獲取列索引
  • T 轉置
  • values 獲取值索引
  • describe 獲取快速統計
one    two
a   1   2
b   2   1
c   3   3
# 這樣一個數組df
---------------------------------------------------------------------------
df.index

> Index(['a', 'b', 'c'], dtype='object')
---------------------------------------------------------------------------
df.columns

> Index(['one', 'two'], dtype='object')
--------------------------------------------------------------------------
df.T

>    a  b   c
one 1   2   3
two 2   1   3

-------------------------------------------------------------------------
df.values

> array([[1, 2],
       [2, 1],
       [3, 3]], dtype=int64)
------------------------------------------------------------------------
df.describe()

>       one two
count   3.0 3.0   # 數據統計
mean    2.0 2.0   # 平均值
std     1.0 1.0   # 標準差
min     1.0 1.0   # 最小值
25%     1.5 1.5   # 四分之一均值
50%     2.0 2.0   # 二分之一均值
75%     2.5 2.5   # 四分之三均值
max     3.0 3.0   # 最大值

3.2.三、索引和切片

  • DataFrame有行索引和列索引。
  • DataFrame一樣能夠經過標籤和位置兩種方法進行索引和切片。

DataFrame使用索引切片:

  • 方法1:兩個中括號,不管是先取行仍是先取列均可以。
import tushare as ts

data = ts.get_k_data("000001")

data['open'][:10]  # 先取列再取行
data[:10]['open']  # 先取行再取列
  • 方法2(推薦):使用loc/iloc屬性,一箇中括號,逗號隔開,先取行再取列。
    • loc屬性:解釋爲標籤
    • iloc屬性:解釋爲下標
data.loc[:10,"open":"low"]  # 用標籤取值

data.iloc[:10,1:5]  # 用下標取值
  • 向DataFrame對象中寫入值時只使用方法2
  • 行/列索引部分能夠是常規索引、切片、布爾值索引、花式索引任意搭配。(注意:兩部分都是花式索引時結果可能與預料的不一樣)

3.三、時間對象處理

處理時間對象多是咱們在進行數據分析的過程中最多見的,咱們會遇到各類格式的時間序列,也須要處理各類格式的時間序列,可是必定不能對這些數據懵逼,咱們須要找到最合適的招式來處理這些時間。接下來就一塊兒來看吧!!!

3.3.一、時間序列類型

  • 時間戳:特定時刻
  • 固定時期:如2019年1月
  • 時間間隔:起始時間-結束時間

3.3.二、Python庫:datatime

  • date、datetime、timedelta
import datetime

# datetime.date()  # date對象

today = datetime.date.today()  # 獲取當天日期,返回date對象
t1 = datetime.date(2019,4,18) # 設置時間格式爲datetime.date

# datetime.datetime()  # datetime對象

now = datetime.datetime.now()  # 獲取當天日期,返回datetime對象
t2 = datetime.datetime(2019,4,18) # 設置時間格式爲datetime.datetime

# datetime.timedelta()  # 時間差

today = datetime.datetime.today()
yestoday = today - datetime.timedelta(1)  # 以時間作運算
print(today,yestoday)
  • dt.strftime()
# 將時間格式轉換爲字符串
today.strftime("%Y-%m-%d")
yestoday.strftime("%Y-%m-%d")
  • strptime()
# 將日期字符串轉成datetime時間格式,第二個參數由時間格式決定
datetime.datetime.strptime('2019-04-18','%Y-%m-%d')

3.3.三、靈活處理時間對象:dateutil包

  • dateutil.parser.parse()
import dateutil

# 將字符串格式的日期轉換爲datetime對象
date = '2019 Jan 2nd'
t3 = dateutil.parser.parse(date)

3.3.四、成組處理時間對象:pandas

  • pd.to_datetime(['2018-01-01', '2019-02-02'])

將字符串轉換爲爲時間對象

from datetime import datetime
import pandas as pd

date1 = datetime(2019, 4, 18, 12, 24, 30)
date2 = '2019-04-18'
t4 = pd.to_datetime(date1)
t5 = pd.to_datetime(date2)
t6 = pd.to_datetime([date1,date2])

t4,t5,t6  # 轉換單個時間數據是返回Timestamp對象,轉換多個時間數據返回DatetimeIndex對象
> 
"""
(Timestamp('2019-04-18 12:24:30'),
 Timestamp('2019-04-18 00:00:00'),
 DatetimeIndex(['2019-04-18 12:24:30', '2019-04-18 00:00:00'], dtype='datetime64[ns]', freq=None))
"""

將索引設置爲時間序列

ind = pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
sr = pd.Series([1,2,3],index=ind)

# 補充:
"""
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019']).to_pydatetime()

> array([datetime.datetime(2018, 3, 1, 0, 0),
       datetime.datetime(2019, 2, 3, 0, 0),
       datetime.datetime(2019, 8, 12, 0, 0)], dtype=object)
# 經過to_pydatetime()方法將其轉換爲ndarray數組
"""

3.3.五、產生時間對象數組:data_range

  • start 開始時間
  • end 結束時間
  • periods 時間長度
  • freq 時間頻率,默認爲'D',可選H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…
pd.date_range("2019-1-1","2019-2-2",freq="D")

> DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
               '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
               '2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12',
               '2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16',
               '2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20',
               '2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24',
               '2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28',
               '2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01',
               '2019-02-02'],
              dtype='datetime64[ns]', freq='D')

3.3.六、時間序列

時間序列就是以時間對象爲索引的Series或DataFrame。datetime對象做爲索引時是存儲在DatetimeIndex對象中的。

# 轉換時間索引
dt = pd.date_range("2019-01-01","2019-02-02")
# 生成一個帶有時間數據的DataFrame數組
a = pd.DataFrame({"num":pd.Series(random.randint(-100,100) for _ in range(30)),"date":dt})
# 經過index修改索引
a.index = pd.to_datetime(a["date"])

特殊功能:

  • 傳入「年」或「年月」做爲切片方式
  • 傳入日期範圍做爲切片方式
  • 豐富的函數支持:resample(), strftime(), ……
a.resample("3D").mean()  # 計算每三天的均值
a.resample("3D").sum()  #  計算每三天的和
...

時間序列的處理在數據分析當中很是重要,可是有時候時間的格式不一致又會讓人很是煩躁,只要把以上祕籍都學會就能夠把時間序列製得服服帖帖。

3.四、數據分組和聚合

在數據分析當中,咱們有時須要將數據拆分,而後在每個特定的組裏進行運算,這些操做一般也是數據分析工做中的重要環節。
分組聚合相對來講也是一個稍微難理解的點,須要各位有必定的功力來學習.

3.4.一、分組(GroupBY機制)

pandas對象(不管Series、DataFrame仍是其餘的什麼)當中的數據會根據提供的一個或者多個鍵被拆分爲多組,拆分操做實在對象的特定軸上執行的。就好比DataFrame能夠在他的行上或者列上進行分組,而後將一個函數應用到各個分組上併產生一個新的值。最後將全部的執行結果合併到最終的結果對象中。

img

分組鍵能夠是多種樣式,而且鍵不必定是徹底相同的類型:

  • 列表或者數組,長度要與待分組的軸同樣
  • 表示DataFrame某個列名的值。
  • 字典或Series,給出待分組軸上的值與分組名之間的對應關係
  • 函數,用於處理軸索引或者索引中的各個標籤

後三種只是快捷方式,最終仍然是爲了產生一組用於拆分對象的值。

首先,經過一個很簡單的DataFrame數組嘗試一下:

df = pd.DataFrame({'key1':['x','x','y','y','x',                               
            'key2':['one','two','one',',two','one'],
            'data1':np.random.randn(5),
            'data2':np.random.randn(5)})
df
                           
>   key1    key2    data1   data2
0   x   one 0.951762    1.632336
1   x   two -0.369843   0.602261
2   y   one 1.512005    1.331759
3   y   two 1.383214    1.025692
4   x   one -0.475737   -1.182826

訪問data1,並根據key1調用groupby:

f1 = df['data1'].groupby(df['key1'])
f1

> <pandas.core.groupby.groupby.SeriesGroupBy object at 0x00000275906596D8>

上述運行是沒有進行任何計算的,可是咱們想要的中間數據已經拿到了,接下來,就能夠調用groupby進行任何計算

f1.mean()  # 調用mean函數求出平均值
> key1
    x    0.106183
    y    2.895220
    Name: data1, dtype: float64

以上數據通過分組鍵(一個Series數組)進行了聚合,產生了一個新的Series,索引就是key1列中的惟一值。這些索引的名稱就爲key1。接下來就嘗試一次將多個數組的列表傳進來

f2 = df['data1'].groupby([df['key1'],df['key2']])
f2.mean()
> key1  key2
    x     one     0.083878
          two     0.872437
    y     one    -0.665888
          two    -0.144310
    Name: data1, dtype: float64

傳入多個數據以後會發現,獲得的數據具備一個層次化的索引,key1對應的x\y;key2對應的one\two.

f2.mean().unstack()  # 經過unstack方法就可讓索引不堆疊在一塊兒了

> key2  one     two
key1        
x   0.083878    0.872437
y   -0.665888   -0.144310

補充:

  • 一、分組鍵能夠是任意長度的數組
  • 二、分組時,對於不是數組數據的列會從結果中排除,例如key一、key2這樣的列
  • 三、GroupBy的size方法,返回一個含有分組大小的Series
# 以上面的f2測試
f2.size()
> key1  key2
x     one     2
      two     1
y     one     1
      two     1
Name: data1, dtype: int64

到這跟着我上面的步驟一步一步的分析,會發現仍是很簡單的,可是必定不能幹看,還要本身下手練,只有多練才能融匯貫通!!!

3.4.二、聚合(組內應用某個函數)

聚合是指任何可以從數組產生標量值的數據轉換過程。剛纔上面的操做會發現使用GroupBy並不會直接獲得一個顯性的結果,而是一箇中間數據,能夠經過執行相似mean、count、min等計算得出結果,常見的還有一些:

函數名 描述
sum 非NA值的和
median 非NA值的算術中位數
std、var 無偏(分母爲n-1)標準差和方差
prod 非NA值的積
first、last 第一個和最後一個非NA值

自定義聚合函數

不只可使用這些經常使用的聚合運算,還能夠本身自定義。

# 使用自定義的聚合函數,須要將其傳入aggregate或者agg方法當中

def peak_to_peak(arr):
    return arr.max() - arr.min()
f1.aggregate(peak_to_peak)
運行結果:
key1
x    3.378482
y    1.951752
Name: data1, dtype: float64

多函數聚合:

f1.agg(['mean','std'])
運行結果:
    mean    std
key1        
x   -0.856065   0.554386
y   -0.412916   0.214939

最終獲得的列就會以相應的函數命名生成一個DataFrame數組

以上咱們是能夠經過agg或者是aggregate來實現多函數聚合以及自定義聚合函數,可是必定要注意agg方法只能進行聚合操做,進行其餘例如:排序,這些方法是會報錯的。agg返回的是數據的標量,因此有些時候並不適合使用agg,這就要看咱們接下來的操做了。

3.4.三、apply

GroupBy當中自由度最高的方法就是apply,它會將待處理的對象拆分爲多個片斷,而後各個片斷分別調用傳入的函數,最後將它們組合到一塊兒。

df.apply(
['func', 'axis=0', 'broadcast=None', 'raw=False', 'reduce=None', 'result_type=None', 'args=()', '**kwds']

func:傳入一個自定義函數
axis:函數傳入參數當axis=1就會把一行數據做爲Series的數據

# 分析歐洲盃和歐洲冠軍聯賽決賽名單
import pandas as pd

url="https://en.wikipedia.org/wiki/List_of_European_Cup_and_UEFA_Champions_League_finals"
eu_champions=pd.read_html(url)  # 獲取數據
a1 = eu_champions[2]    # 取出決賽名單
a1.columns = a1.loc[0]  # 使用第一行的數據替換默認的橫向索引
a1.drop(0,inplace=True)  # 將第一行的數據刪除
a1.drop('#',axis=1,inplace=True)  # 將以#爲列名的那一列刪除
a1.columns=['Season', 'Nation', 'Winners', 'Score', 'Runners_up', 'Runners_up_Nation', 'Venue','Attendance']  # 設置列名

a1.tail()  # 查看後五行數據
a1.drop([64,65],inplace=True)  # 刪除其中的缺失行以及無用行
a1

運行結果:

分組apply1

如今想根據分組選出Attendance列中值最高的三個。

# 先自定義一個函數
def top(df,n=3,column='Attendance'):
    return df.sort_values(by=column)[-n:]
top(a1,n=3)

運行結果:

分組apply2

接下來,就對a1分組而且使用apply調用該函數:

a1.groupby('Nation').apply(top)

分組apply3

運行以後會發現,咱們經過這個操做將每一個國家各個年份時段出席的人數的前三名進行了一個提取。

以上top函數是在DataFrame的各個片斷上調用,而後結果又經過pandas.concat組裝到一塊兒,而且以分組名稱進行了標記。

以上只是基本用法,apply的強大之處就在於傳入函數能作什麼都由本身說了算,它只是返回一個pandas對象或者標量值就行

3.五、其餘經常使用方法

pandas經常使用方法(適用Series和DataFrame)

  • mean(axis=0,skipna=False)
  • sum(axis=1)
  • sort_index(axis, …, ascending) # 按行或列索引排序
  • sort_values(by, axis, ascending) # 按值排序
  • apply(func, axis=0) # 將自定義函數應用在各行或者各列上,func可返回標量或者Series
  • applymap(func) # 將函數應用在DataFrame各個元素上
  • map(func) # 將函數應用在Series各個元素上
相關文章
相關標籤/搜索