Pandas高頻使用技巧


 

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 False
    • typ : 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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM