Pandas 數據結構簡介
Pandas 數據結構簡介知乎專欄 - 隨心寫作,自由表達
前段時間我說過我會寫一些關於 Pandas 的文章,但是我卻一直沒有跟進。然而,本周兩位同事向我表達了他們對於Pandas的學習興趣,因此我打算重新討論這個話題。
因為我覺得這是一個龐大的任務,所以下面我將分成三個部分來全面地介紹Pandas庫:
- Part 1: Pandas數據結構簡介,該部分主要介紹該庫的兩個基本數據結構—— Series 和 DataFrames。
- Part 2: DataFrames的使用方法,該部分主要介紹如何使用 DataFrames 的篩選、過濾、合併、聯合以及分組功能。
- Part 3: 利用Pandas處理 MovieLens 數據集,該部分主要利用前兩部分的內容來回答關於 MovieLens 收視率數據的幾個基本分析的問題。
如果你想跟著文章的內容運行相應代碼的話,你可以在這裡下載到相關 CSV 數據和 MovieLens數據。
本篇文章的目的在於通過比較 Pandas 與 SQL 之間的差異來介紹該庫的基本用法。由於我的同事都非常熟悉 SQL 的語法,所以我覺得這是一個易於被讀者所理解的寫作方法。
如果你想要學習更多的 Pandas 知識,你可以閱讀 Pandas作者撰寫的書籍《Python for Data Analysis》。
Pandas是 Python中用於分析數據的常用開源庫。Python 可以很好地預處理和加工數據,但是它無法很好地進行數據分析——通常情況下你會利用 R 或者 SQL 來分析數據。有了 Pandas之後,我們可以利用 Python 快速地進行數據分析。
數據結構知乎專欄 - 隨心寫作,自由表達
Pandas中引入了兩種新的數據結構——Series和DataFrame,這兩種數據結構都建立在NumPy的基礎之上。
In [2]:import pandas as pdnimport numpy as npnimport matplotlib.pyplot as pltnpd.set_option("max_columns", 50)n%matplotlib inlinen
Series知乎專欄 - 隨心寫作,自由表達
Series是指一個類似於數組、列表或列變數的一維對象,Series中每個條目都會被分配一個標籤索引。默認情況下,每個條目都會收到一個從0到N之間的索引標籤,其中N等於Series的長度減一。
In [3]:# create a Series with an arbitrary listns = pd.Series([7, Heisenberg, 3.14, -1789710578, Happy Eating!])nsn
Out[3]:
0 7n1 Heisenbergn2 3.14n3 -1789710578n4 Happy Eating!ndtype: objectn
Series可以直接轉換詞典格式的數據,其中詞典的鍵值對應Series中的索引值。
In [4]:d = {Chicago: 1000, New York: 1300, Portland: 900, San Francisco:1100, n Austin: 450, Boston: None}ncities = pd.Series(d)ncitiesn
Out[4]:
Austin 450nBoston NaNnChicago 1000nNew York 1300nPortland 900nSan Francisco 1100ndtype: float64n
你可以利用索引從Series中提取出特定的條目。
In [5]:cities[Chicago]n
Out[5]:
1000.0n
In [6]:
cities[[Chicago, Portland, San Francisco]]n
Out[6]:
Chicago 1000nPortland 900nSan Francisco 1100ndtype: float64n
或者你也可以利用布爾索引值來選取數據。
In [7]:cities[cities < 1000]n
Out[7]:
Austin 450nPortland 900ndtype: float64n
第二種方法可能看起來有點奇怪,所以讓我們更清楚地了解下它的邏輯——cities < 1000將返回一系列邏輯值,然後我們可以利用這些值從Series中提取出相應的條目。
In [8]:less_than_1000 = cities < 1000nprint(less_than_1000)nprint(n)nprint(cities[less_than_1000])n
Austin TruenBoston FalsenChicago FalsenNew York FalsenPortland TruenSan Francisco Falsendtype: boolnnnAustin 450nPortland 900ndtype: float64n
我們還可以更改Series中的數值。
In [9]:# changing based on the indexnprint(Old value, cities[Chicago])ncities[Chicago] = 1400nprint(New value, cities[Chicago])n
(Old value, 1000.0)n(New value, 1400.0)n
In [10]:
# changing values using boolean logicnprint(cities[cities < 1000])nprint(n)ncities[cities < 1000] = 750nprint(cities[cities < 1000])n
Austin 450nPortland 900ndtype: float64nnnAustin 750nPortland 750ndtype: float64n
如果你不確定Series中是否存在某個條目,你可以利用 Python 代碼來檢測。
In [11]:print(Seattle in cities)nprint(San Francisco in cities)n
FalsenTruen
我們還可以對Series進行數學運算和函數運算。
In [12]:# divide city value by 3ncities / 3n
Out[12]:
Austin 250.000000nBoston NaNnChicago 466.666667nNew York 433.333333nPortland 250.000000nSan Francisco 366.666667ndtype: float64n
In [13]:
# square city valuesnnp.square(cities)n
Out[13]:
Austin 562500nBoston NaNnChicago 1960000nNew York 1690000nPortland 562500nSan Francisco 1210000ndtype: float64n
此外你還可以匯總兩個Series,這會返回兩個Series的並集,其中沒有共同索引的條目將會返回 NULL/NaN。
In [14]:print(cities[[Chicago, "New York", "Portland"]])nprint(n)nprint(cities[[Austin, New York]])nprint(n)nprint(cities[[Chicago, New York, Portland]] + cities[[Austin, New York]])n
Chicago 1400nNew York 1300nPortland 750ndtype: float64nnnAustin 750nNew York 1300ndtype: float64nnnAustin NaNnChicago NaNnNew York 2600nPortland NaNndtype: float64n
由於兩個Series中沒有同時包含Austin,Chicago和Portland,因此它們的返回值是 NULL/NaN。
我們可以利用 isnull 和 notnull 函數來檢測 NULL 值。
In [15]:# returns a boolean series indicating which values arent NULLncities.notnull()n
Out[15]:
Austin TruenBoston FalsenChicago TruenNew York TruenPortland TruenSan Francisco Truendtype: booln
In [16]:
# use boolean logic to grab the NULL citiesnprint(cities.isnull())nprint(n)nprint(cities[cities.isnull()])n
Austin FalsenBoston TruenChicago FalsenNew York FalsenPortland FalsenSan Francisco Falsendtype: boolnnnBoston NaNndtype: float64n
DataFrame知乎專欄 - 隨心寫作,自由表達
DataFrame是一種由列向量和行向量組成的數據結構,它類似於電子數據表、資料庫表格和 R 語言中的 data.frame 對象。你也可以理解成DataFrame是由多個共享索引值的Series對象構成的。
本文的剩下篇幅中,我將主要介紹DataFrame的內容。
Reading Data知乎專欄 - 隨心寫作,自由表達
我們可以將 Python 中常用的數據結構(如詞典列表)轉換成DataFrame,其中通過控制columns的參數值可以調整變數的順序。默認情況下,DataFrame會按字母順序對變數進行排序。
In [18]:data = {year: [2010, 2011, 2012, 2011, 2012, 2010, 2011, 2012],n team: [Bears, Bears, Bears, Packers, Packers, Lions, Lions, Lions],n wins: [11, 8, 10, 15, 11, 6, 10, 4],n losses: [5, 8, 6, 1, 5, 10, 6, 12]}nfootball = pd.DataFrame(data, columns=[year, team, wins, losses])nfootballn
Out[18]:
yearteamwinslosses02010Bears11512011Bears8822012Bears10632011Packers15142012Packers11552010Lions61062011Lions10672012Lions412更多情況下,我們需要將數據集讀到DataFrame中,接下來我們將介紹幾種常用的讀取數據的方法。
CSV知乎專欄 - 隨心寫作,自由表達
我們可以利用read.csv函數來讀取 CSV 文件,其中read.csv函數默認CSV數據集是以逗號分隔的,你可以通過 sep 參數來控制分隔符的類別。
In [19]:
%cd ~/Desktop/n
/Users/zengphil/Desktopn
In [20]:
# Source: baseball-reference.com/players/r/riverma01.shtmln!head -n 5 mariano-rivera.csvn
Year,Age,Tm,Lg,W,L,W-L%,ERA,G,GS,GF,CG,SHO,SV,IP,H,R,ER,HR,BB,IBB,SO,HBP,BK,WP,BF,ERA+,FIP,WHIP,H9,HR9,BB9,SO9,SO/W,Awardsn1995,25,NYY,AL,5,3,.625,5.51,19,10,2,0,0,0,67.0,71,43,41,11,30,0,51,2,1,0,301,84,5.15,1.507,9.5,1.5,4.0,6.9,1.70,n1996,26,NYY,AL,8,3,.727,2.09,61,0,14,0,0,5,107.2,73,25,25,1,34,3,130,2,0,1,425,240,1.88,0.994,6.1,0.1,2.8,10.9,3.82,CYA-3MVP-12n1997 ,27,NYY,AL,6,4,.600,1.88,66,0,56,0,0,43,71.2,65,17,15,5,20,6,68,0,0,2,301,239,2.96,1.186,8.2,0.6,2.5,8.5,3.40,ASMVP-25n
In [23]:
from_csv = pd.read_csv(mariano-rivera.csv)nfrom_csv.head()n
Out[23]:
YearAgeTmLgWLW-L%ERAGGSGFCGSHOSVIPHRERHRBBIBBSOHBPBKWPBFERA+FIPWHIPH9HR9BB9SO9SO/WAwards0199525NYYAL53.6255.511910200067.07143411130051210301845.151.5079.51.54.06.91.70NaN1199626NYYAL83.7272.0961014005107.273252513431302014252401.880.9946.10.12.810.93.82CYA-3MVP-1221997 27NYYAL64.6001.8866056004371.26517155206680023012392.961.1868.20.62.58.53.40ASMVP-253199828NYYAL301.0001.9154049003661.14813133171361002462333.481.0607.00.42.55.32.12NaN41999 29NYYAL43.5711.8366063004569.04315142183523122682572.920.8845.60.32.36.82.89ASCYA-3MVP-14該函數默認將文件中的第一行設定為列變數的標題,我們還可以設定 header=None 來手動設定列標題。
In [25]:# Source: pro-football-reference.com/players/M/MannPe00/touchdowns/passing/2012/n!head -n 6 peython-passing-TDS-2012.csvn
Rk,G#,Date,Tm,,Opp,Result,Quarter,Dist,Scorer/Receiver,Score Before,Score Aftern1,1,2012-09-09,DEN,,PIT,W 31-19,3,71,Demaryius Thomas,Trail 7-13,Lead 14-13*n2,1,2012-09-09,DEN,,PIT,W 31-19,4,1,Jacob Tamme,Trail 14-19,Lead 22-19*n3,2,2012-09-17,DEN,@,ATL,L 21-27,2,17,Demaryius Thomas,Trail 0-20,Trail 7-20n4,3,2012-09-23,DEN,,HOU,L 25-31,4,38,Brandon Stokley,Trail 11-31,Trail 18-31n
In [27]:
cols = [num, game, date, team, home_away, opponent, n result, quarter, distance, receiver, score_before,n score_after]nno_headers = pd.read_csv(peython-passing-TDS-2012.csv, sep = ,,n header=None, names=cols)nno_headers.head()n
Out[27]:
numgamedateteamhome_awayopponentresultquarterdistancereceiverscore_beforescore_after0RkG#DateTmNaNOppResultQuarterDistScorer/ReceiverScore BeforeScore After1112012-09-09DENNaNPITW 31-19371Demaryius ThomasTrail 7-13Lead 14-13*2212012-09-09DENNaNPITW 31-1941Jacob TammeTrail 14-19Lead 22-19*3322012-09-17DEN@ATLL 21-27217Demaryius ThomasTrail 0-20Trail 7-204432012-09-23DENNaNHOUL 25-31438Brandon StokleyTrail 11-31Trail 18-31Pandas的reader系列函數中有許多可控參數,用於控制讀取數據時的其他設定。
大家可以參閱IO文檔來熟悉文件讀取/寫入功能。
Excel知乎專欄 - 隨心寫作,自由表達
你們討厭VBA嗎?我非常討厭它,我相信你也會討厭它的。幸運的是,pandas允許我們讀寫 Excel 文件,所以我們可以利用Python處理完數據後再導出Excel文件,這樣可以規避使用煩人的VBA來處理數據。
讀取Excel文件需要安裝xlrd庫,我們可以利用pip工具來安裝它(pip install xlrd)。
In [28]:# this is the DataFrame we created from a dictionary earliernfootball.head()n
Out[28]:
yearteamwinslosses02010Bears11512011Bears8822012Bears10632011Packers15142012Packers115In [29]:# since our index on the football DataFrame is meaningless, lets not write itnfootball.to_excel(football.xlsx, index=False)n
In [32]:
!ls -l *.xlsxn
-rw-r--r-- 1 zengphil staff 5588 4 23 10:56 football.xlsxn
In [33]:
# delete the DataFramendel footballn
In [35]:
# read from Excelnfootball = pd.read_excel(football.xlsx, Sheet1)nfootballn
Out[35]:
yearteamwinslosses02010Bears11512011Bears8822012Bears10632011Packers15142012Packers11552010Lions61062011Lions10672012Lions412Database知乎專欄 - 隨心寫作,自由表達
Pandas還可以直接從資料庫中讀寫DataFrame文件,你只需要利用http://pandas.io模塊中的read_sql或to_sql函數來創建一個連接資料庫的對象即可。
需要注意的是,to_sql直接調用INSERT INTO語句,因此數據的傳輸速度比較慢。如果你想將一個大型DataFrame寫入資料庫中,最好先導出CSV文件然後再導入資料庫中。
In [38]:from pandas.io import sqlnimport sqlite3nnconn = sqlite3.connect(/Users/zengphil/Downloads/Database)nquery = "SELECT * FROM towed WHERE make = FORD;"nnresults = sql.read_sql(query, con = conn)nresults.head()n
Clipboard知乎專欄 - 隨心寫作,自由表達
相比於直接將查詢結果插入DataFrame中,我更傾向於從剪貼板中讀取數據。Python可以很好地處理剪貼板中的分隔符數據,你可以控制sep參數來設定數據分隔符。
Hank Aaron
In [39]:hank = pd.read_clipboard()nhank.head()n
Out[39]:
195420MLNNL12250946858131276136922.12839.280.322.447.76910420913.136.14Unnamed: 27*79RoY-401955 21MLNNL153665602105189379271063149610.3140.3660.5400.906141325203745*974AS,MVP-911956 22MLNNL153660609106200341426922437540.3280.3650.5580.923151340212576*9AS,MVP-321957 23MLNNL151675615118198276441321157580.3220.3780.6000.9781663691300315*98AS,MVP-131958 24MLNNL15366460110919634430954159490.3260.3860.5460.9311523282110316*98AS,MVP-3,GG41959 25MLNNL154693629116223467391238051540.3550.4010.6361.0371824001940917*98/5AS,MVP-3,GGURL知乎專欄 - 隨心寫作,自由表達
此外,我們還可以利用read_table函數直接從 URL 鏈接中讀取數據。
In [40]:url = https://raw.github.com/gjreda/best-sandwiches/master/data/best-sandwiches-geocode.tsvnn# fetch the text from the URL and read it into a DataFramenfrom_url = pd.read_table(url, sep=t)nfrom_url.head(3)n
Out[40]:
ranksandwichrestaurantdescriptionpriceaddresscityphonewebsitefull_addressformatted_addresslatlng01BLTOld Oak TapThe B is applewood smoked&mdash;nice and snapp...$102109 W. Chicago Ave.Chicago773-772-0406theoldoaktap.com2109 W. Chicago Ave., Chicago2109 West Chicago Avenue, Chicago, IL 60622, USA41.895734-87.67996012Fried BolognaAu ChevalThought your bologna-eating days had retired w...$9800 W. Randolph St.Chicago312-929-4580aucheval.tumblr.com800 W. Randolph St., Chicago800 West Randolph Street, Chicago, IL 60607, USA41.884672-87.64775423Woodland MushroomXocoLeave it to Rick Bayless and crew to come up w...$9.50.445 N. Clark St.Chicago312-334-3688rickbayless.com445 N. Clark St., Chicago445 North Clark Street, Chicago, IL 60654, USA41.890602-87.630925Google Analytics知乎專欄 - 隨心寫作,自由表達
Pandas還整合了 Google Analytics 的API介面,但是需要進行一些設置。本文沒有介紹這些內容,你可以參閱文章1和文章2。
http://weixin.qq.com/r/WkMCGqvEoPbfre959xZI (二維碼自動識別)
原文鏈接:Intro to pandas data structures
原文作者:Greg Reda
譯者:Fibears
推薦閱讀:
※centos在python3環境下安裝PIP的問題?
※薦書:《Fluent Python》
※Python3.4 用 pip 安裝lxml時出現 「Unable to find vcvarsall.bat 」?
※學習數據分析的8個 pandas資源
TAG:Python |