Pandas基礎06 異常值的檢測與過濾
在數據分析中,異常值(Outliers)是指與其他數據點顯著不同的值。這些值可能由于數據錄入錯誤、設備故障或極端情況而產生,因此在進行數據分析之前,需要對其進行檢測與過濾。本文將介紹如何利用 Pandas 中的一些常見函數,檢測、處理和過濾數據中的異常值,同時對數據進行基本的處理和探索。
3.5.1. describe()
:查看每一列的描述性統計量
describe()
函數是 Pandas 中最常用的查看數據分布的工具之一。它可以幫助我們了解每一列的基本統計信息,包括計數、均值、標準差、最小值、最大值以及四分位數等。通過這些信息,我們可以初步識別數據中的異常值。
import pandas as pd
import numpy as npdf = pd.DataFrame(np.random.randint(1, 100, (4, 3)), index=["zhangsan", "lisi", "wangwu", "zhouliu"], columns=["Chinese", "Math", "English"])# 查看描述性統計量
df.describe()
輸出結果:
Chinese Math English
count 4.000000 4.000000 4.000000
mean 85.750000 36.750000 25.250000
std 13.022417 26.474831 19.397165
min 74.000000 11.000000 7.000000
25% 74.750000 16.250000 9.250000
50% 85.500000 35.000000 25.500000
75% 96.500000 55.500000 41.500000
max 98.000000 66.000000 43.000000
通過 describe()
輸出的統計數據,我們可以觀察到各列的均值、標準差以及最大最小值。如果某一列的最小值或最大值顯得非常偏離其他數據點,這可能意味著該列中有異常值。
3.5.2. info()
:查看數據信息
info()
函數可以幫助我們快速查看 DataFrame 的結構,包括行數、列數、每列的非空值數量以及數據類型等。這對于檢查數據完整性和結構非常有用。
df.info()
輸出結果:
<class 'pandas.core.frame.DataFrame'>:數據結構為DataFrame
Index: 4 entries, zhangsan to zhouliu:行索引
Data columns (total 3 columns): :列索引# Column Non-Null Count Dtype :列的信息
--- ------ -------------- -----0 Chinese 4 non-null int32 :4個均為非空值1 Math 4 non-null int322 English 4 non-null int32
dtypes: int32(3) :元素的類型
memory usage: 80.0+ bytes :內存中的存儲情況
通過 info()
,我們得知所有列的數據類型均為 int32
,且每列都沒有缺失值。這有助于確認數據是否完整且正確。
3.5.3. std()
:標準差
標準差是衡量數據分散程度的一個指標。標準差較大的列可能存在更多的異常值,因為數據點的波動幅度較大。我們可以通過 std()
函數來計算每列數據的標準差,并作為識別異常值的一個輔助指標。
df.std()
輸出結果:
Chinese 13.022417
Math 26.474831
English 19.397165
dtype: float64
如果某一列的標準差非常大,且數據的分布范圍較廣,則可能存在一些離群點或異常值。
3.5.4. drop()
:刪除特定索引
drop()
函數可以幫助我們刪除 DataFrame 中的特定行或列。如果在數據中發現了明顯的異常值或錯誤數據,可以使用 drop()
來移除這些數據。
df1 = df.copy()
df1.drop("zhangsan") # 刪除行
df1.drop(index="zhangsan") # 刪除行df1.drop("Chinese", axis=1) # 刪除列
df1.drop(columns=["Chinese", "Math"], inplace=True) # 刪除多列并覆蓋原數據
在數據清理過程中,刪除異常值或者錯誤數據是常見的操作,drop()
函數提供了簡單且靈活的方式來刪除不需要的數據。
3.5.5. unique()
:唯一值去重
unique()
函數可以幫助我們檢查數據中是否有重復值,對于檢測異常值非常有幫助。它返回一個包含唯一值的數組。
df["Chinese"].unique() # 獲取“Chinese”列中的唯一值
如果某列中有重復值,unique()
可以幫助我們識別并處理這些重復數據。
3.5.6. query()
:按條件查詢
query()
函數可以通過條件表達式來過濾數據,這對于識別某一特定范圍之外的異常值非常有用。
df.query('Math > 60') # 查詢 Math 列大于 60 的數據
df.query('Math > 60 and English > 60') # 多條件查詢
df.query('Math in [10, 20, 30]') # 查詢 Math 列為指定值的數據
query()
函數可以結合邏輯運算符(如 and
、or
)以及比較符號(如 >
, <
, ==
)對數據進行靈活的過濾。
3.5.7. sort_values()
:根據值排序
sort_values()
函數可以根據某列的值對數據進行排序,幫助我們識別最大或最小值,從而找到異常值。
df.sort_values("Chinese") # 按照“Chinese”列升序排序
df.sort_values("Chinese", ascending=False) # 降序排序
通過排序,我們可以快速發現某列的極端值,進而識別可能的異常值。
3.5.8. sort_index()
:根據索引排序
有時我們需要根據行索引來排序數據,sort_index()
函數提供了這一功能。盡管它與異常值過濾關系不大,但在數據整理過程中,它依然非常實用。
df.sort_index() # 根據索引排序
3.5.9 案例
(練習)新建一個形狀為10000*3的標準正態分布的DataFrame(np.random.randn),去除掉所有滿足以下情況的行:其中任一元素絕對值大于3倍標準差
df = pd.DataFrame(np.random.randn(10000, 3))
cond = df.abs() > df.std()*3 #通過矩陣的運算求得各元素是否滿足條件
cond1 = cond.any(axis=1) #判斷每一行是否包含一個False(即不滿足條件的行)
df[~cond1] #將不滿足條件的行過濾
3.5 Pandas的數學處理
3.5.1 抽樣
df.take([1, 0, 3, 2])# 行排序
df.take([2, 1, 0], axis=1) #列排序
np.random.permutation([0, 1, 2]) #隨機排序
# 無放回抽樣
df.take(np.random.permutation([0, 1, 2]))
# 有放回抽樣
df.take(np.random.randint(0, 4, size=5))
3.5.2 常用的數學函數
Pandas 提供了許多常用的數學函數,幫助我們對數據進行統計和分析
1 統計指標函數
-
max()
:計算每一列或每一行的最大值。df.max() # 默認求每一列的最大值 df.max(axis=1) # 求每一行的最大值
-
count()
:計算每一列或每一行的非空元素個數。df.count() # 默認求每一列的非空元素個數 df.count(axis=1) # 求每一行的非空元素個數
-
median()
:計算每一列的中位數。df.median() # 默認求每一列的中位數
-
mean()
:計算每一列的平均值。df.mean() # 默認求每一列的平均值
-
var()
:計算每一列的方差。df.var() # 默認求每一列的方差
-
std()
:計算每一列的標準差。df.std() # 默認求每一列的標準差
2 相關性與協方差
-
cov()
:計算每一列之間的協方差。df.cov() # 默認求每一列的協方差
-
corr()
:計算每一列之間的相關系數。df.corr() # 默認求每一列的相關系數
3 其他常用函數
-
value_counts()
:統計某一列或 Series 中每個元素的出現次數。df[0].value_counts() # 統計第0列元素的出現次數
-
cumsum()
:計算每一列的累加和。df.cumsum() # 每列的累加和
-
cumprod()
:計算每一列的累乘積。df.cumprod() # 每列的累乘積
4. 組合使用示例
假設我們有一個 DataFrame,我們可以結合上述數學函數和抽樣方法進行更復雜的操作。
例如,隨機抽樣 3 行數據并計算它們的平均值和標準差:
import pandas as pd
import numpy as np# 示例 DataFrame
data = {'A': [1, 2, 3, 4, 5],'B': [6, 7, 8, 9, 10],'C': [11, 12, 13, 14, 15]}
df = pd.DataFrame(data)# 隨機抽樣
sampled_df = df.take(np.random.permutation(df.index)[:3])# 計算平均值和標準差
mean_values = sampled_df.mean()
std_values = sampled_df.std()print("抽樣數據:\n", sampled_df)
print("\n平均值:\n", mean_values)
print("\n標準差:\n", std_values)
Pandans數據聚合
數據聚合通常是在數據處理的最后一步,它的目的是將每個分組的數據轉換成一個單一的數值,以便做出總結或進一步分析。數據分類處理(GroupBy)是數據分析中非常重要的一步,它主要分為三個步驟:
3.6.1. 分組 (Group)
- 在分組的步驟中,數據會根據某一列或多列的值進行分組。比如,你可以根據“顏色”列將數據分為不同的顏色組,或者根據日期將數據分為不同的時間段組。
- 這一步使用
groupby()
函數來完成。groupby()
函數可以將數據框按某些列的值分組,創建一個GroupBy
對象。
grouped = ddd.groupby('color')
# 可以通過groups屬性查看元素的值
grouped.groups #里面包含聚合元素的索引
3.6.2. 用函數處理 (Apply Functions)
- 一旦數據被分組,你可以對每一組數據應用特定的函數進行處理。常見的操作有求和、平均數、最大值、最小值等。
- 你可以對分組后的數據應用標準的聚合函數(如
sum()
、mean()
、count()
等),或者你可以定義自己的自定義函數來處理每個分組。
grouped_sum = grouped.sum() # 對每個分組的數據求和
grouped_mean = grouped.mean() # 對每個分組的數據求平均
也可以使用 apply()
或 agg()
方法,來應用更加復雜的操作:
grouped_custom = grouped.apply(lambda x: x['score'].max() - x['score'].min())
3.6.3. 合并 (Combine)
- 聚合操作完成后,最終的結果是各組的數據經過處理后得到的一個單一數值。
groupby()
返回的是一個GroupBy
對象,你通常需要將不同組的結果合并成一個新的數據框或系列。 - 比如,使用
sum()
或mean()
后,會返回每個分組的匯總結果,合并成一個新的數據框或系列。
final_result = grouped['score'].sum() # 對每個分組的 "score" 列求和并合并結果
groupby()
的常見方法:
- 聚合:
sum()
:求和- mean()`:均值
count()
:計數min()
:最小值max()
:最大值std()
:標準差agg()
:自定義聚合函數
- 過濾:對分組后的數據進行過濾(
filter()
) - 轉換:對分組后的數據進行轉換(
transform()
) - 應用:應用自定義函數(
apply()
)
3.6.4. 案例
ddd=pd.DataFrame(
data={"item":["蘿卜","白菜","辣椒","冬瓜","蘿卜","白菜","辣椒","冬瓜"],"color":["白","青","紅","白","青","紅","白","青"],"weight":[10,20,10,10,30,40,50,60],"price":[0.99,1.99,2.99, 3.99,4,5,6,7]
})
# 對ddd進行聚合操作,求出顏色為白色的價格總和
ddd.groupby("color").sum(numeric_only=False).loc['白']
# 對ddd進行聚合操作,分別求出蘿卜的所有重量以及平均價格
x1 = ddd.groupby("item")[["weight"]].sum()
x2 = ddd.groupby("item")[["price"]].mean()
x1.merge(x2, left_index=True, right_index=True).loc[['蘿卜']]