import pandas as pd import numpy as np
導入文件
1.read_excel
Pandas能夠讀取很多文件:Excel、CSV、數據庫、TXT,甚至是在線的文件都是OK的
to_csv
-
DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None)
- path_or_buf :文件路徑
- sep :分隔符,默認用","隔開
- columns :選擇需要的列索引
- header :boolean or list of string, default True,是否寫進列索引值
- index:是否寫進行索引
- mode:‘w’:重寫, ‘a’ 追加
舉例:保存讀取出來的股票數據
保存’open’列的數據,然后讀取查看結果:
# 選取10行數據保存,便於觀察數據 data[:10].to_csv("./data/test.csv", columns=['open']) # 讀取,查看結果 pd.read_csv("./data/test.csv") Unnamed: 0 open 0 2018-02-27 23.53 1 2018-02-26 22.80 2 2018-02-23 22.88 3 2018-02-22 22.25 4 2018-02-14 21.49 5 2018-02-13 21.40 6 2018-02-12 20.70 7 2018-02-09 21.20 8 2018-02-08 21.79 9 2018-02-07 22.69會發現將索引存入到文件當中,變成單獨的一列數據。如果需要刪除,可以指定index參數,刪除原來的文件,重新保存一次。
下面例子把index指定為False,那么保存的時候就不會保存行索引了:
# index:存儲不會將索引值變成一列數據 data[:10].to_csv("./data/test.csv", columns=['open'], index=False)
當然我們也可以這么做,就是把索引保存到文件中,讀取的時候變成了一列,那么可以把這個列再變成索引,如下:
# 把Unnamed: 0這一列,變成行索引 open.set_index(["Unnamed: 0"]) # 把索引名字變成index open.index.name = "index"
read_json
-
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)
- 按照每行讀取json對象
- (1)‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
- (2)‘records’ : list like [{column -> value}, … , {column -> value}]
- (3)‘index’ : dict like {index -> {column -> value}}
- (4)‘columns’ : dict like {column -> {index -> value}},默認該格式
- (5)‘values’ : just the values array
- split 將索引總結到索引,列名到列名,數據到數據。將三部分都分開了
- records 以columns:values的形式輸出
- index 以index:{columns:values}…的形式輸出
- colums 以columns:{index:values}的形式輸出
- values 直接輸出值
path_or_buf
: 路徑orient
: string,以什么樣的格式顯示.下面是5種格式:lines
: boolean, default Falsetyp
: default ‘frame’, 指定轉換成的對象類型series或者dataframe
案例:
- 數據介紹:
這里使用一個新聞標題諷刺數據集,格式為json。is_sarcastic:1諷刺的,否則為0;headline:新聞報道的標題;article_link:鏈接到原始新聞文章。存儲格式為:
{"article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5", "headline": "former versace store clerk sues over secret 'black code' for minority shoppers", "is_sarcastic": 0} {"article_link": "https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365", "headline": "the 'roseanne' revival catches up to our thorny political mood, for better and worse", "is_sarcastic": 0}
- 讀取
orient指定存儲的json格式,lines指定按照行去變成一個樣本:
json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
結果為:
創建DataFrame
在以前的文章中介紹過10種DataFrame的方法
Series的創建
Series是一個類似於一維數組的數據結構,它能夠保存任何類型的數據,比如整數、字符串、浮點數等,主要由一組數據和與之相關的索引兩部分構成。
# 導入pandas import pandas as pd pd.Series(data=None, index=None, dtype=None)
- 參數:
- data:傳入的數據,可以是ndarray、list等
- index:索引,必須是唯一的,且與數據的長度相等。如果沒有傳入索引參數,則默認會自動創建一個從0-N的整數索引。
- dtype:數據的類型
通過已有數據創建:
-
(1)指定內容,默認索引:
pd.Series(np.arange(10))
# 運行結果 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 dtype: int64
(2)指定索引:
pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])
# 運行結果 1 6.7 2 5.6 3 3.0 4 10.0 5 2.0 dtype: float64
(3)通過字典數據創建
color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000}) color_count
# 運行結果 blue 200 green 500 red 100 yellow 1000 dtype: int64
(2)Series的屬性
為了更方便地操作Series對象中的索引和數據,Series中提供了兩個屬性index和values:
index:
color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000}) color_count.index # 結果 Index(['blue', 'green', 'red', 'yellow'], dtype='object')
values:
color_count.values # 結果 array([ 200, 500, 100, 1000])
也可以使用索引來獲取數據:
color_count[2] # 結果 100
MultiIndex
(1)MultiIndex
MultiIndex是三維的數據結構;
多級索引(也稱層次化索引)是pandas的重要功能,可以在Series、DataFrame對象上擁有2個以及2個以上的索引。
- (1)multiIndex的特性
打印剛才的df的行索引結果
df sale year month 2012 1 55 2014 4 40 2013 7 84 2014 10 31 df.index MultiIndex(levels=[[2012, 2013, 2014], [1, 4, 7, 10]], labels=[[0, 2, 1, 2], [0, 1, 2, 3]], names=['year', 'month'])
多級或分層索引對象。
- index屬性
- names:levels的名稱
- levels:每個level的元組值
df.index.names # FrozenList(['year', 'month']) df.index.levels # FrozenList([[2012, 2013, 2014], [1, 4, 7, 10]])
(2)multiIndex的創建
arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']] pd.MultiIndex.from_arrays(arrays, names=('number', 'color')) # 結果 MultiIndex(levels=[[1, 2], ['blue', 'red']], codes=[[0, 0, 1, 1], [1, 0, 1, 0]], names=['number', 'color'])
T 轉置
data.T
刪除列
刪除一些列,讓數據更簡單些,再去做后面的操作 data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)
賦值操作
對DataFrame當中的close列進行重新賦值為1。
# 直接修改原來的值 data['close'] = 1 # 這一列都變成1 # 或者 data.close = 1
查看頭尾數據
頭尾都是默認5行數據,可以指定行數
# df2.head() 默認頭部5行 df2.head(3) # 指定3行 # df2.tail() 默認尾部5行 df2.tail(2) # 指定尾部2行
顯示全部列名
顯示索引
查看列的數據類型
查看行列數
查看數據大小
查看缺失值
修改列名
兩種方式:使用rename函數和直接使用columns屬性
統計元素
統計每個元素的個數
轉成列表數據
提取列中數據
提取文本數據
數值范圍數據提取
提取整列數據
缺失值填充
1、替換缺失值:fillna(value, inplace=True)
- value:替換成的值
- inplace:True:會修改原數據,False:不替換修改原數據,生成新的對象
- 指定填充的值
- 用計算值
- 用其他值
2.刪除存在缺失值的:dropna(axis='rows')
注:不會修改原數據,需要接受返回值
判斷數據中是否包含NaN:
pd.isnull(df),
-
這個和上面的正好相反,判斷是否是缺失值,是則返回True。
# 判斷是否是缺失值,是則返回True pd.isnull(movie).head() # 結果: Rank Title Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore 0 False False False False False False False False False False False False 1 False False False False False False False False False False False False 2 False False False False False False False False False False False False 3 False False False False False False False False False False False False 4 False False False False False False False False False False False False
這個也不好觀察,我們利用np.any()
來判斷是否有缺失值,若有則返回True,下面看例子:
np.any(pd.isnull(movie)) # 返回 True
存在缺失值nan:
pd.notnull(df)
# 判斷是否是缺失值,是則返回False pd.notnull(movie) # 結果: Rank Title Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore 0 True True True True True True True True True True True True 1 True True True True True True True True True True True True 2 True True True True True True True True True True True True 3 True True True True True True True True True True True True 4 True True True True True True True True True True True True 5 True True True True True True True True True True True True 6 True True True True True True True True True True True True 7 True True True True True True True True True True False True
但是上面這樣顯然不好觀察,我們可以借助np.all()
來返回是否有缺失值。np.all()
只要有一個就返回False,下面看例子:
np.all(pd.notnull(movie)) # 返回 False
存在缺失值nan,並且是np.nan 刪除或替換
- 1、刪除
pandas刪除缺失值,使用dropna的前提是,缺失值的類型必須是np.nan
# 不修改原數據 movie.dropna() # 可以定義新的變量接受或者用原來的變量名 data = movie.dropna()
2、替換缺失值
# 替換存在缺失值的樣本的兩列 # 替換填充平均值,中位數 movie['Revenue (Millions)'].fillna(movie['Revenue (Millions)'].mean(), inplace=True)
替換所有缺失值:
# 這個循環,每次取出一列數據,然后用均值來填充 for i in movie.columns: if np.all(pd.notnull(movie[i])) == False: print(i) movie[i].fillna(movie[i].mean(), inplace=True)
不是缺失值nan,有默認標記的
# 讀入數據 wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
以上數據在讀取時,可能會報如下錯誤:
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)>
解決辦法:
# 全局取消證書驗證 import ssl ssl._create_default_https_context = ssl._create_unverified_context
處理思路分析:
- 1、先替換‘?’為np.nan
- to_replace:替換前的值
- value:替換后的值
df.replace(to_replace=, value=)
# 把一些其它值標記的缺失值,替換成np.nan wis = wis.replace(to_replace='?', value=np.nan)
2、再進行缺失值的處理
# 刪除 wis = wis.dropna()
3、驗證:
np.all(pd.notnull(wis)) # 返回True,說明沒有了缺失值 # 或者 np.any(pd.isnull(wis)) # 返回False,說明沒有了缺失值
數據去重
計算統計值
計算統計值,比如最值和均值等
算術運算(1)add(other)
比如進行數學運算加上具體的一個數字
data['open'].head().add(1) 2018-02-27 24.53 2018-02-26 23.80 2018-02-23 23.88 2018-02-22 23.25 2018-02-14 22.49 Name: open, dtype: float64
算術運算(2)sub(other)
整個列減一個數
data.open.head().sub(2) 2018-02-27 21.53 2018-02-26 20.80 2018-02-23 20.88 2018-02-22 20.25 2018-02-14 19.49 Name: open, dtype: float64
邏輯運算函數查詢字符串
-
(1)
query(expr)
- expr:查詢字符串
通過query使得剛才的過程更加方便簡單,下面是使用的例子:
data.query("open<24 & open>23").head()
結果:
-
(2)
isin(values)
例如判斷’open’是否為23.53和23.85:
# 可以指定值進行一個判斷,從而進行篩選操作 data[data["open"].isin([23.53, 23.85])]
對於單個函數去進行統計的時候,坐標軸還是按照默認列“columns” (axis=0, default),如果要對行“index” 需要指定(axis=1)。
(1)max()、min()
# 使用統計函數:0 代表列求結果, 1 代表行求統計結果 data.max(axis=0) # 最大值 open 34.99 high 36.35 close 35.21 low 34.01 volume 501915.41 price_change 3.03 p_change 10.03 turnover 12.56 my_price_change 3.41 dtype: float64
(2)std()、var()
# 方差 data.var(axis=0) open 1.545255e+01 high 1.662665e+01 close 1.554572e+01 low 1.437902e+01 volume 5.458124e+09 price_change 8.072595e-01 p_change 1.664394e+01 turnover 4.323800e+00 my_price_change 6.409037e-01 dtype: float64 # 標准差 data.std(axis=0) open 3.930973 high 4.077578 close 3.942806 low 3.791968 volume 73879.119354 price_change 0.898476 p_change 4.079698 turnover 2.079375 my_price_change 0.800565 dtype: float64
(3)median()
:中位數
中位數為將數據從小到大排列,在最中間的那個數為中位數。如果沒有中間數,取中間兩個數的平均值。
data.median(axis=0) open 21.44 high 21.97 close 10.00 low 20.98 volume 83175.93 price_change 0.05 p_change 0.26 turnover 2.50 dtype: float64
(4)idxmax()、idxmin()
# 求出最大值的位置 data.idxmax(axis=0) open 2015-06-15 high 2015-06-10 close 2015-06-12 low 2015-06-12 volume 2017-10-26 price_change 2015-06-09 p_change 2015-08-28 turnover 2017-10-26 my_price_change 2015-07-10 dtype: object # 求出最小值的位置 data.idxmin(axis=0) open 2015-03-02 high 2015-03-02 close 2015-09-02 low 2015-03-02 volume 2016-07-06 price_change 2015-06-15 p_change 2015-09-01 turnover 2016-07-06 my_price_change 2015-06-15 dtype: object
累計統計函數
統計函數
看一下min(最小值)
, max(最大值)
, mean(平均值)
, median(中位數)
, var(方差)
, std(標准差)
,mode(眾數)
是怎么操作的:
對p_change進行求和
stock_rise = data['p_change'] stock_rise.cumsum() 2015-03-02 2.62 2015-03-03 4.06 2015-03-04 5.63 2015-03-05 7.65 2015-03-06 16.16 2015-03-09 16.37 2015-03-10 18.75 2015-03-11 16.36 2015-03-12 15.03 2015-03-13 17.58 2015-03-16 20.34 2015-03-17 22.42 2015-03-18 23.28 2015-03-19 23.74 2015-03-20 23.48 2015-03-23 23.74
# plot顯示圖形, plot方法集成了直方圖、條形圖、餅圖、折線圖
如果要使用plot函數,需要導入matplotlib.下面是繪圖代碼:
-
DataFrame.plot(kind='line')
- ‘line’ : 折線圖
- ‘bar’ : 條形圖
- ‘barh’ : 橫放的條形圖
- ‘hist’ : 直方圖
- ‘pie’ : 餅圖
- ‘scatter’ : 散點圖
- kind : str,需要繪制圖形的種類
import matplotlib.pyplot as plt # plot顯示圖形, plot方法集成了直方圖、條形圖、餅圖、折線圖 stock_rise.cumsum().plot() # 需要調用show,才能顯示出結果 plt.show()
結果:
自定義運算apply(func, axis=0)
apply(func, axis=0)
- func:自定義函數
- axis=0:默認是列,axis=1為行進行運算
- 定義一個對列,最大值-最小值的函數
下面看個例子:
data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0) open 22.74 close 22.85 dtype: float64
計算中位數
提取最值所在的行
Pandas切片
df2.iloc[22] # 提取某個行的數據 df2.iloc[:,1:6] # 行和列上的切片
大小排序
分組聚合
使用groupby分組之后,對不同的字段可以使用不同的聚合函數
索引重排
注意和上面例子的比較。使用的是reset_index函數
以某列值設置為新的索引
- set_index(keys, drop=True)
- keys : 列索引名成或者列索引名稱的列表
- drop : boolean, default True.當做新的索引,刪除原來的列
設置新索引案例:
1、創建
f = pd.DataFrame({'month': [1, 4, 7, 10], 'year': [2012, 2014, 2013, 2014], 'sale':[55, 40, 84, 31]}) month sale year 0 1 55 2012 1 4 40 2014 2 7 84 2013
2、以月份設置新的索引
df.set_index('month') sale year month 1 55 2012 4 40 2014 7 84 2013 10 31 2014
3、設置多個索引,以年和月份
df = df.set_index(['year', 'month']) df sale year month 2012 1 55 2014 4 40 2013 7 84 2014 10 31
注:通過剛才的設置,這樣DataFrame就變成了一個具有MultiIndex的DataFrame。
去掉原索引
使用索引重排之后我們需要去掉原來的索引;比較上下兩個結果的區別。通過drop=True來實現
apply函數
兩個列相加
DataFrame合並
1、先看看兩個原始數據
2、默認情況:求的兩個DF的交集
3、保留左邊全部數據
4、保留右邊全部數據
how="inner"其實就是默認情況:
導出數據
導出數據的時候通常是不需要索引的
to_json
DataFrame.to_json(path_or_buf=None, orient=None, lines=False)
- 將Pandas 對象存儲為json格式
- path_or_buf=None:文件地址
- orient:存儲的json形式,{‘split’,’records’,’index’,’columns’,’values’}
- lines:一個對象存儲為一行
案例:
- 存儲文件
# 不指定lines=Treu,則保存成一行 json_read.to_json("./data/test.json", orient='records')
結果:
[{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0},{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1},{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/advancing-the-worlds-women_b_6810038.html","headline":"advancing the world's women","is_sarcastic":0},....]
修改lines
參數為True
# 指定lines=True,則多行存儲 json_read.to_json("./data/test.json", orient='records', lines=True)
結果:
"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0} {"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0} {"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1} {"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1} {"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0}...
實現行轉列
第一種:
# 遇事不要慌,先導個包吧 import pandas as pd import numpy as np # 造假數據 data = {'name':['嚴小樣兒','嚴小樣兒','嚴小樣兒','才華橫豎都溢','才華橫豎都溢','才華橫豎都溢','幽蘭幽香','幽蘭幽香','幽蘭幽香'], 'subject':['Python','C','SQL','Python','C','SQL','Python','C','SQL'], 'score':[95,60,95,96,95,80,99,94,88]} # 生成df df = pd.DataFrame(data) df
使用pivot方法即可完成行轉列哦~語法如下:
#df.pivot(index=None, columns=None, values=None) df.pivot(index='name',columns='subject',values='score')
不要高興的太早,遇到重復值就麻煩了!少俠請看:
# 造含有重復值的假數據 data1 = {'name':['嚴小樣兒','嚴小樣兒','嚴小樣兒','嚴小樣兒','才華橫豎都溢','才華橫豎都溢','才華橫豎都溢','幽蘭幽香','幽蘭幽香','幽蘭幽香'], 'subject':['Python','Python','C','SQL','Python','C','SQL','Python','C','SQL'], 'score':[95,95,60,95,96,95,80,99,94,88]} df1 = pd.DataFrame(data1) df1
df1.pivot(index='name',columns='subject',values='score') # 一旦有重復值,就會報錯。 ValueError: Index contains duplicate entries, cannot reshape
別急別急,去個重不就可以了嗎?!
df1.drop_duplicates().pivot(index='name',columns='subject',values='score')
方法二:數據透視表
# pivot_table(data, values=None, index=None, columns=None, aggfunc='mean') pd.pivot_table(df1,index='name',columns='subject',values='score',aggfunc={'score':'max'})
聚合
剛剛說了,要求每個人的總分,其實使用透視表就可以完成。
不過,稍微動動腦筋哦。遇到重復值數據的話,只能使用下面的方法一,去重后的數據集,方法一,二都支持。
計算每個人的總分,語法如下:
# 重復數據集也可以 df_pivot = pd.pivot_table(df1,index='name',columns='subject',values='score',aggfunc={'score':'max'}) # 增加一個新列:Total df_pivot['Total'] = df_pivot.apply(lambda x:np.sum(x),axis = 1) df_pivot
方法二,必須是去重后的數據集,否則會出現計算錯誤。
# 使用去重數據集才可以 pd.pivot_table(df,index='name',values='score',aggfunc='sum')
# 使用join方法把總分列加進去。 total = pd.pivot_table(df,index='name',values='score',aggfunc='sum') pd.pivot_table(df,index='name',columns='subject',values='score').join(total)
--需求方:算是算出來了,可是,這個score看着怪怪的,能不能改成“總分”呢?
--嚴小樣兒:我改(卑微)!安排~
total1 = pd.pivot_table(df,index='name',values='score',aggfunc='sum').rename({'score':'總分'},axis=1) pd.pivot_table(df,index='name',columns='subject',values='score').join(total1)