天天看點

Pandas-進階處理(七):透視表(pivot_table)【以指定列作為行索引對另一指定列的值進行分組聚合操作】、交叉表(crosstab)【統計頻率】一、透視表二、交叉表三、案例分析

交叉表與透視表的作用

  • 交叉表:計算一列資料對于另外一列資料的分組個數
  • 透視表:指定某一列對另一列的關系

一、透視表

透視表是一種可以對資料動态排布并且分類彙總的表格格式。

透視表:透視表是将原有的DataFrame的列分别作為行索引和列索引,然後對指定的列應用聚集函數

  • data.pivot_table()
  • DataFrame.pivot_table([], index=[])

比如:

pd.pivot_table(data=df, index='date', values='values', aggfunc=np.sum)

以 date 列作為行索引對values列進行分組聚合(sum)操作。

import numpy as np
import pandas as pd

# 透視表:pivot_table
# pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')

date = ['2017-5-1', '2017-5-2', '2017-5-3'] * 3
rng = pd.to_datetime(date)
df = pd.DataFrame({'date': rng,
                   'key': list('abcdabcda'),
                   'values': np.random.rand(9) * 10})
print("df = \n", df)
print('-' * 200)

# data:DataFrame對象
# values:要聚合的列或列的清單
# index:資料透視表的index,從原資料的列中篩選
# columns:資料透視表的columns,從原資料的列中篩選
# aggfunc:用于聚合的函數,預設為numpy.mean,支援numpy計算方法

x1 = pd.pivot_table(data=df, values='values', index='date', aggfunc=np.sum)  # 也可以寫 aggfunc='sum'
print("x1 = pd.pivot_table(data=df, values='values', index='date', aggfunc=np.sum) = \n", x1)
print('-' * 200)

# 這裡就分别以date、key共同做資料透視,值為values:統計不同(date,key)情況下values的和
# aggfunc=len(或者count):計數
x2 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=np.sum)
print("x2 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=np.sum) = \n", x2)
print('-' * 200)

# 這裡就分别以date、key共同做資料透視,值為values:統計不同(date,key)情況下values的長度【aggfunc=len:計數】
x3 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=len)
print("x3 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=len) = \n", x3)
print('-' * 200)
           

列印結果:

df = 
         date key    values
0 2017-05-01   a  6.331764
1 2017-05-02   b  0.139295
2 2017-05-03   c  7.775829
3 2017-05-01   d  0.366474
4 2017-05-02   a  9.533083
5 2017-05-03   b  0.671094
6 2017-05-01   c  5.951416
7 2017-05-02   d  5.920482
8 2017-05-03   a  6.119202
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x1 = pd.pivot_table(data=df, values='values', index='date', aggfunc=np.sum) = 
                values
date                 
2017-05-01  12.649654
2017-05-02  15.592859
2017-05-03  14.566126
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x2 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=np.sum) = 
                   values
date       key          
2017-05-01 a    6.331764
           c    5.951416
           d    0.366474
2017-05-02 a    9.533083
           b    0.139295
           d    5.920482
2017-05-03 a    6.119202
           b    0.671094
           c    7.775829
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x3 = pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=len) = 
                 values
date       key        
2017-05-01 a       1.0
           c       1.0
           d       1.0
2017-05-02 a       1.0
           b       1.0
           d       1.0
2017-05-03 a       1.0
           b       1.0
           c       1.0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Process finished with exit code 0
           

二、交叉表

交叉表:交叉表用于計算一列資料對于另外一列資料的分組個數(用于統計分組頻率的特殊透視表)

  • pd.crosstab(value1, value2)
import numpy as np
import pandas as pd

# 交叉表:crosstab
# 預設情況下,crosstab計算因子的頻率表,比如用于str的資料透視分析
# pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)

df = pd.DataFrame({'A': [1, 2, 2, 2, 2],
                   'B': [3, 3, 4, 4, 4],
                   'C': [1, 1, np.nan, 1, 1]})
print("df = \n", df)
print('-' * 200)

# 如果crosstab隻接收兩個Series,它将提供一個頻率表。
# 用A的唯一值,統計B唯一值的出現次數
x1 = pd.crosstab(df['A'], df['B'])
print("pd.crosstab(df['A'], df['B']) = \n", x1)
print('-' * 200)

# normalize:預設False,将所有值除以值的總和進行歸一化 → 為True時候顯示百分比
x2 = pd.crosstab(df['A'], df['B'], normalize=True)
print("x2 = pd.crosstab(df['A'], df['B'], normalize=True) = \n", x2)
print('-' * 200)

# values:可選,根據因子聚合的值數組
# aggfunc:可選,如果未傳遞values數組,則計算頻率表,如果傳遞數組,則按照指定計算
# 這裡相當于以A和B界定分組,計算出每組中第三個系列C的值
x3 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum)
print("x3 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum) = \n", x3)
print('-' * 200)

# margins:布爾值,預設值False,添加行/列邊距(小計)
x4 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum, margins=True)
print("x4 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum, margins=True) = \n", x4)
print('-' * 200)
           

列印結果:

df = 
    A  B    C
0  1  3  1.0
1  2  3  1.0
2  2  4  NaN
3  2  4  1.0
4  2  4  1.0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pd.crosstab(df['A'], df['B']) = 
 B  3  4
A      
1  1  0
2  1  3
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x2 = pd.crosstab(df['A'], df['B'], normalize=True) = 
 B    3    4
A          
1  0.2  0.0
2  0.2  0.6
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x3 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum) = 
 B    3    4
A          
1  1.0  NaN
2  1.0  2.0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x4 = pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum, margins=True) = 
 B      3    4  All
A                 
1    1.0  NaN  1.0
2    1.0  2.0  3.0
All  2.0  2.0  4.0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Process finished with exit code 0
           

三、案例分析

1 交叉表與透視表什麼作用

探究股票的漲跌與星期幾有關?

以下圖當中表示,week代表星期幾,1,0代表這一天股票的漲跌幅是好還是壞,裡面的資料代表比例

可以了解為所有時間為星期一等等的資料當中漲跌幅好壞的比例

Pandas-進階處理(七):透視表(pivot_table)【以指定列作為行索引對另一指定列的值進行分組聚合操作】、交叉表(crosstab)【統計頻率】一、透視表二、交叉表三、案例分析
Pandas-進階處理(七):透視表(pivot_table)【以指定列作為行索引對另一指定列的值進行分組聚合操作】、交叉表(crosstab)【統計頻率】一、透視表二、交叉表三、案例分析

2 案例分析

2.1 資料準備

  • 準備兩列資料,星期資料以及漲跌幅是好是壞資料
  • 進行交叉表計算
# 尋找星期幾跟股票張得的關系
# 1、先把對應的日期找到星期幾
date = pd.to_datetime(data.index).weekday
data['week'] = date

# 2、假如把p_change按照大小去分個類0為界限
data['posi_neg'] = np.where(data['p_change'] > 0, 1, 0)

# 通過交叉表找尋兩列資料的關系
count = pd.crosstab(data['week'], data['posi_neg'])
           

但是我們看到count隻是每個星期日子的好壞天數,并沒有得到比例,該怎麼去做?

  • 對于每個星期一等的總天數求和,運用除法運算求出比例
# 算數運算,先求和
sum = count.sum(axis=1).astype(np.float32)

# 進行相除操作,得出比例
pro = count.div(sum, axis=0)
           

2.2 檢視效果

使用plot畫出這個比例,使用stacked的柱狀圖

pro.plot(kind='bar', stacked=True)
plt.show()
           
Pandas-進階處理(七):透視表(pivot_table)【以指定列作為行索引對另一指定列的值進行分組聚合操作】、交叉表(crosstab)【統計頻率】一、透視表二、交叉表三、案例分析

2.3 使用pivot_table(透視表)實作

使用透視表,剛才的過程更加簡單

# 通過透視表,将整個過程變成更簡單一些
data_pivot = data.pivot_table(['posi_neg'], index='week')
data_pivot.plot(kind="bar")
plt.show()
           
Pandas-進階處理(七):透視表(pivot_table)【以指定列作為行索引對另一指定列的值進行分組聚合操作】、交叉表(crosstab)【統計頻率】一、透視表二、交叉表三、案例分析

繼續閱讀