當前位置:
首頁 > 知識 > Python 數據處理庫 pandas 入門教程

Python 數據處理庫 pandas 入門教程

(點擊

上方公眾號

,可快速關注)




來源:強波的技術博客


http://qiangbo.space/2018-02-15/pandas_tutorial/




pandas是一個Python語言的軟體包,在我們使用Python語言進行機器學習編程的時候,這是一個非常常用的基礎編程庫。本文是對它的一個入門教程。


pandas提供了快速,靈活和富有表現力的數據結構,目的是使「關係」或「標記」數據的工作既簡單又直觀。它旨在成為在Python中進行實際數據分析的高級構建塊。


入門介紹


pandas適合於許多不同類型的數據,包括:




  • 具有異構類型列的表格數據,例如SQL表格或Excel數據



  • 有序和無序(不一定是固定頻率)時間序列數據。



  • 具有行列標籤的任意矩陣數據(均勻類型或不同類型)



  • 任何其他形式的觀測/統計數據集。


由於這是一個Python語言的軟體包,因此需要你的機器上首先需要具備Python語言的環境。關於這一點,請自行在網路上搜索獲取方法。


關於如何獲取pandas請參閱官網上的說明:

pandas Installation


通常情況下,我們可以通過

pip

來執行安裝:



sudo pip3 install

pandas




或者通過

conda

 來安裝pandas:





conda install

pandas



目前(2018年2月)pandas的最新版本是v0.22.0(發布時間:2017年12月29日)。


我已經將本文的源碼和測試數據放到Github上: pandas_tutorial ,讀者可以前往獲取。


另外,pandas常常和NumPy一起使用,本文中的源碼中也會用到NumPy。


建議讀者先對NumPy有一定的熟悉再來學習pandas,我之前也寫過一個NumPy的基礎教程,參見這裡:Python 機器學習庫 NumPy 教程


核心數據結構


pandas最核心的就是

Series

DataFrame

兩個數據結構。


這兩種類型的數據結構對比如下:
















名稱

維度

說明

Series

1維

帶有標籤的同構類型數組

DataFrame

2維

表格結構,帶有標籤,大小可變,且可以包含異構的數據列


DataFrame可以看做是Series的容器,即:一個DataFrame中可以包含若干個Series。



註:在0.20.0版本之前,還有一個三維的數據結構,名稱為Panel。這也是pandas庫取名的原因:

pan

(el)-

da

(ta)-

s

。但這種數據結構由於很少被使用到,因此已經被廢棄了。


Series


由於Series是一維結構的數據,我們可以直接通過數組來創建這種數據,像這樣:



# data_structure.py


 


import pandas

as

pd


import numpy

as

np


 


series1

=

pd

.

Series

([

1

,

2

,

3

,

4

])


print

(

"series1:
{}
"

.

format

(

series1

))




這段代碼輸出如下:






series1

:


0

    

1


1

    

2


2

    

3


3

    

4


dtype

:

int64




這段輸出說明如下:




  • 輸出的最後一行是Series中數據的類型,這裡的數據都是

    int64

    類型的。



  • 數據在第二列輸出,第一列是數據的索引,在pandas中稱之為

    Index


我們可以分別列印出Series中的數據和索引:



# data_structure.py


 


print

(

"series1.values: {}
"

.

format

(

series1

.

values

))


 


print

(

"series1.index: {}
"

.

format

(

series1

.

index

))




這兩行代碼輸出如下:






series1

.

values

:

[

1

2

3

4

]


 


series1

.

index

:

RangeIndex

(

start

=

0

,

stop

=

4

,

step

=

1

)




如果不指定(像上面這樣),索引是[1, N-1]的形式。不過我們也可以在創建Series的時候指定索引。索引未必一定需要是整數,可以是任何類型的數據,例如字元串。例如我們以七個字母來映射七個音符。索引的目的是可以通過它來獲取對應的數據,例如下面這樣:






# data_structure.py


 


series2

=

pd

.

Series

([

1

,

2

,

3

,

4

,

5

,

6

,

7

],


    

index

=

[

"C"

,

"D"

,

"E"

,

"F"

,

"G"

,

"A"

,

"B"

])


print

(

"series2:
{}
"

.

format

(

series2

))


print

(

"E is {}
"

.

format

(

series2

[

"E"

]))




這段代碼輸出如下:






series2

:


C

    

1


D

    

2


E

    

3


F

    

4


G

    

5


A

    

6


B

    

7


dtype

:

int64


 


E

is

3




DataFrame


下面我們來看一下DataFrame的創建。我們可以通過NumPy的介面來創建一個4×4的矩陣,以此來創建一個DataFrame,像這樣:



# data_structure.py


 


df1

=

pd

.

DataFrame

(

np

.

arange

(

16

).

reshape

(

4

,

4

))


print

(

"df1:
{}
"

.

format

(

df1

))




這段代碼輸出如下:






df1

:


    

0

  

1

  

2

  

3


0

  

0

  

1

  

2

  

3


1

  

4

  

5

  

6

  

7


2

  

8

  

9

  

10

  

11


3

  

12

  

13

  

14

  

15




從這個輸出我們可以看到,默認的索引和列名都是[0, N-1]的形式。


我們可以在創建DataFrame的時候指定列名和索引,像這樣:



# data_structure.py


 


df2

=

pd

.

DataFrame

(

np

.

arange

(

16

).

reshape

(

4

,

4

),


    

columns

=

[

"column1"

,

"column2"

,

"column3"

,

"column4"

],


    

index

=

[

"a"

,

"b"

,

"c"

,

"d"

])


print

(

"df2:
{}
"

.

format

(

df2

))




這段代碼輸出如下:






df2

:


  

column1  column2  column3  

column4


a

        

0

        

1

        

2

        

3


b

        

4

        

5

        

6

        

7


c

        

8

        

9

      

10

      

11


d

      

12

      

13

      

14

      

15




我們也可以直接指定列數據來創建DataFrame:






# data_structure.py


 


df3

=

pd

.

DataFrame

({

"note"

:

[

"C"

,

"D"

,

"E"

,

"F"

,

"G"

,

"A"

,

"B"

],


    

"weekday"

:

[

"Mon"

,

"Tue"

,

"Wed"

,

"Thu"

,

"Fri"

,

"Sat"

,

"Sun"

]})


print

(

"df3:
{}
"

.

format

(

df3

))




這段代碼輸出如下:






df3

:


  

note

weekday


0

    

C

    

Mon


1

    

D

    

Tue


2

    

E

    

Wed


3

    

F

    

Thu


4

    

G

    

Fri


5

    

A

    

Sat


6

    

B

    

Sun




請注意:




  • DataFrame的不同列可以是不同的數據類型



  • 如果以Series數組來創建DataFrame,每個Series將成為一行,而不是一列


例如:



# data_structure.py


 


noteSeries

=

pd

.

Series

([

"C"

,

"D"

,

"E"

,

"F"

,

"G"

,

"A"

,

"B"

],


    

index

=

[

1

,

2

,

3

,

4

,

5

,

6

,

7

])


weekdaySeries

=

pd

.

Series

([

"Mon"

,

"Tue"

,

"Wed"

,

"Thu"

,

"Fri"

,

"Sat"

,

"Sun"

],


    

index

=

[

1

,

2

,

3

,

4

,

5

,

6

,

7

])


df4

=

pd

.

DataFrame

([

noteSeries

,

weekdaySeries

])


print

(

"df4:
{}
"

.

format

(

df4

))


 


df4的輸出如下:






df4

:


    

1

    

2

    

3

    

4

    

5

    

6

    

7


0

    

C

    

D

    

E

    

F

    

G

    

A

    

B


1

  

Mon  Tue  Wed  Thu  Fri  Sat  

Sun




我們可以通過下面的形式給DataFrame添加或者刪除列數據:






# data_structure.py


 


df3

[

"No."

]

=

pd

.

Series

([

1

,

2

,

3

,

4

,

5

,

6

,

7

])


print

(

"df3:
{}
"

.

format

(

df3

))


 


del

df3

[

"weekday"

]


print

(

"df3:
{}
"

.

format

(

df3

))




這段代碼輸出如下:





df3

:


  

note weekday  

No

.


0

    

C

    

Mon

    

1


1

    

D

    

Tue

    

2


2

    

E

    

Wed

    

3


3

    

F

    

Thu

    

4


4

    

G

    

Fri

    

5


5

    

A

    

Sat

    

6


6

    

B

    

Sun

    

7


 


df3

:


  

note  

No

.


0

    

C

    

1


1

    

D

    

2


2

    

E

    

3


3

    

F

    

4


4

    

G

    

5


5

    

A

    

6


6

    

B

    

7




Index對象與數據訪問


pandas的Index對象包含了描述軸的元數據信息。當創建Series或者DataFrame的時候,標籤的數組或者序列會被轉換成Index。可以通過下面的方式獲取到DataFrame的列和行的Index對象:



# data_structure.py


 


print

(

"df3.columns
{}
"

.

format

(

df3

.

columns

))


print

(

"df3.index
{}
"

.

format

(

df3

.

index

))




這兩行代碼輸出如下:






df3

.

columns


Index

([

"note"

,

"No."

],

dtype

=

"object"

)


 


df3

.

index


RangeIndex

(

start

=

0

,

stop

=

7

,

step

=

1

)




請注意:




  • Index並非集合,因此其中可以包含重複的數據



  • Index對象的值是不可以改變,因此可以通過它安全的訪問數據


DataFrame提供了下面兩個操作符來訪問其中的數據:




  • loc

    :通過行和列的索引來訪問數據



  • iloc

    :通過行和列的下標來訪問數據


例如這樣:




# data_structure.py


 


print

(

"Note C, D is:
{}
"

.

format

(

df3

.

loc

[[

0

,

1

],

"note"

]))


print

(

"Note C, D is:
{}
"

.

format

(

df3

.

iloc

[[

0

,

1

],

0

]))




第一行代碼訪問了行索引為0和1,列索引為「note」的元素。第二行代碼訪問了行下標為0和1(對於df3來說,行索引和行下標剛好是一樣的,所以這裡都是0和1,但它們卻是不同的含義),列下標為0的元素。


這兩行代碼輸出如下:




Note

C

,

D

is

:


0

    

C


1

    

D


Name

:

note

,

dtype

:

object


 


Note

C

,

D

is

:


0

    

C


1

    

D


Name

:

note

,

dtype

:

object




文件操作


pandas庫提供了一系列的

read_

函數來讀取各種格式的文件,它們如下所示:




  • read_csv



  • read_table



  • read_fwf



  • read_clipboard



  • read_excel



  • read_hdf



  • read_html



  • read_json



  • read_msgpack



  • read_pickle



  • read_sas



  • read_sql



  • read_stata



  • read_feather


讀取Excel文件



註:要讀取Excel文件,還需要安裝另外一個庫:

xlrd


通過pip可以這樣完成安裝:



sudo pip3 install

xlrd




安裝完之後可以通過pip查看這個庫的信息:






$

  

pip3 show xlrd


Name

:

xlrd


Version

:

1.1.0


Summary

:

Library

for

developers

to

extract data from Microsoft Excel

(

tm

)

spreadsheet files


Home

-

page

:

http

:

//www.python-excel.org/


Author

:

John Machin


Author

-

email

:

sjmachin

@

lexicon

.

net


License

:

BSD


Location

: /

Library

/

Frameworks

/

Python

.

framework

/

Versions

/

3.6

/

lib

/

python3

.

6

/

site

-

packages


Requires

:




接下來我們看一個讀取Excel的簡單的例子






# file_operation.py


 


import pandas

as

pd


import numpy

as

np


 


df1

=

pd

.

read_excel

(

"data/test.xlsx"

)


print

(

"df1:
{}
"

.

format

(

df1

))




這個Excel的內容如下:






df1

:


  

C

  

Mon


0

  

D

  

Tue


1

  

E

  

Wed


2

  

F

  

Thu


3

  

G

  

Fri


4

  

A

  

Sat


5

  

B

  

Sun





註:本文的代碼和數據文件可以通過文章開頭提到的Github倉庫獲取。


讀取CSV文件


下面,我們再來看讀取CSV文件的例子。


第一個CSV文件內容如下



$

cat

test1

.

csv


C

,

Mon


D

,

Tue


E

,

Wed


F

,

Thu


G

,

Fri


A

,

Sat




讀取的方式也很簡單:






# file_operation.py


 


df2

=

pd

.

read_csv

(

"data/test1.csv"

)


print

(

"df2:
{}
"

.

format

(

df2

))




我們再來看第2個例子,這個文件的內容如下:






$

cat

test2

.

csv


C

|

Mon


D

|

Tue


E

|

Wed


F

|

Thu


G

|

Fri


A

|

Sat




嚴格的來說,這並不是一個CSV文件了,因為它的數據並不是通過逗號分隔的。在這種情況下,我們可以通過指定分隔符的方式來讀取這個文件,像這樣:






# file_operation.py


 


df3

=

pd

.

read_csv

(

"data/test2.csv"

,

sep

=

"|"

)


print

(

"df3:
{}
"

.

format

(

df3

))




實際上,read_csv支持非常多的參數用來調整讀取的參數,如下表所示:






































































參數 說明
path 文件路徑
sep或者delimiter 欄位分隔符
header 列名的行數,默認是0(第一行)
index_col 列號或名稱用作結果中的行索引
names 結果的列名稱列表
skiprows 從起始位置跳過的行數
na_values 代替NA的值序列
comment 以行結尾分隔注釋的字元
parse_dates 嘗試將數據解析為datetime。默認為False
keep_date_col 如果將列連接到解析日期,保留連接的列。默認為False
converters 列的轉換器
dayfirst 當解析可以造成歧義的日期時,以內部形式存儲。默認為False
data_parser 用來解析日期的函數
nrows 從文件開始讀取的行數
iterator 返回一個TextParser對象,用於讀取部分內容
chunksize 指定讀取塊的大小
skip_footer 文件末尾需要忽略的行數
verbose 輸出各種解析輸出的信息
encoding 文件編碼
squeeze 如果解析的數據只包含一列,則返回一個Series
thousands 千數量的分隔符

詳細的read_csv函數說明請參見這裡:pandas.read_csv


處理無效值


現實世界並非完美,我們讀取到的數據常常會帶有一些無效值。如果沒有處理好這些無效值,將對程序造成很大的干擾。


對待無效值,主要有兩種處理方法:直接忽略這些無效值;或者將無效值替換成有效值。


下面我先創建一個包含無效值的數據結構。然後通過pandas.isna函數來確認哪些值是無效的:




# process_na.py


 


import pandas

as

pd


import numpy

as

np


 


df

=

pd

.

DataFrame

([[

1.0

,

np

.

nan

,

3.0

,

4.0

],


                  

[

5.0

,

np

.

nan

,

np

.

nan

,

8.0

],


                  

[

9.0

,

np

.

nan

,

np

.

nan

,

12.0

],


                  

[

13.0

,

np

.

nan

,

15.0

,

16.0

]])


 


print

(

"df:
{}
"

.

format

(

df

));


print

(

"df:
{}
"

.

format

(

pd

.

isna

(

df

)));

****




這段代碼輸出如下:






df

:


      

0

  

1

    

2

    

3


0

  

1.0

NaN

  

3.0

  

4.0


1

  

5.0

NaN  

NaN

  

8.0


2

  

9.0

NaN  

NaN

  

12.0


3

  

13.0

NaN

  

15.0

  

16.0


 


df

:


      

0

    

1

      

2

      

3


0

  

False

  

True

  

False

  

False


1

  

False

  

True

  

True

  

False


2

  

False

  

True

  

True

  

False


3

  

False

  

True

  

False

  

False




忽略無效值


我們可以通過pandas.DataFrame.dropna函數拋棄無效值:




# process_na.py


 


print

(

"df.dropna():
{}
"

.

format

(

df

.

dropna

()));


 




註:dropna默認不會改變原先的數據結構,而是返回了一個新的數據結構。如果想要直接更改數據本身,可以在調用這個函數的時候傳遞參數 inplace = True


對於原先的結構,當無效值全部被拋棄之後,將不再是一個有效的DataFrame,因此這行代碼輸出如下:



df

.

dropna

()

:


Empty DataFrame


Columns

:

[

0

,

1

,

2

,

3

]


Index

:

[]




我們也可以選擇拋棄整列都是無效值的那一列:






# process_na.py


 


print

(

"df.dropna(axis=1, how="all"):
{}
"

.

format

(

df

.

dropna

(

axis

=

1

,

how

=

"all"

)));





註:axis=1表示列的軸。how可以取值』any』或者』all』,默認是前者。


這行代碼輸出如下:




df

.

dropna

(

axis

=

1

,

how

=

"all"

)

:


      

0

    

2

    

3


0

  

1.0

  

3.0

  

4.0


1

  

5.0

  

NaN

  

8.0


2

  

9.0

  

NaN

  

12.0


3

  

13.0

  

15.0

  

16.0




替換無效值


我們也可以通過fillna函數將無效值替換成為有效值。像這樣:




# process_na.py


 


print

(

"df.fillna(1):
{}
"

.

format

(

df

.

fillna

(

1

)));




這段代碼輸出如下:






df

.

fillna

(

1

)

:


      

0

    

1

    

2

    

3


0

  

1.0

  

1.0

  

3.0

  

4.0


1

  

5.0

  

1.0

  

1.0

  

8.0


2

  

9.0

  

1.0

  

1.0

  

12.0


3

  

13.0

  

1.0

  

15.0

  

16.0




將無效值全部替換成同樣的數據可能意義不大,因此我們可以指定不同的數據來進行填充。為了便於操作,在填充之前,我們可以先通過

rename

方法修改行和列的名稱:






# process_na.py


 


df

.

rename

(

index

=

{

0

:

"index1"

,

1

:

"index2"

,

2

:

"index3"

,

3

:

"index4"

},


          

columns

=

{

0

:

"col1"

,

1

:

"col2"

,

2

:

"col3"

,

3

:

"col4"

},


          

inplace

=

True

);


df

.

fillna

(

value

=

{

"col2"

:

2

},

inplace

=

True

)


df

.

fillna

(

value

=

{

"col3"

:

7

},

inplace

=

True

)


print

(

"df:
{}
"

.

format

(

df

));




這段代碼輸出如下:







df

:


        

col1  col2  col3  col4


index1

  

1.0

  

2.0

  

3.0

  

4.0


index2

  

5.0

  

2.0

  

7.0

  

8.0


index3

  

9.0

  

2.0

  

7.0

  

12.0


index4

  

13.0

  

2.0

  

15.0

  

16.0




處理字元串


數據中常常牽涉到字元串的處理,接下來我們就看看pandas對於字元串操作。


Series

str

欄位包含了一系列的函數用來處理字元串。並且,這些函數會自動處理無效值。


下面是一些實例,在第一組數據中,我們故意設置了一些包含空格字元串:




# process_string.py


 


import pandas

as

pd


 


s1

=

pd

.

Series

([

" 1"

,

"2 "

,

" 3 "

,

"4"

,

"5"

]);


print

(

"s1.str.rstrip():
{}
"

.

format

(

s1

.

str

.

lstrip

()))


print

(

"s1.str.strip():
{}
"

.

format

(

s1

.

str

.

strip

()))


print

(

"s1.str.isdigit():
{}
"

.

format

(

s1

.

str

.

isdigit

()))




在這個實例中我們看到了對於字元串

strip

的處理以及判斷字元串本身是否是數字,這段代碼輸出如下:






s1

.

str

.

rstrip

()

:


0

    

1


1

    

2


2

    

3


3

    

4


4

    

5


dtype

:

object


 


s1

.

str

.

strip

()

:


0

    

1


1

    

2


2

    

3


3

    

4


4

    

5


dtype

:

object


 


s1

.

str

.

isdigit

()

:


0

    

False


1

    

False


2

    

False


3

    

True


4

    

True


dtype

:

bool




下面是另外一些示例,展示了對於字元串大寫,小寫以及字元串長度的處理:






# process_string.py


 


s2

=

pd

.

Series

([

"Stairway to Heaven"

,

"Eruption"

,

"Freebird"

,


                    

"Comfortably Numb"

,

"All Along the Watchtower"

])


print

(

"s2.str.lower():
{}
"

.

format

(

s2

.

str

.

lower

()))


print

(

"s2.str.upper():
{}
"

.

format

(

s2

.

str

.

upper

()))


print

(

"s2.str.len():
{}
"

.

format

(

s2

.

str

.

len

()))



該段代碼輸出如下:






s2

.

str

.

lower

()

:


0

          

stairway

to

heaven


1

                    

eruption


2

                    

freebird


3

            

comfortably

numb


4

    

all along the watchtower


dtype

:

object


 


s2

.

str

.

upper

()

:


0

          

STAIRWAY

TO

HEAVEN


1

                    

ERUPTION


2

                    

FREEBIRD


3

            

COMFORTABLY

NUMB


4

    

ALL ALONG THE WATCHTOWER


dtype

:

object


 


s2

.

str

.

len

()

:


0

    

18


1

    

8


2

    

8


3

    

16


4

    

24


dtype

:

int64




結束語


本文是pandas的入門教程,因此我們只介紹了最基本的操作。對於




  • MultiIndex/Advanced Indexing



  • Merge, join, concatenate



  • Computational tools


之類的高級功能,以後有機會我們再來一起學習。


讀者也可以根據下面的鏈接獲取更多的知識。


參考資料與推薦讀物




  • pandas官方網站



  • Python for Data Analysis



  • Pandas Tutorial: Data analysis with Python: Part 1







看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發者 的精彩文章:

不踩坑的Python爬蟲:如何在一個月內學會爬取大規模數據
不懂 Python,你在 AI 時代將成為新「文盲」

TAG:Python開發者 |