Pandas01
Pandas02
文章目錄
- 內容回顧
- 1 排序和統計函數
- 2 缺失值處理
- 2.1 認識缺失值
- 2.2 缺失值處理- 刪除
- 2.3 缺失值處理- 填充
- 非時序數據
- 時序數據
- 3 Pandas數據類型
- 3.1 數值類型和字符串類型之間的轉換
- 3.2 日期時間類型
- 3.3 日期時間索引
- 4 分組聚合
- 4.1 分組聚合的API使用
- 4.2 分組聚合的代碼說明
- 4.3 自定義聚合函數
- 5 數據的分箱(分桶)
內容回顧
數據讀取保存
- pd.read_xxx
- df.to_XXX
- index 是否保存
查詢
- query
- loc/iloc屬性 loc名稱 iloc序號
- series.isin([])
增加刪除修改
-
df[‘新列名’]=新值/[]
-
df.insert()
-
df.drop()
- axis =0 /1
- inplace
-
df.drop_duplicates(subset=,keep=,inplace)
-
df.replace()
-
loc/iloc 定位到數據直接修改
-
apply
-
先自己定義一個方法, 這個方法不是由我們來調用, 而是要交給apply方法 由這個方法來調用, 傳給它的是函數對象
def func(s)
? return s
-
s.apply() 傳入的是每一個值
-
df.apply( axis) 傳入給自定義函數的是Series對象
-
index 和 columns 的修改
- set_index()
- reset_index()
- 直接替換, 但是不能直接單獨修改某一個索引, 單獨修改某一個索引需要使用方法rename()
1 排序和統計函數
nlargest/nsmallest
sort_values 多字段排序
df.sort_values(['價格','面積'],ascending=[False,True])
# 多字段排序, by可以通過列表,傳入多個字段,
# ascending 也可以傳入列表 分別指定每個字段的升序/降序的情況 升序降序列表長度需要和排序字段長度一致
corr() 計算相關性
df.corr(numeric_only=True)
# 相關系數 判斷兩列數據是否同增同減 [-1,1]
# 如果一個變量增大的時候, 另一個變量也跟一起增大 正相關 最大 1
# 如果一個變量增大的時候, 另一個變量減小 負相關 最小 -1
# 相關系數的絕對值 >0.7 強相關 0.3~0.7 具有相關性 0.3以下 弱相關 0附近 不相關
2 缺失值處理
2.1 認識缺失值
from numpy import NaN,NAN,nan
NaN和任何一個值都不相等 包括自己
不能通過 == 方式找到缺失值
NaN 是float 類型
加載包含缺失值的數據
df = pd.read_csv('C:/Develop/深圳42/data/city_day.csv',keep_default_na=False)
# 是否用默認的方式來加載空值, 默認加載成NaN 改成False 就會加載成空串
pd.read_csv('C:/Develop/深圳42/data/city_day.csv',na_values='0.0')
# na_values 可以指定某些特殊的值, 在加載數據的時候當作空值來對待
缺失值的識別
- df.isnull() 缺失返回True 否則返回False
- df.notnull() 和isnull 相反
df.isnull().sum() # 可以計算每一列缺失值的數量
df.isnull().sum()/df.shape[0] # 可以計算每一列缺失值的占比
2.2 缺失值處理- 刪除
df2 = df.sample(10,random_state=5)
# sample 從數據中隨機采樣 n條數據, 這里傳了10 取出10條, random_state 隨機數種子, 如果這個值設置的是一樣的, 運行多少次結果都相同, 這么做的目的是為了方便復現結果
df2.dropna()
#%%
df2.isnull().sum(1) # 計算每一行缺失值數量
#%%
df2.dropna(subset=['PM2.5','CO']) # 通過 subset 指定 去掉缺失值的時候只考慮 'PM2.5','CO'
df2.dropna(subset=['PM2.5','CO'],how='any') # how = any 有缺失就刪除 可選all 都缺失才刪除
df2.dropna(thresh=12)
# 設置閾值, 設置了每一行/列 非空元素的下限, 當每一行/列 非空值小于這個閾值時就會被刪除
什么時候刪除缺失值
- 關鍵信息缺失 , 舉例:用戶ID 缺少, 訂單ID
- 某一列數據, 缺失值占比過高(50%), 也可以考慮刪除
- 有些時候, 數據的作用比較大的,暫時缺失值比較高, 可以考慮先觀察這一列數, 可以通過運營手段, 降低缺失率
2.3 缺失值處理- 填充
非時序數據
- 統計量來填充, 均值, 中位數 眾數(類別型 可以用出現次數最多的) 業務的默認值
df2['PM2.5'].fillna(df2['PM2.5'].mean())
#%%
df2.fillna({'PM2.5':df2['PM2.5'].mean(),'PM10':df2['PM10'].mean()})
時序數據
- 溫度, 天氣, 用電量, 個人存款金額, 個人貸款金額
- 用前一個非空值, 和后一個非空值來進行填充
- 也可以考慮線性插值
s1 = df['Xylene'][54:64] # 篩選部分數據
s1.fillna(method='bfill')
# bfill 用后面的非空值進行填充 ffill 用空值前面的非空值進行填充
s1.interpolate(method='linear')
# 線性插值 和空值相鄰的兩個非空值連線, 空值就從線上取值, 等差數列
3 Pandas數據類型
字符串 → Object
數值型 → int64 float64
類別型 → category 后面介紹
日期時間 → datetime timedelta
3.1 數值類型和字符串類型之間的轉換
as_type 可以做類型的轉換, 對類型沒有限制
pd.to_numeric() 把一列數據轉換成數值類型
import pandas as pd
df = pd.read_csv('C:/Develop/深圳42/data/city_day.csv')
df.head()
#把數值型轉換成字符串
df['NO'] = df['NO'].astype(object)
# 把它在轉換回來, 都可以成功轉換
df['NO'] = df['NO'].astype(float)
#
df2 = df.head().copy()
# 構造數據, 把部分數據改成字符串
df2.loc[::2,'NO'] = 'missing'
df2.info()
# 此時不能成功轉換, errors='ignore' 兩個參數 ignore忽略, raise 拋異常
df2['NO'].astype(float,errors='ignore')
#%%
# 轉換成數值型
pd.to_numeric(df2['NO'], errors='coerce')
# 有些時候, 應該整列都是數值的列, 由于采集/傳輸的原因, 導致有幾值是字符串, 這會導致整列變成字符串類型, 后續計算會十分麻煩, 需要把這一列轉換成數值類型
# 如果直接使用astype 要么報錯, 要么不處理,此時可以使用 pd.to_numeric 可以指定errors參數為coerce 不能轉換成數值的字符串會被處理成NaN
3.2 日期時間類型
加載數據的時候, 如果發現了有年月日時分秒這樣的數據, 需要查看一下數據類型, 如果需要從年月日時分秒這樣的數據中提取出日期時間相關信息, 需要轉換成datetime類型
- 加載的時候直接某一列為日期時間類型
df = pd.read_csv('C:/Develop/深圳42/data/city_day.csv',parse_dates=['Date'])
parse_dates
- 通過pd.to_datetime進行轉換
df['Date'] = pd.to_datetime(df['Date'])
- 數據如果是來自數據庫, xlsx excel文件, 有可能不需要特殊處理, 直接就是日期時間類型, 如果是從CSV文件讀取出來, 默認讀出來的日期時間的數據都是object
跟日期時間相關的三種類型
- datetime64
df['Date'] = pd.to_datetime(df['Date'])
年月日 這樣的列,轉換之后得到的就是datetime64[ns] 這種類型
從日期時間類型中, 提取出相關的不同時間維度, df[‘Date’].dt.XXX
- year, month月 day日…
- timestamp 時間戳
df['Date'].max()
Timestamp(‘2020-07-01 00:00:00’)
- Timedelta64
df['Date']-df['Date'].min()
3.3 日期時間索引
DatetimeIndex 和 TimedeltaIndex 是兩種日期時間索引
把datetime64類型的一列數據, 設置為索引以后, 就是DatetimeIndex , 我們對索引排序,排序以后就可以按日期時間維度進行選取子集,做數據切片
df.set_index('Date', inplace=True) # 設置為日期時間索引
#%%
df.sort_index(inplace=True) # 對索引進行排序
#%%
df.loc['2018'] # 篩選2018年的數據
#
df.loc['2018-06-05']# 篩選2018年6月5日的數據
df.loc['2018-06-05':'2018-06-15']
把Timedelta64類型的一列數據, 設置為索引以后, 就是TimedeltaIndex對索引排序,排序以后就可以按時間差值的維度進行選取子集,做數據切片
df['time_delta']=df['Date']-df['Date'].min()
#%%
df.set_index('time_delta', inplace=True)
#%%
df.loc['10 days']
df.loc['20 days':'30 days']
4 分組聚合
4.1 分組聚合的API使用
df.groupby('區域').mean() # 區域字段分組,只對數值列計算平均值
在高版本 比如2.0 這種寫法會有錯, 可以傳入numeric_only = True
df.groupby('區域')['價格'].mean() # 區域字段分組,對價格計算平均值
df.groupby(分組字段)[聚合字段].聚合函數()
如果對一個字段按一種方式進行聚合, 這種寫法就可以了
df.groupby('區域')[['面積','價格']].agg(['mean','median'])
如果需要對多個字段進行聚合, 需要[] 傳入列表
同時計算多個聚合函數需要調用agg方法 ,傳入列表
df.groupby('區域').agg({'面積':'mean','價格':'median'})
不同字段不同方式進行聚合, agg里面傳入字典, key聚合字段,value 聚合函數
多字段分組/多字段聚合
groupby([‘字段1’,'字段2])
- 返回復合索引 MultiIndex
對一個字段做多種不同的聚合計算, 返回的結果column是MutiIndex
- 復合索引 列表里套元組, 取數的時候, 可以傳元組中的第1個元素, 也可以直接傳入元組[()]
groupby分組聚合之后, 結果默認會把分組字段作為結果的索引, 如果不想把分組字段作為結果的索引
- df.groupby(‘區域’,as_index = False)
- 對結果reset_index()
4.2 分組聚合的代碼說明
df.groupby('區域')['價格'].mean()
上面的代碼可以拆分成三句
df_groupby = df.groupby('區域') # 得到的是一個dataframegroupby對象
df_groupby.groups 返回一個字段 {‘區域不同的取值’:[這個值對應的行索引]}
df_groupby.get_group(‘CBD租房’) 獲取CBD租房 對應的DataFrame數據
s_groupby = df_groupby['價格'] # 得到的是一個seriesgroupby對象
從dataframegroupby對象的每一組中, 獲取了[‘價格列’], 組層了seriesgroupby對象
s_groupby.mean()
每一組, 對價格的數據求一下平均, 有多少組算多少次, 把結果匯總起來
4.3 自定義聚合函數
當常規的聚合函數不能滿足業務需求的時候, 需要自己來寫聚合的邏輯, 就是自定義聚合函數
- 舉例子, 按照區域進行分組, 計算不同區域的平均房租 計算價格均值的時候, 需要過濾掉價格低于3000的
def func(s):print(s)print(type(s)) print('=====================')# 每一組選出價格>3000的 對這部分求平均result = s[s<12000].mean()return result
## 自定義聚合函數
df.groupby(['區域'])['價格'].agg(func)
自定義聚合函數, 一定要有返回值, 返回的是一個值, 不能是多個值
分組聚合, 每組應該只有一個聚合結果
5 數據的分箱(分桶)
有很多場景, 我們需要把連續型取值的數據列, 變成類別型
- 年齡這一列 → 年齡段( 未成年, 青年, 中年, 老年)
- 收入這一列 → 收入檔次 (低收入,中收入, 高收入, 超高收入)
類似上面提到的場景, 就可以使用pd.cut() 對數據進行分箱處理
pd.cut(df['價格'],bins=3)
bins = 3 分成3組(3箱)
此時劃分策略, 每一組(每一箱) 上邊界 和下邊界之間的差值, 盡可能相等 (等距分箱)
pd.cut(df['價格'],bins=[0,4500,8500,210000],labels=['低','中','高'])
第一個參數 df[‘價格’] 要被分箱/分組的數據列(Series)
bins 傳入一個列表, 列表里的值, 從小到大, 定義了每一箱的邊界
- 做開右閉合 ,需要注意, 最左邊的下限要小于數據中的最小值, 否則會漏掉, 漏掉的數據會變成NaN
labels 如果不傳, 分箱之后, 每一箱的取值會用這一箱的邊界(下限,上限] 來替代, 我們傳入一個列表,可以自己定義分箱之后每一箱的取值
若有錯誤與不足請指出,關注DPT一起進步吧!!!