字符串處理
Pandas爲字符串提供了形如“obj.str.方法()”的一系列命令支持,這些方法一般在數據清洗、轉換時使用。
s = Series(['Beauty and the Beast', 'Captain America: Civil War',
'Jurassic World', 'Toy Story'])
help(s.str) # 顯示 s.str幫助
s.str.len() # 返回字符串長度
s.str.split() # 分割字符串
s.str[:6] # 字符串切片
s.str.contains('War') # 測試電影名中是否包含War
s.str.lower().str.contains('war') # 轉小寫再測是否含war
s.str.replace(' ', '-') # 字符替換,用橫線- 替換空格
分組統計
Pandas支持數據分組,功能類似數據庫中的group by(分組統計)。
df = pd.DataFrame({'color': ['red', 'white', 'black', 'red', 'black', 'red'], 'size':
['s','m','b','s','m','b'], 'price': [10, 11, 12, 20, 21, 22], 'quantity': [1, 2, 3, 3, 4, 5]})
g = df.groupby('color') # 按color分組
g是一個DataFrameGroupBy對象,它實際上還沒有進行任何分組統計,
僅含有一些分組如何劃分的關鍵信息。分組鍵有多種形式:
某個列或列的組合。
列表或數組,其長度與待分組的軸⼀樣
字典或Series,給出待分組軸上的值與分組名之間的對應關係。
函數,用於處理數據或標籤。
分組對象的屬性和方法
g.ngroups # ngroups分組數
g.groups # 列出每個分組包含的數據索引編號
for name, group in g:
print(name) # 輸出組名
print(group) # 組內容
g.size() # 列出每個分組的數據條數
g.sum() # sum只對數值列求和,非數值列未顯示
g.get_group('black') # 指定返回black組數據
g.head(2) # 取每個分組的頭2個數據
g.nth(0) # 取每組的第0個數據
g.price.describe() # 對price列做describe,得到一組常用統計量
分組對象有一個aggregate合計方法(簡寫爲agg),它允許傳遞多個統計函數,因此可以一次性得到多個統計值。
# 對quantity列求和、均值、最大值、最小值
g.quantity.agg((np.sum, np.mean, np.max, np.min))
g.quantity.agg([('均值','mean'), ('最大值','max')]) # 定義列名
練習
m = pd.read_excel('movie.xlsx') # 月度票房前10名 2008-2019
m = m[m.MovieName!='其他']
g = m.groupby(m.month.str[:4]) # 按年分組 2019-01
g.boxoffice.sum() # 按年彙總 票房
g.boxoffice.sum() / m.boxoffice.sum() # 比率
g1 = m.groupby('MovieName') # 按電影名分組
g1.size().sort_values(ascending=False)[:10] # 月度排名出現次數最多,先是按照名字來分組的,然後根據分組後的值來進行排序
# 多級索引分組
s = Series(np.arange(5), index=[list('xxyyx'),list('rbrbb')])
g = s.groupby(level=0) # 按0級索引分組
g.size()
g.agg(lambda x:(x.max(), x.min()) ) # 返回每個分組的最大/最小值
數據透視表
Excel中有一個數據透視表功能,Pandas提供了類似的命令pivot_table()。
df.pivot_table(index='color', columns='size', values='quantity', aggfunc='sum')
color作爲行索引,size是列索引,裏面的值是quantity,計算方法是sum求和
參數表中index指定分組索引列,columns指定列名,values指定要計算的列,aggfunc指定計算方法。例如,'sum’是求和,'mean’是求平均值,'count’是計數。
時間序列
Pandas最初研發的目的是作爲金融數據分析包,因此提供了豐富的時間序列處理方法。時間序列做索引,運算時會自動按日期對齊。
Pandas中的時間函數
to_datetime()
將字符串轉換爲時間,識別不同格式的日期字符串。
pd.to_datetime('2019-2-20') # 年-月-日
Out: Timestamp('2019-02-20 00:00:00')
pd.to_datetime(['2/20/2019', '2019.2.20']) #不同格式日期字符串都可轉換
Out: DatetimeIndex(['2019-02-20', '2019-02-20'], dtype='datetime64[ns]')
pd.to_datetime('2019-2-20 15:30:00') # 年-月-日 時:分:秒
Out: Timestamp('2019-02-20 15:30:00')
today = pd.datetime.now() # 生成今天的日期
today + pd.DateOffset(days=3) # 後推3天
# 將數據框df的索引類型轉爲日期型
df = pd.read_csv('stock.txt', index_col=0, encoding='cp936', sep='\s+')
df.index = pd.to_datetime(df.index)
date_range()
用於產生指定日期段內的一系列日期時間值。
pd.date_range(起始日期, 結束日期, periods=週期數, freq=日期頻率)
date_range函數的常用freq參數表
pd.date_range('2019-02-01', '2019-02-28') # 默認頻率1天
pd.date_range('2019-02-01', '2019-02-28', freq='3D') # 頻率爲每3天
pd.date_range('2019-01-01', periods=6, freq='3D') # 每3天1個日期
shift()
有時需要對日期序列做shift(移動)轉換,以計算相鄰日期間的數據變動。
np.random.seed(7)
dates = pd.date_range('2018-9-1', periods=4) # 生成4個日期索引值
s = Series(np.random.rand(4), index=dates)
s.shift(1) # 後移一個數據位
s.shift(-2) # 前移兩個數據位
s - s.shift(1) # 計算後一天相對前一天的變動值, s.pct_change()
((s - s.shift(1)) / s.shift(1)).map(lambda x: format(x, '.2%')) # 變動百分比並格式化
s - s.shift(1) 會自動對齊日期索引,完成相同日期的數值相減。
時間頻率變換
用時間作爲索引時,可以方便地按時間段查看數據。對時間序列數據可用resample()方法按不同頻率進行重採樣,然後對樣本進行計算。
np.random.seed(7)
dates = pd.date_range('2018-1-1', periods=365)
s = Series(np.random.randn(365), index=dates) # 2018年模擬數據
s['2018-1'] # 選取2018年1月的數據
s['2018-02' : '2018-04'] # 選取2018年2月至4月的數據
s.resample("1M").mean() # 按月求均值
s.resample("10D").sum() # 每10天求和
# 每10天一次採樣,返回每組樣本的最大值、最小值
s.resample("10D").agg([np.max, np.min])
練習
股票每日的漲跌幅在區間[-10%, 10%]內,且只在週一到週五交易。
先設置隨機數種子爲7,試生成模擬一隻股票2019年全年交易日的漲跌幅數據。然後計算:
(1)該股票2019年的年漲跌幅。
(2)統計12個月中漲幅最大的月份和跌幅最大的月份。
import pandas as pd
np.random.seed(7)
dates = pd.date_range('2019-1-1', '2019-12-31', freq='B')# 全年漲跌數據, B 商業日
df = pd.DataFrame(np.random.uniform(-0.1, 0.1, len(dates)), index=dates, columns=['rate'])
for x in ['2019-1-1', '2019-5-1', '2019-10-1']:
if x in df.index: # 剔除不交易的節假日
df.drop(pd.to_datetime(x), inplace=True)
df['percent'] = df['rate'] + 1 # 加1調整爲正值百分比,調整後範圍爲[0.9, 1.1]
yearrate = df['percent'].prod() # 累乘計算全年漲跌幅
print('全年漲跌幅爲:{:.2%}'.format(yearrate - 1))
mrate = df.resample('1m')['percent'].prod() # 按月採樣
print('全年按月份漲跌幅如下:\n', (mrate - 1).apply(lambda x: format(x, '.2%')))
s = (mrate - 1).sort_values()
print('跌幅最大的月份是:', str(s.index[0])[:7])
print('漲幅最大的月份是:', str(s.index[-1])[:7])