Pandas 常見操作詳解
很多人有誤解,總以為Pandas跟熊貓有點關系,跟gui叔創建Python一樣覺得Pandas是某某奇葩程序員喜歡熊貓就以此命名,簡單介紹一下,Pandas的命名來自於面板數據這個概念,即Panel datas ,說起面板我想很多人腦海里第一印象會是寶塔,這里對面板數據不做過多介紹,有興趣的可以自行百度。 Pandas的功能有多強大不需要我過多解釋,有人拿Excel和它對比,兩者很顯然不在同一水平。當然,對Python一竅不通的初學者可能覺得Pandas一點都不友好,Pandas其實並不需要太多Python基礎,但是很多語法有類似的地方。
版本的選擇,其實2.7版本和3.x版本個人覺得差距並不大,如果非要做一個選擇,我是這樣推薦,我覺得如果你是在校學生,我建議3.x版本學起吧,2.7停止更新,而且不久就要停止技術支持了,要學就學有未來的嘛。如果是馬上找工作,或者馬上要進入工作環境得的同學,我更建議使用2.7版本,以為畢竟現在還是2.7版本的天下,大多數程序都是用2.7寫的。但是學到最后,你會發現兩者之間語法差距並不大,很容易可以駕馭兩個版本。廢話不多說了,進入主題。
一、安裝模塊
具體內容進入這篇博客:https://www.cnblogs.com/weidu/p/9831980.html
二、引入模塊
將pandas作為第三方庫導入,我們一般為pandas取一個別名叫做pd
import pandas as pd
三、導入數據
df = pd.read_csv( # 該參數為數據在電腦中的路徑,可以不填寫 filepath_or_buffer='/Users/Weidu/Desktop/sz000002.csv', # 該參數代表數據的分隔符,csv文件默認是逗號。其他常見的是'\t' sep=',', # 該參數代表跳過數據文件的的第1行不讀入 skiprows=1, # nrows,只讀取前n行數據,若不指定,讀入全部的數據 nrows=15, # 將指定列的數據識別為日期格式。若不指定,時間數據將會以字符串形式讀入。一開始先不用。 # parse_dates=['交易日期'], # 將指定列設置為index。若不指定,index默認為0, 1, 2, 3, 4... # index_col=['交易日期'], # 讀取指定的這幾列數據,其他數據不讀取。若不指定,讀入全部列 usecols=['交易日期', '股票代碼', '股票名稱', '收盤價', '漲跌幅', '成交量', '新浪概念', 'MACD_金叉死叉'], # 當某行數據有問題時,報錯。設定為False時即不報錯,直接跳過該行。當數據比較臟亂的時候用這個。 error_bad_lines=False, # 將數據中的null識別為空值 na_values='NULL',
)
調整上列參數,使用print函數觀察變化 print(df) #2.7版本 print df
注意:
- 使用read_csv導入數據非常方便
- 導入的數據的數據類型是DataFrame。
- 導入數據主要使用read系列函數
- 還有read_table、read_excel、read_json等,他們的參數內容都是大同小異,可以自行搜索查看
四、查看數據常用操作
print(df.shape) # 輸出dataframe有多少行、多少列。
print(df.shape[0]) # 取行數量,相應的列數量就是df.shape[1]
print(df.columns) # 順序輸出每一列的名字,演示如何for語句遍歷。
print(df.index) # 順序輸出每一行的名字,可以for語句遍歷。
print(df.dtypes) # 數據每一列的類型不一樣,比如數字、字符串、日期等。該方法輸出每一列變量類型
print(df.head(3)) # 看前3行的數據,默認是5。與自然語言很接近
print(df.tail(3)) # 看最后3行的數據,默認是5。
print(df.sample(n=3)) # 隨機抽取3行,想要去固定比例的話,可以用frac參數
print(df.describe()) # 非常方便的函數,對每一列數據有直觀感受;只會對數字類型的列有效
五、對print出的數據格式進行修正
pd.set_option('expand_frame_repr', False) # 當列太多時不換行
pd.set_option('max_colwidth', 8) # 設定每一列的最大寬度,恢復原設置的方法,pd.reset_option('max_colwidth')
更多設置請見http://pandas.pydata.org/pandas-docs/stable/options.html
六、如何選取指定的行、列
print(df['股票代碼']) # 根據列名稱來選取,讀取的數據是Series類型
print(df[['股票代碼', '收盤價']]) # 同時選取多列,需要兩個括號,讀取的數據是DataFrame類型
print(df[[0, 1, 2]]) # 也可以通過列的position來選取
七、loc操作:通過label(columns和index的名字)來讀取數據
print(df.loc['12/12/2016']) # 選取指定的某一行,讀取的數據是Series類型 print(df.loc['13/12/2016': '06/12/2016']) # 選取在此范圍內的多行,和在list中slice操作類似,讀取的數據是DataFrame類型 print(df.loc[:, '股票代碼':'收盤價']) # 選取在此范圍內的多列,讀取的數據是DataFrame類型 print(df.loc['13/12/2016': '06/12/2016', '股票代碼':'收盤價']) # 讀取指定的多行、多列。逗號之前是行的范圍,逗號之后是列的范圍。讀取的數據是DataFrame類型 print(df.loc[:, :]) # 讀取所有行、所有列,讀取的數據是DataFrame類型 print(df.at['12/12/2016', '股票代碼']) # 使用at讀取指定的某個元素。loc也行,但是at更高效。
八、iloc操作:通過position來讀取數據
print(df.iloc[0]) # 以index選取某一行,讀取的數據是Series類型 print(df.iloc[1:3]) # 選取在此范圍內的多行,讀取的數據是DataFrame類型 print(df.iloc[:, 1:3]) # 選取在此范圍內的多列,讀取的數據是DataFrame類型 print(df.iloc[1:3, 1:3]) # 讀取指定的多行、多列,讀取的數據是DataFrame類型 print(df.iloc[:, :]) # 讀取所有行、所有列,讀取的數據是DataFrame類型 print(df.iat[1, 1]) # 使用iat讀取指定的某個元素。使用iloc也行,但是iat更高效。
九、列操作
行列加減乘除
print(df['股票名稱'] + '_地產') # 字符串列可以直接加上字符串,對整列進行操作 print(df['收盤價'] * 100) # 數字列直接加上或者乘以數字,對整列進行操作。 print(df['收盤價'] * df['成交量']) # 兩列之間可以直接操作。收盤價*成交量計算出的是什么?
新增一列
df['股票名稱+行業'] = df['股票名稱'] + '_地產'
十、統計函數
print(df['收盤價'].mean()) # 求一整列的均值,返回一個數。會自動排除空值。 print(df[['收盤價', '成交量']].mean()) # 求兩列的均值,返回兩個數,Series print(df[['收盤價', '成交量']]) print(df[['收盤價', '成交量']].mean(axis=1)) # 求兩列的均值,返回DataFrame。axis=0或者1要搞清楚。 #axis=1,代表對整幾列進行操作。axis=0(默認)代表對幾行進行操作。實際中弄混很正常,到時候試一下就知道了。 print(df['收盤價'].max()) # 最大值 print(df['收盤價'].min()) # 最小值 print(df['收盤價'].std()) # 標准差 print(df['收盤價'].count()) # 非空的數據的數量 print(df['收盤價'].median()) # 中位數 print(df['收盤價'].quantile(0.25)) # 25%分位數
還有其他的函數計算其他的指標,在實際使用中遇到可以自己搜索
十一、shift類函數、刪除列的方式
df['昨天收盤價'] = df['收盤價'].shift(-1) # 讀取上一行的數據,若參數設定為3,就是讀取上三行的數據;若參數設定為-1,就是讀取下一行的數據; print(df[['收盤價', '昨天收盤價']]) del df['昨天收盤價'] # 刪除某一列的方法 df['漲跌'] = df['收盤價'].diff(-1) # 求本行數據和上一行數據相減得到的值 print(df[['收盤價', '漲跌']]) df.drop(['漲跌'], axis=1, inplace=True) # 刪除某一列的另外一種方式,inplace參數指是否替代原來的df print(df) df['漲跌幅_計算'] = df['收盤價'].pct_change(-1) # 類似於diff,但是求的是兩個數直接的比例,相當於求漲跌幅
十二、cum(cumulative)類函數
df['成交量_cum'] = df['成交量'].cumsum() # 該列的累加值 print(df[['成交量', '成交量_cum']]) print((df['漲跌幅'] + 1.0).cumprod()) # 該列的累乘值,此處計算的就是資金曲線,假設初始1元錢。
十三、其他列函數
df['收盤價_排名'] = df['收盤價'].rank(ascending=True, pct=False) # 輸出排名。ascending參數代表是順序還是逆序。pct參數代表輸出的是排名還是排名比例 print(df[['收盤價', '收盤價_排名']]) del df['收盤價_排名'] print(df['股票代碼'].value_counts()) # 計數。統計該列中每個元素出現的次數。返回的數據是Series
十四、篩選操作,根據指定的條件,篩選出相關拿數據
print(df['股票代碼'] == 'sh000002') # 判斷股票代碼是否等於sz000002 print(df[df['股票代碼'] == 'sz000002']) # 將判斷為True的輸出:選取股票代碼等於sz000002的行 print(df[df['股票代碼'].isin(['sz000002', 'sz000003 ', 'sz000004'])]) # 選取股票代碼等於sz000002的行 print(df[df['收盤價'] >= 24.0]) # 選取收盤價大於24的行 print(df[(df.index >= '03/12/2016') & (df.index <= '06/12/2016')]) # 兩個條件,或者的話就是|
十五、缺失值處理:原始數據中存在缺失值,如何處理?
刪除缺失值
print(df.dropna(how='any')) # 將帶有空值的行刪除。how='any'意味着,該行中只要有一個空值,就會刪除,可以改成all。 print(df.dropna(subset=['MACD_金叉死叉', '漲跌幅'], how='all')) # subset參數指定在特定的列中判斷空值。 #all代表全部為空,才會刪除該行;any只要一個為空,就刪除該行。
補全缺失值
print(df.fillna(value='沒有金叉死叉')) # 直接將缺失值賦值為固定的值 df['MACD_金叉死叉'].fillna(value=df['收盤價'], inplace=True) # 直接將缺失值賦值其他列的數據 print(df.fillna(method='ffill')) # 向上尋找最近的一個非空值,以該值來填充缺失的位置,全稱forward fill,非常有用 print(df.fillna(method='bfill')) # 向下尋找最近的一個非空值,以該值來填充確實的位置,全稱backward fill
找出缺失值
print(df.notnull()) # 判斷是否為空值,反向函數為isnull() print(df[df['MACD_金叉死叉'].notnull()]) # 將'MACD_金叉死叉'列為空的行輸出
十六、排序函數
df.reset_index(inplace=True) print(df.sort_values(by=['交易日期'], ascending=1)) # by參數指定按照什么進行排序,acsending參數指定是順序還是逆序,1順序,0逆序 print(df.sort_values(by=['股票名稱', '交易日期'], ascending=[1, 1])) # 按照多列進行排序
十七、兩個df上下合並操作,append操作
df.reset_index(inplace=True) df1 = df.iloc[0:10][['交易日期', '股票代碼', '收盤價', '漲跌幅']] print(df1) df2 = df.iloc[5:15][['交易日期', '股票名稱', '收盤價', '漲跌幅']] print(df2) print(df1.append(df2)) # append操作,將df1和df2上下拼接起來。注意觀察拼接之后的index df3 = df1.append(df2, ignore_index=True) # ignore_index參數,用戶重新確定index print(df3)
十八、對數據進行去重
df3中有重復的行數,我們如何將重復的行數去除?
#df3中有重復的行數,我們如何將重復的行數去除? df3.drop_duplicates( subset=['收盤價', '交易日期'], # subset參數用來指定根據哪類類數據來判斷是否重復。若不指定,則用全部列的數據來判斷是否重復 keep='first', # 在去除重復值的時候,我們是保留上面一行還是下面一行?first保留上面一行,last保留下面一行,False就是一行都不保留 inplace=True ) print(df3)
十九、其他常用重要函數
print(df.rename(columns={'MACD_金叉死叉': '金叉死叉', '漲跌幅': '漲幅'})) # rename函數給變量修改名字。使用dict將要修改的名字傳給columns參數 print(df.empty) # 判斷一個df是不是為空,此處輸出不為空 print(pd.DataFrame().empty) # pd.DataFrame()創建一個空的DataFrame,此處輸出為空 print(df.T) # 將數據轉置,行變成列,很有用
二十、字符串處理
print(df['股票代碼']) print('sz000002'[:2]) print(df['股票代碼'].str[:2]) print(df['股票代碼'].str.upper()) # 加上str之后可以使用常見的字符串函數對整列進行操作 print(df['股票代碼'].str.lower()) print(df['股票代碼'].str.len()) # 計算字符串的長度,length df['股票代碼'].str.strip() # strip操作,把字符串兩邊的空格去掉 print(df['股票代碼'].str.contains('sh')) # 判斷字符串中是否包含某些特定字符 print(df['股票代碼'].str.replace('sz', 'sh')) # 進行替換,將sz替換成sh
split操作
print(df['新浪概念'].str.split(';')) # 對字符串進行分割 print(df['新浪概念'].str.split(';').str[:2]) # 分割后取第一個位置 print(df['新浪概念'].str.split(';', expand=True)) # 分割后並且將數據分列
更多字符串函數請見:http://pandas.pydata.org/pandas-docs/stable/text.html#method-summary
二十一、時間處理
導入數據時將index參數注釋掉
df['交易日期'] = pd.to_datetime(df['交易日期']) # 將交易日期由字符串改為時間變量 print(df['交易日期']) print(df.iloc[0]['交易日期']) print(df.dtypes) print(pd.to_datetime('1999年01月01日')) # pd.to_datetime函數:將字符串轉變為時間變量 print(df.at[0, '交易日期']) print(df['交易日期'].dt.year) # 輸出這個日期的年份。相應的month是月份,day是天數,還有hour, minute, second print(df['交易日期'].dt.week) # 這一天是一年當中的第幾周 print(df['交易日期'].dt.dayofyear) # 這一天是一年當中的第幾天 print(df['交易日期'].dt.dayofweek) # 這一天是這一周當中的第幾天,0代表星期一 print(df['交易日期'].dt.weekday) # 和上面函數相同,更加常用 print(df['交易日期'].dt.weekday_name) # 和上面函數相同,返回的是星期幾的英文,用於報表的制作。 print(df['交易日期'].dt.days_in_month) # 這一天是這一月當中的第幾天 print(df['交易日期'].dt.is_month_end) # 這一天是否是該月的開頭,是否存在is_month_end? print(df['交易日期'] + pd.Timedelta(days=1)) # 增加一天,Timedelta用於表示時間差數據 print((df['交易日期'] + pd.Timedelta(days=1)) - df['交易日期']) # 增加一天然后再減去今天的日期
二十二、rolling、expanding操作
#計算'收盤價'這一列的均值 print(df['收盤價'].mean()) #如何得到每一天的最近3天收盤價的均值呢?即如何計算常用的移動平均線? #使用rolling函數 df['收盤價_3天均值'] = df['收盤價'].rolling(5).mean() print(df[['收盤價', '收盤價_3天均值']]) #rolling(n)即為取最近n行數據的意思,只計算這n行數據。后面可以接各類計算函數,例如max、min、std等 print(df['收盤價'].rolling(3).max()) print(df['收盤價'].rolling(3).min()) print(df['收盤價'].rolling(3).std())
rolling可以計算每天的最近3天的均值,如果想計算每天的從一開始至今的均值,應該如何計算?
#使用expanding操作 df['收盤價_至今均值'] = df['收盤價'].expanding().mean() print(df[['收盤價', '收盤價_至今均值']])
expanding即為取從頭至今的數據。后面可以接各類計算函數
print(df['收盤價'].expanding().max()) print(df['收盤價'].expanding().min()) print(df['收盤價'].expanding().std())
rolling和expanding簡直是為量化領域量身定制的方法,經常會用到。
二十三、輸出
print(df) df.to_csv('output.csv', encoding='gbk', index=False)
結語:以上基本上包含了所有常見函數,還有一些不常用函數沒寫,如果需要,請到官方文檔查詢:
http://pandas.pydata.org/pandas-docs/stable/api.html