標籤:

Python數據分析之Pandas數據結構

註:本文主要內容及示例代碼來自《 Python for Data Analysis》(2th Edition)一書,是為學習筆記

首先導入Pandas包:

import pandas as pd

另外可以導入Series和DataFrame,因為這兩個經常被用到:

from pandas import Series, DataFrame

數據結構其實就是Series和DataFrame。

1. Series

series是一個像數組一樣的一維序列,並伴有一個數組表示label,叫做索引(index)。創建一個series的方法也很簡單:

obj = pd.Series([4, 7, -5, 3])obj0 41 72 -53 3dtype: int64

可以看到,左邊表示index,右邊表示對應的value。可以通過value和index屬性查看:

obj.valuesarray([ 4, 7, -5, 3])obj.index # like range(4)RangeIndex(start=0, stop=4, step=1)

當然也可以自己指定index的label:

obj2 = pd.Series([4, 7, -5, 3], index=[d, b, a, c])obj2d 4b 7a -5c 3dtype: int64obj2.indexIndex([d, b, a, c], dtype=object)

可以用index的label來選擇:

obj2[a]-5obj2[d] = 6obj2[[c, a, d]]c 3a -5d 6dtype: int64

這裡[c, a, d]其實被當做了索引,儘管這個索引是用string構成的。

使用numpy函數或類似的操作,會保留index-value的關係:

obj2[obj2 > 0]d 4b 7c 3dtype: int64obj2 * 2d 12b 14a -10c 6dtype: int64import numpy as npnp.exp(obj2)d 403.428793b 1096.633158a 0.006738c 20.085537dtype: float64

另一種看待series的方法,它是一個長度固定,有順序的dict,從index映射到value。在很多場景下,可以當做dict來用:

b in obj2Truee in obj2False

還可以直接用現有的dict來創建series:

sdata = {Ohio: 35000, Texas: 71000, Oregon:16000, Utah: 5000}obj3 = pd.Series(sdata)obj3Ohio 35000Oregon 16000Texas 71000Utah 5000dtype: int64

series中的index其實就是dict中排好序的keys。我們也可以傳入一個自己想要的順序:

states = [California, Ohio, Oregon, Texas]obj4 = pd.Series(sdata, index=states)obj4California NaNOhio 35000.0Oregon 16000.0Texas 71000.0dtype: float64

順序是按states里來的,但因為沒有找到california,所以是NaN。NaN表示缺失數據。pandas中的isnull和notnull函數可以用來檢測缺失數據:

pd.isnull(obj4)California TrueOhio FalseOregon FalseTexas Falsedtype: boolpd.notnull(obj4)California FalseOhio TrueOregon TrueTexas Truedtype: bool

series也有對應的方法:

obj4.isnull()California TrueOhio FalseOregon FalseTexas Falsedtype: bool

series中一個有用的特色就是自動按index label來排序(Data alignment features):

obj3Ohio 35000Oregon 16000Texas 71000Utah 5000dtype: int64obj4California NaNOhio 35000.0Oregon 16000.0Texas 71000.0dtype: float64obj3 + obj4California NaNOhio 70000.0Oregon 32000.0Texas 142000.0Utah NaNdtype: float64

這個Data alignment features(數據對齊特色)和資料庫中的join相似。

series自身和它的index都有一個叫name的屬性,這個能和其他pandas的函數進行整合:

obj4.name = populationobj4.index.name = stateobj4stateCalifornia NaNOhio 35000.0Oregon 16000.0Texas 71000.0Name: population, dtype: float64

series的index能被直接更改:

obj0 41 72 -53 3dtype: int64obj.index = [Bob, Steve, Jeff, Ryan]objBob 4Steve 7Jeff -5Ryan 3dtype: int64

2. DataFrame

DataFrame表示一個長方形表格,並包含排好序的列,每一列都可以是不同的數值類型(數字,字元串,布爾值)。DataFrame有行索引和列索引(row index, column index);可以看做是分享所有索引的由series組成的字典。數據是保存在一維以上的區塊里的。

(其實我是把dataframe當做excel里的那種表格來理解的,這樣感覺更直觀一些)

構建一個dataframe的方法,是用一個dcit,dict里的值是list:

data = {state: [Ohio, Ohio, Ohio, Nevada, Nevada, Nevada], year: [2000, 2001, 2002, 2001, 2002, 2003], pop: [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}frame = pd.DataFrame(data)frame

dataframe也會像series一樣,自動給數據賦index, 而列則會按順序排好。

對於一個較大的DataFrame,用head方法會返回前5行(註:這個函數在數據分析中經常使用,用來查看錶格里有什麼東西):

frame.head()

如果指定一列的話,會自動按列排序:

pd.DataFrame(data, columns=[year, state, pop])

如果你導入一個不存在的列名,那麼會顯示為缺失數據:

frame2 = pd.DataFrame(data, columns=[year, state, pop, debt], index=[one, two, three, four, five, six])frame2

frame2.columnsIndex([year, state, pop, debt], dtype=object)

從DataFrame里提取一列的話會返回series格式,可以以屬性或是dict一樣的形式來提取:

frame2[state]one Ohiotwo Ohiothree Ohiofour Nevadafive Nevadasix NevadaName: state, dtype: objectframe2.yearone 2000two 2001three 2002four 2001five 2002six 2003Name: year, dtype: int64

注意:frame2[column]能應對任何列名,但frame2.column的情況下,列名必須是有效的python變數名才行。

返回的series有DataFrame種同樣的index,而且name屬性也是對應的。

對於行,要用在loc屬性里用 位置或名字:

frame2.loc[three]year 2002state Ohiopop 3.6debt NaNName: three, dtype: object

列值也能通過賦值改變。比如給debt賦值:

frame2[debt] = 16.5frame2

frame2[debt] = np.arange(6.)frame2

如果把list或array賦給column的話,長度必須符合DataFrame的長度。如果把一二series賦給DataFrame,會按DataFrame的index來賦值,不夠的地方用缺失數據來表示:

val = pd.Series([-1.2, -1.5, -1.7], index=[two, four, five])frame2[debt] = valframe2

如果列不存在,賦值會創建一個新列。而del也能像刪除字典關鍵字一樣,刪除列:

frame2[eastern] = frame2.state == Ohioframe2

然後用del刪除這一列:

del frame2[eastern]frame2.columnsIndex([year, state, pop, debt], dtype=object)

注意:columns返回的是一個view,而不是新建了一個copy。因此,任何對series的改變,會反映在DataFrame上。除非我們用copy方法來新建一個。

另一種常見的格式是dict中的dict:

pop = {Nevada: {2001: 2.4, 2002: 2.9}, Ohio: {2000: 1.5, 2001: 1.7, 2002: 3.6}}

把上面這種嵌套dcit傳給DataFrame,pandas會把外層dict的key當做列,內層key當做行索引:

frame3 = pd.DataFrame(pop)frame3

另外DataFrame也可以向numpy數組一樣做轉置:

frame3.T

指定index:

pd.DataFrame(pop, index=[2001, 2002, 2003])

series組成的dict:

pdata = {Ohio: frame3[Ohio][:-1], Nevada: frame3[Nevada][:2]}pd.DataFrame(pdata)

其他一些可以傳遞給DataFrame的構造器:

如果DataFrame的index和column有自己的name屬性,也會被顯示:

frame3.index.name = year; frame3.columns.name = stateframe3

values屬性會返回二維數組:

frame3.valuesarray([[ nan, 1.5], [ 2.4, 1.7], [ 2.9, 3.6]])

如果column有不同的類型,dtype會適應所有的列:

frame2.valuesarray([[2000, Ohio, 1.5, nan], [2001, Ohio, 1.7, -1.2], [2002, Ohio, 3.6, nan], [2001, Nevada, 2.4, -1.5], [2002, Nevada, 2.9, -1.7], [2003, Nevada, 3.2, nan]], dtype=object)

3. 索引對象

pandas的Index Objects (索引對象)負責保存axis labels和其他一些數據(比如axis name或names)。一個數組或其他一個序列標籤,只要被用來做構建series或DataFrame,就會被自動轉變為index:

obj = pd.Series(range(3), index=[a, b, c])index = obj.indexindexIndex([a, b, c], dtype=object)index[1:]Index([b, c], dtype=object)

index object是不可更改的:

index[1] = d---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-67-676fdeb26a68> in <module>()----> 1 index[1] = d/Users/xu/anaconda/envs/py35/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value) 1243 1244 def __setitem__(self, key, value):-> 1245 raise TypeError("Index does not support mutable operations") 1246 1247 def __getitem__(self, key):TypeError: Index does not support mutable operations

正因為不可修改,所以data structure中分享index object是很安全的:

labels = pd.Index(np.arange(3))labelsInt64Index([0, 1, 2], dtype=int64)obj2 = pd.Series([1.5, -2.5, 0], index=labels)obj20 1.51 -2.52 0.0dtype: float64obj2.index is labelsTrue

index除了像數組,index的功能也類似一個大小固定的集合(set):

frame3

frame3.columnsIndex([Nevada, Ohio], dtype=object, name=state)Ohio in frame3.columnsTrue2003 in frame3.columnsFalse

與python里的set不同,pandas的index可以有重複的labels:

dup_labels = pd.Index([foo, foo, bar, bar])dup_labelsIndex([foo, foo, bar, bar], dtype=object)

在這種重複的標籤中選擇的話,會選中所有相同的標籤。

Index還有一些方法和屬性:

推薦閱讀:

大數據有哪些工作崗位,日常工作內容是什麼,需要掌握哪些工具和技能
數據分析階段性總結
老闆炒掉分析師,多掙1千萬,如今腸子都悔青了!
Kaggle項目泰坦尼克號生存預測
我的首次簡單」數據分析「

TAG:數據分析 |