Pandas學習記錄
來自專欄 Python程序員
pandas在數據分析領域是一個非常強大的庫,能夠類似於處理excel一樣處理數據,也正因為它的強大,導致學習曲線陡峭,因此對學習的過程和一些有用的經驗進行總結。照舊先是庫的導入約定如下:
import pandas as pdimport matplotlib.pyplot as pltfrom pandas import Series,DataFrameimport numpy as np
1、創建基本數據結構
Pandas中常用的數據類型有Series和DataFrame,pandas中的Series是由一組index和一組values值組成的。和Python本身的dict對象有些類似,都擁有一組索引,一組數據。但是Series操作起來更為方便,快捷。也可以使用read_csv,read_excel得到DataFrame。
s1 = Series([2,2,4,5,6],index=[hh,as,ff,da,zx])s1
hh 2as 2ff 4da 5zx 6dtype: int64
s1.name = zhous1.index.name = wow
s1
wowhh 2as 2ff 4da 5zx 6Name: zhou, dtype: int64
DataFrame是一個表格數據,可以看作是一組Series組成的,不過這些Series有共同的索引。DataFrame有行索引和列索引,對這兩個方向的索引基本上對等的,因為DataFrame本身是可轉置的。下面先創建這一對象。
data = {state:[anhui,hebei,hainan,jiangsu,riben], year:[2001,2002,2003,2004,2004], pop:[1.1,1.2,1.1,1.4,1.8]}frame = DataFrame(data,columns = [state,pop,year,hh],index=[a1,a2,a3,a4,a5])frame
可以看出,DataFrame就是一個表格,除了利用字典的方式創建這種數據結構之外,還可以使用二維ndarray,多個Series等來創建,在這裡都可以指定索引,包括縱向或者橫向的。
import numpy as npDataFrame(np.arange(0,10).reshape(5,2),columns = [hh,ww])
2、索引和取值
對於Series,因為它只有一列,所以它的取值直接索引的是index(這裡注意我們使用的是標籤索引而不是數字索引。前者必須知道keyword,而後者使用的是序號)。這裡也可以用標籤切片,不過與數組切片不同的是,標籤切片表示的是一個封閉區間。
s1
wowhh 2as 2ff 4da 5zx 6Name: zhou, dtype: int64
s1[hh]
2
s1[[ff,as]]
wowff 4as 2Name: zhou, dtype: int64
s1[ff:zx]
wowff 4da 5zx 6Name: zhou, dtype: int64
相比較於Series,DataFrame的索引方式由於增加了一維的因素變得略微有些複雜。我們直接對DataFrame進行索引實際上得到的是一列或者是多列。這類似於Series簡單的索引。
frame[state]
a1 anhuia2 hebeia3 hainana4 jiangsua5 ribenName: state, dtype: object
frame[[pop,hh]]
為了讓語法上更加接近ndarray,對於DataFrame的數字切片表示的是取出一個或多個行。此外還有bool索引表示的也是選取行。
frame[:2]
frame[frame[pop]>1.1]
下面是兩個很重要的索引方式標籤索引和數字索引。前者使用的是loc函數。
frame.loc[a2:a3,[pop,hh]]
frame.loc[:,pop]
a1 1.1a2 1.2a3 1.1a4 1.4a5 1.8Name: pop, dtype: float64
frame.loc[a2,pop]
1.2
可以看出loc函數可以利用標籤來包含上文的所有索引功能,是非常強大的一種方式。而如果我們不想使用或者不方便使用標籤時,我們可以使用它的相似函數iloc來進行索引。
frame.iloc[:,:2]
frame.iloc[[1,2,3],1:3]
總結:對於Series的索引基本上與字典的索引類似,DataFrame的索引方式很多很複雜,但是對於一般的方式我們只需要了解,重點掌握iloc和loc兩個函數即可方便的對DataFrame進行索引。
3、一些操作
首先要講的當然是Series對象啦,Series有兩個重要參數,index和values,這確實特別類似於字典。
s1.index,s1.values
(Index([hh, as, ff, da, zx], dtype=object, name=wow), array([2, 2, 4, 5, 6], dtype=int64))
除了這兩個參數之外,我們來介紹一下一些常用函數
s1[hh] = np.nan pd.isnull(s1) # 判斷是否為預設值
wowhh Trueas Falseff Falseda Falsezx FalseName: zhou, dtype: bool
s2 = s1.copy()s2 = s2.drop([as]) # 丟掉某一行s2
wowhh NaNff 4.0da 5.0zx 6.0Name: zhou, dtype: float64
s1[hh] = 5s1.sort_index() # 按照index進行排序
wowas 2.0da 5.0ff 4.0hh 5.0zx 6.0Name: zhou, dtype: float64
s1.sort_values(ascending=False) # 按照值進行排序,降序排列
wowzx 6.0da 5.0hh 5.0ff 4.0as 2.0Name: zhou, dtype: float64
s1.unique() # 得到values中唯一值數組
array([ 5., 2., 4., 6.])
s1.value_counts() # 得到value每個值的個數
5.0 26.0 14.0 12.0 1Name: zhou, dtype: int64
DataFrame的values,columns,index的屬性,其中的index和columns類似於Series的index,不過這裡變成了二維。
frame.index,frame.columns,frame.values
(Index([a1, a2, a3, a4, a5], dtype=object), Index([state, pop, year, hh], dtype=object), array([[anhui, 1.1, 2001, nan], [hebei, 1.2, 2002, nan], [hainan, 1.1, 2003, nan], [jiangsu, 1.4, 2004, nan], [riben, 1.8, 2004, nan]], dtype=object))
frame.index.name = axframe.columns.name = desframe
下面首先介紹幾個可以對DataFrame的概覽的函數,這樣在之後我們拿到數據之後就可以對數據有一個大概的了解,包括數據類型,數據分布等。
frame.describe()
frame.info()
<class pandas.core.frame.DataFrame>Index: 5 entries, a1 to a5Data columns (total 4 columns):state 5 non-null objectpop 5 non-null float64year 5 non-null int64hh 0 non-null objectdtypes: float64(1), int64(1), object(2)memory usage: 200.0+ bytes
frame.head(2)
frame.tail(3)
索引對象,在DataFrame裡面所用到的數組和序列的標籤都會變成Index對象,其不可更改。而reindex是用來改變原來數據的index對象的函數,他可以修改行或者列的對象。
frame.reindex(index = [a1,aa2,a3,aa4,a5])
frame.reindex(columns= [state,hi],fill_value=0)
frame.drop([state],axis = 1) #丟掉某一列
使用函數(自定義函數,統計函數,匯總函數)對行或者列進行計算。(mean,sum,min,max)
f = lambda x:x.min()-x.max()frame.drop([state,hh],axis = 1).apply(f)
despop -0.7year -3.0dtype: float64
frame.sum()
desstate anhuihebeihainanjiangsuribenpop 6.6year 10014hh Nonedtype: object
frame.sort_values(by = pop,axis = 0) #by也可以傳入多個列名
frame.rank(axis = 0) #進行排名
這裡還有比較重要的一點就是缺失數據,我們使用dropna,fillna即可解決。
4、分組匯總
這裡涉及的是非常有用的操作,包括分組運算和數據聚合。數據處理中有一個表示分組運算的術語(拆分-應用-合併)。
df = DataFrame({key1:list(aabba),key2:[one,two,one,two,one],data1:np.random.randn(5),data2:np.random.randn(5)})df
grouped = df[data1].groupby(df[key1])grouped.mean()
key1a 0.430108b 0.150110Name: data1, dtype: float64
means = df[data1].groupby([df[key1],df[key2]]).mean()means
key1 key2a one 0.122082 two 1.046160b one 0.425353 two -0.125133Name: data1, dtype: float64
df.groupby([key1,key2]).size() #類似於value_counts
key1 key2a one 2 two 1b one 1 two 1dtype: int64
這裡我們創建了分組,可以以某一列作為分類標準,也可以一組合適的外來值作為類別。我們進行groupby之後得到的groupby對象,包含了分組信息,但是並還需要進行每一組之間的數據處理函數才能實際分類。使用單個鍵值分組時得到的索引是這個鍵值的unique,使用兩組鍵值進行分組之後,得到的是一個層次化索引(有唯一的鍵值對組成)。默認分組方向是在axis = 0上的,我們也可以在列上進行分組。
for (k1,k2), group_data in df.groupby([key1,key2]): print(k1,k2) print(group_data)
a one data1 data2 key1 key20 0.323545 0.671964 a one4 -0.079380 0.837375 a onea two data1 data2 key1 key21 1.04616 -0.879242 a twob one data1 data2 key1 key22 0.425353 0.69351 b oneb two data1 data2 key1 key23 -0.125133 -1.176448 b two
dict(list(df.groupby([key1,key2])))
{(a, one): data1 data2 key1 key2 0 0.323545 0.671964 a one 4 -0.079380 0.837375 a one, (a, two): data1 data2 key1 key2 1 1.04616 -0.879242 a two, (b, one): data1 data2 key1 key2 2 0.425353 0.69351 b one, (b, two): data1 data2 key1 key2 3 -0.125133 -1.176448 b two}
df.groupby([key1,key2])[data1].mean() #直接在groupby對象上進行索引
key1 key2a one 0.122082 two 1.046160b one 0.425353 two -0.125133Name: data1, dtype: float64
分組方式還有通過傳入字典,函數名,Series,雖然很複雜,但是這些方式最終的形式還是傳入一個數組來進行相同值分在一起的操作。
people = DataFrame(np.random.randn(5,5),columns=list(abcde),index = [Joe,Steve,Wes,Jim,Travis])people
mapp = {a:red,b:red,c:blue,d:blue,e:red} # 通過映射變成了傳入了一組數組people.groupby(mapp,axis = 1).mean()
people.groupby(len).sum() #名字那一列求完長度之後又變成了數組
上面我們對數據進行了分組和聚合,但是如果我們要把得到的這些數據加入到原先的數據表中需要用到merge函數。這裡介紹的是直接將得到的值直接放到原有數據上的transform方法。
people.groupby(len).transform(np.mean)
除了以上介紹的這些操作之外,DataFrame還有一個很重要的技術就是合併數據,分為列連接和行連接。對於列連接,我們使用merge函數,這裡需要注意的是merge函數的一些參數(連接方式how,鍵值left_on,right_on,使用索引連接left_index,suffixes增加區別)。如果對層次化索引的話,連接鍵必須使用列表來指定。
people_mean = people.groupby(len).transform(np.mean)
pd.merge(left=people,right=people_mean,left_index=True,right_index=True,suffixes=(,_mean))
對與行連接,使用的是concat函數,這裡需要注意的也是一些參數的設置。
pd.concat([people,people_mean],keys = [origin,mean])
總結:分組聚合合併是數據處理中很重要的步驟,Pandas中都分別有對應的函數來進行處理,這裡重點掌握groupy,一些聚合函數以及合併的方法。
吐槽:知乎支持導入md文檔,但不支持md裡面的表格是什麼操作??
推薦閱讀:
※在這個世界上,會有屬於你靈魂伴侶嗎?
※基礎群論(三): Sylow理論 上
※Zeta函數——故事的小黃花
※自媒體,我要你何用?數學,我要你又有何用?
※csvService csv操作讀寫