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:數據分析 |