小白也能看懂的Pandas實操演示教程(上)
- 2019 年 10 月 7 日
- 筆記
今天主要帶大家來實操學習下Pandas,因為篇幅原因,分為了兩部分,本篇為上。
1 數據結構的簡介
pandas中有兩類非常重要的數據結構,就是序列Series和數據框DataFrame.Series類似於NumPy中的一維數組,可以使用一維數組的可用函數和方法,而且還可以通過索引標籤的方式獲取數據,還具有索引的自動對齊功能;DataFrame類似於numpy中的二維數組,同樣可以使用numpy數組的函數和方法,還具有一些其它靈活的使用。
1.1 Series的創建 三種方法
通過一維數組創建序列m
import pandas as pd import numpy as np arr1=np.arange(10) print("數組arr1:",arr1) print("arr1的數據類型:",type(arr1)) s1=pd.Series(arr1) print("序列s1: ",s1) print("s1的數據類型:",type(s1))
數組arr1: [0 1 2 3 4 5 6 7 8 9] arr1的數據類型: <class 'numpy.ndarray'> 序列s1: 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 dtype: int32 s1的數據類型: <class 'pandas.core.series.Series'>
通過字典的方式創建序列
dict1={'a':1,'b':2,'c':3,'d':4,'e':5} print("字典dict1:",dict1) print("dict1的數據類型:",type(dict1)) s2=pd.Series(dict1) print("序列s2:",s2) print("s2的數據類型:",type(s2))
字典dict1: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} dict1的數據類型: <class 'dict'> 序列s2:a 1 b 2 c 3 d 4 e 5 dtype: int64 s2的數據類型: <class 'pandas.core.series.Series'>
通過已有DataFrame創建
由於涉及到了DataFrame的概念,所以等後面介紹了DataFrame之後補充下如何通過已有的DataFrame來創建Series。
1.2 DataFrame的創建 三種方法
通過二維數組創建數據框
print("第一種方法創建DataFrame") arr2=np.array(np.arange(12)).reshape(4,3) print("數組2:",arr2) print("數組2的類型",type(arr2)) df1=pd.DataFrame(arr2) print("數據框1: ",df1) print("數據框1的類型:",type(df1))
第一種方法創建DataFrame 數組2: [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] 數組2的類型 <class 'numpy.ndarray'> 數據框1: 0 1 2 0 0 1 2 1 3 4 5 2 6 7 8 3 9 10 11 數據框1的類型: <class 'pandas.core.frame.DataFrame'>
通過字典列表的方式創建數據框
print("第二種方法創建DataFrame") dict2={'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12],'d':[13,14,15,16]} print("字典2-字典列表:",dict2) print("字典2的類型",type(dict2)) df2=pd.DataFrame(dict2) print("數據框2: ",df2) print("數據框2的類型:",type(df2))
第二種方法創建DataFrame 字典2-字典列表: {'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8], 'c': [9, 10, 11, 12], 'd': [13, 14, 15, 16]} 字典2的類型 <class 'dict'> 數據框2: a b c d 0 1 5 9 13 1 2 6 10 14 2 3 7 11 15 3 4 8 12 16 數據框2的類型: <class 'pandas.core.frame.DataFrame'>
通過嵌套字典的方式創建數據框
dict3={'one':{'a':1,'b':2,'c':3,'d':4}, 'two':{'a':5,'b':6,'c':7,'d':8}, 'three':{'a':9,'b':10,'c':11,'d':12}} print("字典3-嵌套字典:",dict3) print("字典3的類型",type(dict3)) df3=pd.DataFrame(dict3) print("數據框3: ",df3) print("數據框3的類型:",type(df3))
字典3-嵌套字典: {'one': {'a': 1, 'b': 2, 'c': 3, 'd': 4}, 'two': {'a': 5, 'b': 6, 'c': 7, 'd': 8}, 'three': {'a': 9, 'b': 10, 'c': 11, 'd': 12}} 字典3的類型 <class 'dict'> 數據框3: one three two a 1 9 5 b 2 10 6 c 3 11 7 d 4 12 8 數據框3的類型: <class 'pandas.core.frame.DataFrame'>
有了DataFrame之後,這裡補充下如何通過DataFrame來創建Series。
s3=df3['one'] #直接拿出數據框3中第一列 print("序列3: ",s3) print("序列3的類型:",type(s3)) print("------------------------------------------------") s4=df3.iloc[0] #df3['a'] #直接拿出數據框3中第一行--iloc print("序列4: ",s4) print("序列4的類型:",type(s4))
序列3: a 1 b 2 c 3 d 4 Name: one, dtype: int64 序列3的類型: <class 'pandas.core.series.Series'> ------------------------------------------------ 序列4: one 1 three 9 two 5 Name: a, dtype: int64 序列4的類型: <class 'pandas.core.series.Series'>
2 數據索引index
無論數據框還是序列,最左側始終有一個非原始數據對象,這個就是接下來要介紹的數據索引。通過索引獲取目標數據,對數據進行一系列的操作。
2.1 通過索引值或索引標籤獲取數據
s5=pd.Series(np.array([1,2,3,4,5,6])) print(s5) #如果不給序列一個指定索引值,序列會自動生成一個從0開始的自增索引
0 1 1 2 2 3 3 4 4 5 5 6 dtype: int32
通過index屬性獲取序列的索引值
s5.index
RangeIndex(start=0, stop=6, step=1)
為index重新賦值
s5.index=['a','b','c','d','e','f'] s5
a 1 b 2 c 3 d 4 e 5 f 6 dtype: int32
通過索引獲取數據
s5[3]
4
s5['e']
5
s5[[1,3,5]]
b 2 d 4 f 6 dtype: int32
s5[:4]
a 1 b 2 c 3 d 4 dtype: int32
s5['c':]
c 3 d 4 e 5 f 6 dtype: int32
s5['b':'e'] #通過索引標籤獲取數據,末端標籤的數據也是返回的,
b 2 c 3 d 4 e 5 dtype: int32
2.2 自動化對齊
#當對兩個 s6=pd.Series(np.array([10,15,20,30,55,80]),index=['a','b','c','d','e','f']) print("序列6:",s6) s7=pd.Series(np.array([12,11,13,15,14,16]),index=['a','c','g','b','d','f']) print("序列7:",s7) print(s6+s7) #s6中不存在g索引,s7中不存在e索引,所以數據運算會產生兩個缺失值NaN。 #可以注意到這裡的算術運算自動實現了兩個序列的自動對齊 #對於數據框的對齊,不僅是行索引的自動對齊,同時也會對列索引進行自動對齊,數據框相當於二維數組的推廣 print(s6/s7)
序列6: a 10 b 15 c 20 d 30 e 55 f 80 dtype: int32 序列7: a 12 c 11 g 13 b 15 d 14 f 16 dtype: int32 a 22.0 b 30.0 c 31.0 d 44.0 e NaN f 96.0 g NaN dtype: float64 a 0.833333 b 1.000000 c 1.818182 d 2.142857 e NaN f 5.000000 g NaN dtype: float64
3 pandas查詢數據
通過布爾索引有針對的選取原數據的子集,指定行,指定列等。
test_data=pd.read_csv('test_set.csv') # test_data.drop(['ID'],inplace=True,axis=1) test_data.head()

非數值值特徵數值化
test_data['job'],jnum=pd.factorize(test_data['job']) test_data['job']=test_data['job']+1 test_data['marital'],jnum=pd.factorize(test_data['marital']) test_data['marital']=test_data['marital']+1 test_data['education'],jnum=pd.factorize(test_data['education']) test_data['education']=test_data['education']+1 test_data['default'],jnum=pd.factorize(test_data['default']) test_data['default']=test_data['default']+1 test_data['housing'],jnum=pd.factorize(test_data['housing']) test_data['housing']=test_data['housing']+1 test_data['loan'],jnum=pd.factorize(test_data['loan']) test_data['loan']=test_data['loan']+1 test_data['contact'],jnum=pd.factorize(test_data['contact']) test_data['contact']=test_data['contact']+1 test_data['month'],jnum=pd.factorize(test_data['month']) test_data['month']=test_data['month']+1 test_data['poutcome'],jnum=pd.factorize(test_data['poutcome']) test_data['poutcome']=test_data['poutcome']+1 test_data.head()

查詢數據的前5行
test_data.head()

查詢數據的末尾5行
test_data.tail()

查詢指定的行
test_data.iloc[[0,2,4,5,7]]

查詢指定的列
test_data[['age','job','marital']].head()

查詢指定的行和列
test_data.loc[[0,2,4,5,7],['age','job','marital']]

查詢年齡為51的資訊
#通過布爾索引實現數據的自己查詢 test_data[test_data['age']==51].head()

查詢工作為5以上的年齡在51的資訊
test_data[(test_data['age']==51) & (test_data['job']>=5)].head()

查詢工作為5以上,年齡在51的人員,並且只選取指定列
#只選取housing,loan,contac和poutcome test_data[(test_data['age']==51) & (test_data['job']>=5)][['education','housing','loan','contact','poutcome']].head()

可以看到,當有多個條件的查詢,需要在&或者|的兩端的條件括起來
4 對DataFrames進行統計分析
Pandas為我們提供了很多描述性統計分析的指標函數,包括,總和,均值,最小值,最大值等。
a=np.random.normal(size=10) d1=pd.Series(2*a+3) d2=np.random.f(2,4,size=10) d3=np.random.randint(1,100,size=10) print(d1) print(d2) print(d3)
0 5.811077 1 2.963418 2 2.295078 3 0.279647 4 6.564293 5 1.146455 6 1.903623 7 1.157710 8 2.921304 9 2.397009 dtype: float64 [0.18147396 0.48218962 0.42565903 0.10258942 0.55299842 0.10859328 0.66923199 1.18542009 0.12053079 4.64172891] [33 17 71 45 33 83 68 41 69 23]
非空元素的計算
d1.count()
10
最小值
d1.min()
0.6149265534311872
最大值
d1.max()
6.217953512253818
最小值的位置
d1.idxmin()
8
最大值的位置
d1.idxmax()
1
10%分位數
d1.quantile(0.1)
1.4006153623854274
求和
d1.sum()
27.43961378467516
平均數
d1.mean()
2.743961378467515
中位數
d1.median()
2.3460435427041384
眾數
d1.mode()
0 0.279647 1 1.146455 2 1.157710 3 1.903623 4 2.295078 5 2.397009 6 2.921304 7 2.963418 8 5.811077 9 6.564293 dtype: float64
方差
d1.var()
4.027871738323722
標準差
d1.std()
2.0069558386580715
平均絕對偏差
d1.mad()
1.456849211331346
偏度
d1.skew()
1.0457755613918738
峰度
d1.kurt()
0.39322767370407874
一次性輸出多個描述性統計指標
d1.describe()
count 10.000000 mean 2.743961 std 2.006956 min 0.279647 25% 1.344189 50% 2.346044 75% 2.952890 max 6.564293 dtype: float64
#自定義一個函數,將這些統計描述指標全部匯總到一起 def stats(x): return pd.Series([x.count(),x.min(),x.idxmin(),x.quantile(.25),x.median(), x.quantile(.75),x.mean(),x.max(),x.idxmax(),x.mad(),x.var(),x.std(),x.skew(),x.kurt()], index=['Count','Min','Which_Min','Q1','Median','Q3','Mean','Max','Which_Max','Mad','Var','Std','Skew', 'Kurt'])
stats(d1)
Count 10.000000 Min 0.279647 Which_Min 3.000000 Q1 1.344189 Median 2.346044 Q3 2.952890 Mean 2.743961 Max 6.564293 Which_Max 4.000000 Mad 1.456849 Var 4.027872 Std 2.006956 Skew 1.045776 Kurt 0.393228 dtype: float64
對於數字型數據,它是直接統計一些數據性描述,觀察這一系列數據的範圍。大小、波動趨勢,便於判斷後續對數據採取哪類模型更合適。
#當實際工作中我們需要處理的是一系列的數值型數據框,可以使用apply函數將這個stats函數應用到數據框中的每一列 df=pd.DataFrame(np.array([d1,d2,d3]).T,columns=['x1','x2','x3']) #將之前創建的d1,d2,d3數據構建數據框 print(df.head()) df.apply(stats)
x1 x2 x3 0 5.811077 0.181474 33.0 1 2.963418 0.482190 17.0 2 2.295078 0.425659 71.0 3 0.279647 0.102589 45.0 4 6.564293 0.552998 33.0

以上很簡單的創建了數值型數據的統計性描述,但對於離散型數據就不能使用該方法了。我們在統計離散變數的觀測數、唯一值個數、眾數水平及個數,只需要使用describe方法就可以實現這樣的統計了。
train_data=pd.read_csv('train_set.csv') # test_data.drop(['ID'],inplace=True,axis=1) train_data.head()

train_data['job'].describe() #離散型數據的描述
count 25317 unique 12 top blue-collar freq 5456 Name: job, dtype: object
test_data['job'].describe() #數值型數據的描述
count 10852.000000 mean 5.593255 std 2.727318 min 1.000000 25% 3.000000 50% 6.000000 75% 8.000000 max 12.000000 Name: job, dtype: float64
除了以上簡單的描述性統計之外,還提供了連續變數的相關係數(corr)和協方差(cov)的求解
df

df.corr() #相關係數的計算方法可以調用pearson方法、kendall方法、或者spearman方法,默認使用的是pearson方法

df.corr('spearman')

df.corr('pearson')

df.corr('kendall')

#如果只關注某一個變數與其餘變數的相關係數的話,可以使用corrwith,如下方只關注x1與其餘變數的相關係數 df.corrwith(df['x1'])
x1 1.000000 x2 -0.075466 x3 -0.393609 dtype: float64
#數值型變數間的協方差矩陣 df.cov()

OK,今天的pandas實操演示就到這裡,剩下的內容我們下期見。
上期問題:
你是淘寶的數據分析師,現在需要你預估雙十一的銷量,你不能獲得雙十一當天和之前的所有數據。只能獲得11月12日開始的數據,你應該如何預估?
答案解析:
因為是開放題,所以沒有固定答案,大家的回答分為兩類:
- 一類是通過後續雙十一的銷量,判斷16年,缺點是需要等一年,優點是簡單到不像話。
- 二類是通過11月12日之後的銷量數據,往前預估,期間會考慮一些權重。缺點是雙十一屬於波峰,預估難度大,優點是可操作性好。
因為題目主要看的是分析思維,目的是找出可能的思路,所以有沒有其他的方法呢?我們嘗試把思維放開,因為銷量能反應商品,有沒有其他維度?
我們可能會想到:退換貨率、和商品評價率。因為雙十一的商品只能在12日後退換貨和收貨後評價,我們就能根據這兩個指標平日的平均比率,以及雙十一商品的後續退換和評價總數,預估賣出總量。退換貨率肯定會虛高一些(畢竟雙十一退貨不少),那麼商品評價率更準確。
還有其他方法么?當然有,比如會有不少人用螞蟻花唄支付雙十一,那麼後續還款的比率能不能預估?
如果再將思路放開呢?雖然我不知道淘寶當天的數據,但是可以尋求外部數據,比如京東,京東的雙十一銷量是多少,是平時的多少倍,那麼就用這個倍數去預估淘寶的。
整體的分析結構就分為:
外部數據:
- 京東等其他平台雙十一銷量
內部數據:
- 商品數據-商品評價率、退換貨率、商品銷量
- 支付數據-螞蟻花唄支付比率等