數據分析——Pandas的用法(Series,DataFrame)


我們先要了解,pandas是基於Numpy構建的,pandas中很多的用法和numpy一致。pandas中又有series和DataFrame,Series是DataFrame的基礎。

pandas的主要功能:

  • 具備對其功能的數據結構DataFrame,Series
  • 集成時間序列功能
  • 提供豐富的數學運算和操作
  • 靈活處理缺失數據,處理NaN數據(******)

一、Series

Series是一種類似於一維數組的對象,由一組數據和一組與之相關的數據標簽(索引)組成

1.創建方法

第一種:
pd.Series([4,5,6,7])
#執行結果
0    4
1    5
2    6
3    7
dtype: int64
#將數組索引以及數組的值打印出來,索引在左,值在右,由於沒有為數據指定索引,於是會自動創建一個0到N-1(N為數據的長度)的整數型索引,取值的時候可以通過索引取
第二種:
pd.Series([4,5,6,7,8],index=['a','b','c','d','e'])   #index索引是用[] #執行結果
a    4
b    5
c    6
d    7
e    8
dtype: int64
# 自定義索引,index是指定的索引名,是一個索引列表,里面包含的是字符串,依然可以通過默認索引取值。
第三種:
pd.Series({"a":1,"b":2})  #傳入字典格式數據 #執行結果:
a    1
b    2
dtype: int64
# 傳入字典格式的數據,字典的key當成指定索引
第四種:
pd.Series(0,index=['a','b','c'])
#執行結果:
a    0
b    0
c    0
dtype: int64
# 創建一個值都是0的數組

對於Series,其實我們可以認為它是一個長度固定且有序的字典,因為它的索引和數據是按位置進行匹配的,像我們會使用字典的上下文,就肯定也會使用Series,也支持通過索引取值。

2.缺失數據(******)在處理數據的時候經常會遇到這類情況

  • dropna() # 過濾掉值為NaN的行
  • fillna() # 填充缺失數據
  • isnull() # 返回布爾數組,缺失值對應為True
  • notnull() # 返回布爾數組,缺失值對應為False
# 第一步,創建一個字典,通過Series方式創建一個Series對象
st = {"sean":18,"yang":19,"bella":20,"cloud":21}
obj = pd.Series(st)
obj
運行結果:
sean     18
yang     19
bella    20
cloud    21
dtype: int64
------------------------------------------
# 第二步
a = {'sean','yang','cloud','rocky'}  # 定義一個索引變量
------------------------------------------
#第三步
obj1 = pd.Series(st,index=a)
obj1  # 將第二步定義的a變量作為索引傳入

# 運行結果:
rocky     NaN
cloud    21.0
sean     18.0
yang     19.0
dtype: float64
# 因為rocky沒有出現在st的鍵中,所以返回的是缺失值

dropna()   #過濾掉值有NaN的行

obj1.dropna()
#執行結果
cloud    21.0
sean     18.0
yang     19.0
dtype: float64

fillna()     #填充缺失數據,這個填寫1

obj1.fillna(1)
#執行結果
cloud    21.0
sean     18.0
yang     19.0
rocky     1.0
dtype: float64

isnull()    #缺失值返回True

obj1.isnull()
#執行結果
cloud    False
sean     False
yang     False
rocky     True
dtype: bool

notnull()   #不是缺失值返回True

obj1.notnull()
#執行結果
cloud     True
sean      True
yang      True
rocky    False
dtype: bool

利用布爾值索引過濾缺失值

obj1[obj1.notnull()]   #只有True的才顯示 #執行結果
cloud    21.0
sean     18.0
yang     19.0
dtype: float64

3.Series特性

  • 從ndarray創建Series:Series(arr)
  • 與標量(數字):sr * 2
  • 兩個Series運算
  • 通用函數:np.ads(sr)
  • 布爾值過濾:sr[sr>0]
  • 統計函數:mean()、sum()、cumsum()

因為pandas是基於numpy的,所以有numpy的很多特性,Series和numpy很多類似

支持字典的特性:

  • 從字典創建Series:Series(dic),
  • In運算:'a'in sr、for x in sr
  • 鍵索引:sr['a'],sr[['a','b','d']]
  • 鍵切片:sr['a':'c']
  • 其他函數:get('a',default=0)等

4.整數索引

sr = pd.Series(np.arange(10))
sr1 = sr[3:]
sr1
運行結果:
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int32
# 到這里會發現很正常,一點問題都沒有,可是當使用整數索引取值的時候就會出現問題了。因為在pandas當中使用整數索引取值是優先以標簽解釋的(就是index的值),而不是下標。

比如我想取索引值為1的數值,不再是我們之前的那種方法

sr1[1]   #這種方式是取不出的,因為默認優先的是以標簽解釋的,這個沒有1的標簽(index)

解決方法:

  • loc屬性 # 以標簽解釋
  • iloc屬性 # 以下標(索引)解釋
sr1.iloc[1]  #以下標取值,(索引值為1的)
#執行結果  
4

sr1.loc[4]   #以標簽取值(index值為1)
#執行結果
4

5.Series數據對齊

sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a',])
sr1 + sr2
運行結果:
a    33
c    32
d    45
dtype: int64
# 可以通過這種索引對齊直接將兩個Series對象進行運算
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1 + sr3
運行結果:
a    33.0
b     NaN
c    32.0
d    45.0
dtype: float64
# sr1 和 sr3的索引不一致,所以最終的運行會發現b索引對應的值無法運算,就返回了NaN,一個缺失值

將兩個Series對象相加時將缺失值設為0

sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1.add(sr3,fill_value=0)
運行結果:
a    33.0
b    14.0
c    32.0
d    45.0
dtype: float64
# 將缺失值設為0,所以最后算出來b索引對應的結果為14

二.DataFrame

DataFrame是一個表格型的數據結構,相當於是一個二維數組,含有一組有序的列。他可以被看做是由Series組成的字典,並且共用一個索引(這里的索引指的就是列索引)

1.創建方式

創建一個DataFrame數組可以有多種方式,其中最為常用的方式就是利用包含等長度列表或Numpy數組的字典來形成DataFrame:

第一種:
pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
# 產生的DataFrame會自動為Series分配所索引,並且列會按照排序的順序排列
運行結果:
    one two
0   1   4
1   2   3
2   3   2
3   4   1
#字典的key就是列索引,行索引和series一致
> 指定列
可以通過columns參數指定順序排列
data = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame(data,columns=['two','one'])  #指定顯示順序 #執行結果
    two    one
0    4    1
1    3    2
2    2    3
3    1    4
#注意:columns一定要是key值中的,才能匹配的到,不然會報錯
第二種:
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
運行結果:
   one  two
a   1   2
b   2   1
c   3   3
#字典的key是列索引,index是行索引

2.查看數據

常用屬性和方法:(和numpy類似)

  • index 獲取行索引
  • columns 獲取列索引
  • T 轉置
  • values 獲取值
  • describe() 獲取快速統計
 one    two
a   1   2
b   2   1
c   3   3
# 這樣一個數組df
----------------------------------------------------------------------------- df.index #行索引
運行結果:
Index(['a', 'b', 'c'], dtype='object')
---------------------------------------------------------------------------- df.columns #列索引
運行結果:
Index(['one', 'two'], dtype='object')
-------------------------------------------------------------------------- df.T #轉置
運行結果:
    a   b   c
one 1   2   3
two 2   1   3
------------------------------------------------------------------------- df.values #獲取值,ndarray類型
運行結果:
array([[1, 2],
       [2, 1],
       [3, 3]], dtype=int64)
------------------------------------------------------------------------ df.describe() #統計信息
運行結果:
one two
count   3.0 3.0
mean    2.0 2.0
std 1.0 1.0
min 1.0 1.0
25% 1.5 1.5
50% 2.0 2.0
75% 2.5 2.5
max 3.0 3.0

3.索引和切片

  • DataFrame有行索引和列索引
  • DataFrame同樣可以通過標簽和位置兩種方法進行索引和切片。

DataFrame使用索引切片:

  • 方法1:兩個中括號,先取列再取行。 比如:df['A'][0]
  • 方法2(推薦):使用loc/iloc屬性,一個中括號,逗號隔開,先取行再取列。
    • loc屬性:解釋為標簽
    • iloc屬性:解釋為下標
  • 向DataFrame對象中寫入值時只使用方法2
  • 行/列索引部分可以是常規索引、切片、布爾值索引、花式索引任意搭配。(注意:兩部分都是花式索引時結果可能與預料的不同)

4.常見獲取數據的方式 

 打開csv,excel等文檔獲取數據

df=pd.read_csv('./douban_movie.csv') #填寫正確的文件路徑
df.head() #head默認顯示前五條

 

 另存為

df.to_csv('./a.csv',index=False)   #另存為,不要保存行索引(index索引),不然打開a.csv會出現兩個行索引

read_html  獲取頁面上的表格

舉例子:計算nba球隊獲取總冠軍的次數

dd=pd.read_html('https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin') #地址為百度nba總冠軍記錄,返回的結果是列表,此頁面的所有表格數據

因為是返回值是列表,所以一個表格代表一個元素,因為此頁面中有兩個表格,索引我們按照索引取值的方式取出第一個表格

champion=dd[0]
champion.head()  #顯示前5條

champion.columns=champion.iloc[0]    #將第一行的數據賦值給列名(colimns代表列名)
champion.drop([0],inplace=True)  #將數據的第一行刪除掉

 

 根據冠軍球隊來分組

champion.groupby('冠軍').groups

 

 統計次數,然后排序

champion.groupby('冠軍').size().sort_values(ascending=False)

 

 5.時間對象處理

 時間序列類型

  • 時間戳:特定時刻
  • 固定時期:如2019年1月
  • 時間間隔:起始時間-結束時間

 python庫:datatime

  • date、time、datetime、timedelta
  • dt.strftime()
  • strptime()

 靈活處理時間對象:dateutil包

  • dateutil.parser.parse()
import dateutil
dateutil.parser.parse("2019 Jan 2nd")   #注意時間格式一定要是英文格式

執行結果:
datetime.datetime(2019, 1, 2, 0, 0)

成組處理時間對象:pandas   (******)

pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])   #處理時間

運行結果:
DatetimeIndex(['2018-03-01', '2019-02-03', '2019-08-12'], dtype='datetime64[ns]', freq=None)  # 產生一個DatetimeIndex對象

# 轉換時間索引,將時間做成索引
ind = pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019'])
sr = pd.Series([1,2,3],index=ind)
sr
運行結果:
2018-03-01    1
2019-02-03    2
2019-08-12    3
dtype: int64
通過以上方式就可以將索引轉換為時間

補充:
pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/019']).to_pydatetime()
運行結果:
array([datetime.datetime(2018, 3, 1, 0, 0),
       datetime.datetime(2019, 2, 3, 0, 0),
       datetime.datetime(2019, 8, 12, 0, 0)], dtype=object)
# 通過to_pydatetime()方法將其轉換為array數組

產生時間對象數組:data_range

  • start 開始時間
  • end 結束時間
  • periods 時間長度
  • freq 時間頻率,默認為'D',可選H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…
pd.date_range("2019-1-1","2019-2-2")
運行結果:
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
               '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
               '2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12',
               '2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16',
               '2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20',
               '2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24',
               '2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28',
               '2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01',
               '2019-02-02'],
              dtype='datetime64[ns]', freq='D')   #默認是D,按天算.  M:按月算

時間序列

時間序列就是以時間對象為索引的Series或DataFrame。datetime對象作為索引時是存儲在DatetimeIndex對象中的。

# 轉換時間索引

dt = pd.date_range("2019-01-01","2019-02-02")
a = pd.DataFrame({"num":pd.Series(random.randint(-100,100) for _ in range(30)),"date":dt})

# 先生成一個帶有時間數據的DataFrame數組

a.index = pd.to_datetime(a["date"])
# 再通過index修改索引

特殊功能:

  • 傳入“年”或“年月”作為切片方式
  • 傳入日期范圍作為切片方式
  • 豐富的函數支持:resample(), strftime(), ……
  • 批量轉換為datetime對象:to_pydatetime()
a.resample("3D").mean()  # 計算每三天的均值
a.resample("3D").sum()  #  計算每三天的和
...

6.數據分組和聚合

在數據分析當中,我們有時需要將數據拆分,然后在每一個特定的組里進行運算,這些操作通常也是數據分析工作中的重要環節。

    • 分組(GroupBY機制)  (分組是經常用到的)
    • 聚合函數(組內應用某個函數)
    • apply
    • 透視表和交叉表

 分組(GroupBY機制)

 主要就是groupby結合索引和size的使用

 聚合函數(組內應用某個函數)

 

函數名 描述  
sum 非NA值的和  
median 非NA值的算術中位數  
std、var 無偏(分母為n-1)標准差和方差  
prod 非NA值的積  
first、last 第一個和最后一個非NA值

 apply(******)

 GroupBy當中自由度最高的方法就是apply,它會將待處理的對象拆分為多個片段,然后各個片段分別調用傳入的函數,最后將它們組合到一起。

df.apply(
['func', 'axis=0', 'broadcast=None', 'raw=False', 'reduce=None', 'result_type=None', 'args=()', '**kwds']

func:傳入一個自定義函數
axis:函數傳入參數當axis=0就會把一行數據作為Series的數據

 


免責聲明!

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



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