核心數據結構:DataFrame

?3.3.1 ?創建與訪問

什么是?DataFrame

DataFrame 是?Pandas 中的核心數據結構之一,多行多列表格數據,類似于?Excel 表格?或?SQL 查詢結果
它是一個?二維表格結構,具有行索引(index)和列標簽(columns)。

Python
df = pd.DataFrame({"name": ["Alice", "Bob"],"score": [90, 80]
})

DataFrame中的數據是以一個或多個二維塊存放的(而不是列表、字典或別的一維數據結構)。它可以被看做由Series組成的字典(共同用一個索引)。提供了各種功能來進行數據訪問、篩選、分割、合并、重塑、聚合以及轉換等操作,廣泛用于數據分析、清洗、轉換、可視化等任務。

DataFrame的創建

Python
# 通過series來創建
import pandas as pd
import numpy as np
np.random.seed(42)
s1 = pd.Series(np.random.randint(0,10,6))
np.random.seed(41)
s2 = pd.Series(np.random.randint(0,20,6))
df = pd.DataFrame({"s1":s1,"s2":s2})

直接通過字典創建DataFrame

Python
import pandas as pd
df = pd.DataFrame({ ???"name": ["Alice", "Bob"], ???"score": [90, 80]})
print(df)
df?= pd.DataFrame({"id": [101, 102, 103],
"name": ["張三", "李四", "王五"], "age": [20, 30, 40]})
print(df)
# ? ? id name ?age
# 0 ?101 ? 張三?? 20
# 1 ?102 ? 李四?? 30
# 2 ?103 ? 王五?? 40

通過字典創建時指定列的順序和行索引

Bash
df?= pd.DataFrame(data={"age": [20, 30, 40],"name": ["張三", "李四", "王五"]},columns=["name", "age"], index=[101, 102, 103]
)
print(df)
# ? ? name ?age
# 101 ? 張三?? 20
# 102 ? 李四?? 30
# 103 ? 王五?? 40

獲取DataFrame數據

方法分類

語法示例

描述

返回值類型

是否支持切片/條件索引

列選擇

df['col']

選擇單列(返回Series)

Series

?

df[['col1', 'col2']]

選擇多列(返回DataFrame)

DataFrame

行選擇

df.loc[row_label]

通過行標簽選擇單行(返回Series)

Series

?(標簽切片)

df.loc[start:end]

通過標簽切片選擇多行(閉區間)

DataFrame

df.iloc[row_index]

通過行位置選擇單行(從0開始)

Series

?(位置切片)

df.iloc[start:end]

通過位置切片選擇多行(左閉右開)

DataFrame

行列組合選擇

df.loc[row_labels, col_labels]

通過標簽選擇行和列(如df.loc['a':'b', ['col1','col2']])

Series/DataFrame

?

df.iloc[row_idx, col_idx]

通過位置選擇行和列(如df.iloc[0:2, [1,3]])

Series/DataFrame

條件篩選

df[df['col'] > 3]

通過布爾條件篩選行

DataFrame

?

df.query("col1 > 3 & col2 < 10")

使用表達式篩選(需字符串表達式)

DataFrame

快速訪問

df.at[row_label, 'col']

快速訪問單個值(標簽索引,高效)

標量值

?

df.iat[row_idx, col_idx]

快速訪問單個值(位置索引,高效)

標量值

頭部/尾部

df.head(n)

返回前n行(默認5)

DataFrame

?

df.tail(n)

返回后n行(默認5)

DataFrame

樣本抽樣

df.sample(n=3)

隨機抽取n行

DataFrame

索引重置

df.reset_index()

重置索引(原索引變為列)

DataFrame

設置索引

df.set_index('col')

指定某列作為新索引

DataFrame

  1. loc** vs ****iloc**??
  • loc:基于**標簽**(index/column names),切片為**閉區間**(如df.loc['a':'c']包含'c')。??
  • iloc:基于**整數位置**(從0開始),切片為**左閉右開**(如df.iloc[0:2]不包含索引2)。??

  1. 布爾條件篩選??
  • 支持組合條件(需用&、|,并用括號分隔條件):??
Python
df[(df['col1'] > 3) & (df['col2'] == 'A')]

  1. at**/****iat**** vs ****loc****/****iloc**??
  • at/iat:僅用于**訪問單個值**,速度更快。??
  • loc/iloc:支持多行/列選擇,功能更靈活。??

獲取一列數據

Python# 訪問數據
print(df['name']) ?#訪問某列數據
print(df.score)# df["col"] / df.col
df["name"] ??????# 返回?Series
df.name ?????
df[["name"]] ????# 返回?DataFrame

獲取多列數據

Python
df[["date", "temp_max", "temp_min"]] ?# 獲取多列數據
print(df[['name','score']]) # 訪問多列數據

獲取行數據

loc通過行標簽獲取數據

Python
df.loc[1] ?# 獲取行標簽為1的數據
df.loc[[1, 10, 100]] ?# 獲取行標簽分別為1、10、100的數據

iloc通過行位置獲取數據

Python
df.iloc[0] ?# 獲取行位置為0的數據
df.iloc[-1] ?# 獲取行位置為最后一位的數據

獲取指定單元格

Python
df.loc[101, "name"] ???# 標簽訪問
df.iloc[0, 1] ?????????# 位置訪問
df.loc[1, "precipitation"] ?# 獲取行標簽為1,列標簽為precipitation的數據
df.loc[:, "precipitation"] ?# 獲取所有行,列標簽為precipitation的數據
df.iloc[:, [3, 5, -1]] ?# 獲取所有行,列位置為3,5,最后一位的數據
df.iloc[:10, 2:6] ?# 獲取前10行,列位置為2、3、4、5的數據
df.loc[:10, ["date", "precipitation", "temp_max", "temp_min"]] ?# 通過行列標簽獲取數據

查看部分數據

通過head()、tail()獲取前n行或后n行

Python
print(df.head())
print(df.tail(10))

使用布爾索引篩選數據

Bash
# 條件篩選
df['score']>70
print(df[df.score>70])
print(df[(df['score']>70) & (df['age']<20)])
# 隨機抽樣
df.sample(2)

常用屬性

屬性

說明

index

DataFrame的行索引

columns

DataFrame的列標簽

values

DataFrame的值

ndim

DataFrame的維度

shape

DataFrame的形狀

size

DataFrame的元素個數

dtypes

DataFrame的元素類型

T

行列轉置

loc[]

顯式索引,按行列標簽索引或切片

iloc[]

隱式索引,按行列位置索引或切片

at[]

使用行列標簽訪問單個元素

iat[]

使用行列位置訪問單個元素

Python
import?pandas?as?pd
df?= pd.DataFrame(data={"id": [101, 102, 103], "name": ["張三", "李四", "王五"], "age": [20, 30, 40]},index=["aa", "bb", "cc"])
# index DataFrame的行索引
print(df.index)
# columns ? DataFrame的列標簽
print(df.columns)
# values ? ?DataFrame的值
print(df.values)
# ndim ?DataFrame的維度
print(df.ndim)
# shape DataFrame的形狀
print(df.shape)
# size ?DataFrame的元素個數
print(df.size)
# dtypes ? ?DataFrame的元素類型
print(df.dtypes)
# T 行列轉置
print(df.T)
# loc[] 顯式索引,按行列標簽索引或切片?逗號前是行切片規則,后是列切片規則
print(df.loc["aa":"cc"])
print(df.loc[:,["id","name"]])
# iloc[] ? ?隱式索引,按行列位置索引或切片
print(df.iloc[0:1])
print(df.iloc[0:3,2])
print("----------")
# at[] ?使用行列標簽訪問單個元素
print(df.at["aa","name"])
# iat[] 使用行列位置訪問單個元素
print(df.iat[0,1])

3.3.2 常用方法與統計

方法

說明

head()

查看前n行數據,默認5行

tail()

查看后n行數據,默認5行

isin()

元素是否包含在參數集合中

isna()

元素是否為缺失值

sum()

求和

mean()

平均值

min()

最小值

max()

最大值

var()

方差

std()

標準差

median()

中位數

mode()

眾數

quantile()

指定位置的分位數,如quantile(0.5)

describe()

常見統計信息

info()

基本信息

value_counts()

每個元素的個數

count()

非空元素的個數

drop_duplicates()

去重

sample()

隨機采樣

replace()

用指定值代替原有值

equals()

判斷兩個DataFrame是否相同

cummax()

累計最大值

cummin()

累計最小值

cumsum()

累計和

cumprod()

累計積

diff()

一階差分,對序列中的元素進行差分運算,也就是用當前元素減去前一個元素得到差值,默認情況下,它會計算一階差分,即相鄰元素之間的差值。參數:

periods:整數,默認為?1。表示要向前或向后移動的周期數,用于計算差值。正數表示向前移動,負數表示向后移動。

axis:指定計算的軸方向。0?或?'index'?表示按列計算,1?或?'columns'?表示按行計算,默認值為?0。

sort_index()

按行索引排序

sort_values()

按某列的值排序,可傳入列表來按多列排序,并通過ascending參數設置升序或降序

nlargest()

返回某列最大的n條數據

nsmallest()

返回某列最小的n條數據

Bash
import?pandas?as?pd
df?= pd.DataFrame(data={"id": [101, 102, 103,104,105,106,101], "name": ["張三", "李四", "王五","趙六","馮七","周八","張三"], "age": [10, 20, 30, 40, None, 60,10]},index=["aa", "bb", "cc", "dd", "ee", "ff","aa"])
# head() ? ?查看前n行數據,默認5行
print(df.head())
# tail() ? ?查看后n行數據,默認5行
print(df.tail())
# isin() ? ?元素是否包含在參數集合中
print(df.isin([103,106]))
# isna() ? ?元素是否為缺失值
print(df.isna())
# sum() 求和
print(df["age"].sum())
# mean() ? ?平均值
print(df["age"].mean())
# min() 最小值
print(df["age"].min())
# max() 最大值
print(df["age"].max())
# var() 方差
print(df["age"].var())
# std() 標準差
print(df["age"].std())
# median() ?中位數
print(df["age"].median())
# mode() ? ?眾數
print(df["age"].mode())
# quantile() ? ?指定位置的分位數,如quantile(0.5)
print(df["age"].quantile(0.5))
# describe() ? ?常見統計信息
print(df.describe())
# info() ? ?基本信息
print(df.info())
# value_counts() ? ?每個元素的個數
print(df.value_counts())
# count() ? 非空元素的個數
print(df.count())
# drop_duplicates() 去重??duplicated()判斷是否為重復行
print(df.duplicated(subset="age"))
# sample() ?隨機采樣
print(df.sample())
# replace() 用指定值代替原有值
print("----------------")
print(df.replace(20,"haha"))# cummax() ?累計最大值
df3?= pd.DataFrame({'A': [2, 5, 3, 7, 4],'B': [1, 6, 2, 8, 3]})
# 按列??等價于axis=0 默認
print(df3.cummax(axis="index"))
# 按行??等價于axis=1
print(df3.cummax(axis="columns"))
# cummin() ?累計最小值
print(df3.cummin())
# cumsum() ?累計和
print(df3.cumsum())
# cumprod() 累計積
print(df3.cumprod())
# diff() ? ?一階差分
print(df3.diff())
# sort_index() ?按行索引排序
print(df.sort_index())
# sort_values() 按某列的值排序,可傳入列表來按多列排序,并通過ascending參數設置升序或降序
print(df.sort_values(by="age"))
# nlargest() ? ?返回某列最大的n條數據
print(df.nlargest(n=2,columns="age"))
# nsmallest() ? 返回某列最小的n條數據
print(df.nsmallest(n=1,columns="age"))

在Pandas的?DataFrame?方法里,axis?是一個非常重要的參數,它用于指定操作的方向。

axis?參數可以取兩個主要的值,即?0?或?'index',以及?1?或?'columns'?,其含義如下:

  • axis=0?或?axis='index':表示操作沿著行的方向進行,也就是對每一列的數據進行處理。例如,當計算每列的均值時,就是對每列中的所有行數據進行計算。
  • axis=1?或?axis='columns':表示操作沿著列的方向進行,也就是對每行的數據進行處理。例如,當計算每行的總和時,就是對每行中的所有列數據進行計算。

3.3.3?運算

標量運算

標量與每個元素進行計算。

Python
df?= pd.DataFrame(data={"age": [20, 30, 40, 10], "name": ["張三", "李四", "王五", "趙六"]},columns=["name", "age"],index=[101, 104, 103, 102],
)
print(df?*?2)
# ? ? ?name ?age
# 101 ?張三張三?? 40
# 104 ?李四李四?? 60
# 103 ?王五王五?? 80
# 102 ?趙六趙六?? 20df1?= pd.DataFrame(data={"age": [10, 20, 30, 40], "name": ["張三", "李四", "王五", "趙六"]},columns=["name", "age"],index=[101, 102, 103, 104],
)
df2?= pd.DataFrame(data={"age": [10, 20, 30, 40], "name": ["張三", "李四", "王五", "田七"]},columns=["name", "age"],index=[102, 103, 104, 105],
)
print(df1?+?df2)
# ? ? ?name ? age
# 101 ? NaN ? NaN
# 102 ?李四張三??30.0
# 103 ?王五李四??50.0
# 104 ?趙六王五??70.0
# 105 ? NaN ? NaN

3.4 數據的導入與導出

導出數據

方法

說明

to_csv()

將數據保存為csv格式文件,數據之間以逗號分隔,可通過sep參數設置使用其他分隔符,可通過index參數設置是否保存行標簽,可通過header參數設置是否保存列標簽。

to_pickle()

如要保存的對象是計算的中間結果,或者保存的對象以后會在Python中復用,可把對象保存為.pickle文件。如果保存成pickle文件,只能在python中使用。文件的擴展名可以是.p、.pkl、.pickle。

to_excel()

保存為Excel文件,需安裝openpyxl包。

to_clipboard()

保存到剪切板。

to_dict()

保存為字典。

to_hdf()

保存為HDF格式,需安裝tables包。

to_html()

保存為HTML格式,需安裝lxml、html5lib、beautifulsoup4包。

to_json()

保存為JSON格式。

to_feather()

feather是一種文件格式,用于存儲二進制對象。feather對象也可以加載到R語言中使用。feather格式的主要優點是在Python和R語言之間的讀寫速度要比csv文件快。feather數據格式通常只用中間數據格式,用于Python和R之間傳遞數據,一般不用做保存最終數據。需安裝pyarrow包。

to_sql()

保存到數據庫。

Python
import?os
import?pandas?as?pdos.makedirs("data", exist_ok=True)
df?= pd.DataFrame({"age": [20, 30, 40, 10], "name": ["張三", "李四", "王五", "趙六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)df.to_csv("data/df.csv")
df.to_csv("data/df.tsv", sep="\t") ?# 設置分隔符為?\t
df.to_csv("data/df_noindex.csv", index=False) ?# index=False 不保存行索引
df.to_pickle("data/df.pkl")
df.to_excel("data/df.xlsx")
df.to_clipboard()
df_dict?= df.to_dict()
df.to_hdf("data/df.h5", key="df")
df.to_html("data/df.html")
df.to_json("data/df.json")
df.to_feather("data/df.feather")

導入數據

方法

說明

read_csv()

加載csv格式的數據。可通過sep參數指定分隔符,可通過index_col參數指定行索引。

read_pickle()

加載pickle格式的數據。

read_excel()

加載Excel格式的數據。

read_clipboard()

加載剪切板中的數據。

read_hdf()

加載HDF格式的數據。

read_html()

加載HTML格式的數據。

read_json()

加載JSON格式的數據。

read_feather()

加載feather格式的數據。

read_sql()

加載數據庫中的數據。

Python
df_csv?= pd.read_csv("data/df.csv", index_col="id") ?# 指定行索引
df_tsv?= pd.read_csv("data/df.tsv", sep="\t") ?# 指定分隔符
df_pkl?= pd.read_pickle("data/df.pkl")
df_excel?= pd.read_excel("data/df.xlsx", index_col="id")
df_clipboard?= pd.read_clipboard(index_col="id")
df_from_dict?= pd.DataFrame(df_dict)
df_hdf?= pd.read_hdf("data/df.h5", key="df")
df_html?= pd.read_html("data/df.html", index_col=0)[0]
df_json?= pd.read_json("data/df.json")
df_feather?= pd.read_feather("data/df.feather")print(df_csv)
print(df_tsv)
print(df_pkl)
print(df_excel)
print(df_clipboard)
print(df_from_dict)
print(df_hdf)
print(df_html)
print(df_json)
print(df_feather)

3.5 數據清洗與預處理

章節

核心內容

關鍵知識點

1. 缺失值處理

檢測、刪除和填充缺失值的方法

isna(), dropna(), fillna(), 前向/后向填充, 均值/中位數填充

2. 重復數據處理

識別和刪除重復行

duplicated(), drop_duplicates(), 按列去重, 保留首次/最后一次出現

3. 數據類型轉換

強制類型轉換、日期/分類數據處理

astype(), to_datetime(), 分類數據優化, 數值格式化

4. 數據重塑與變形

行列轉置、寬表長表轉換、分列操作

T轉置, melt(), pivot(), str.split()分列

5. 文本數據處理

字符串清洗、正則提取、大小寫轉換

str.lower(), str.replace(), str.extract(), 空格處理

6. 數據分箱與離散化

數值分箱(等寬/等頻)

pd.cut(), pd.qcut(), 離散化應用場景

7. 其他常用轉換

重命名列、索引操作、函數應用、內存優化

rename(), set_index(), apply(), 類型優化減少內存占用

1. ?缺失值處理

方法/操作

語法示例

描述

檢測缺失值

df.isna()?或?df.isnull()

返回布爾矩陣,標記缺失值(NaN或None)

統計缺失值

df.isna().sum()

每列缺失值數量統計

刪除缺失值

df.dropna()

刪除包含缺失值的行(默認)

df.dropna(axis=1)

刪除包含缺失值的列

df.dropna(subset=['col1'])

僅刪除指定列的缺失值行

填充缺失值

df.fillna(value)

用固定值填充(如df.fillna(0)

df.fillna(method='ffill')

用前一個非缺失值填充(向前填充)

df.fillna(method='bfill')

用后一個非缺失值填充(向后填充)

df.fillna(df.mean())

用列均值填充

pandas中的缺失值

  • NaN (Not a Number) 是缺失值的標志
  • 方法:?isna(), notna()

pandas使用浮點值NaN(Not a Number)表示缺失數據,使用NA(Not Available)表示缺失值。可以通過isnull()、isna()或notnull()、notna()方法判斷某個值是否為缺失值。

Nan通常表示一個無效的或未定義的數字值,是浮點數的一種特殊取值,用于表示那些不能表示為正常數字的情況,如?0/0、∞-∞等數學運算的結果。nan與任何值(包括它自身)進行比較的結果都為False。例如在?Python 中,nan == nan返回False。

NA一般用于表示數據不可用或缺失的情況,它的含義更側重于數據在某種上下文中是缺失或不存在的,不一定特指數字類型的缺失。

na和nan都用于表示缺失值,但nan更強調是數值計算中的特殊值,而na更強調數據的可用性或存在性。

Plain Text
s?= pd.Series([np.nan, None, pd.NA])
print(s)
# 0 ? ? NaN
# 1 ? ?None
# 2 ? ?<NA>
# dtype: object
print(s.isnull())
# 0 ? ?True
# 1 ? ?True
# 2 ? ?True
# dtype: bool

加載數據中包含缺失值

Python
df?= pd.read_csv("data/weather_withna.csv")
print(df.tail(5))
# ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind weather
# 1456 ?2015-12-27 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1457 ?2015-12-28 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1458 ?2015-12-29 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1459 ?2015-12-30 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1460 ?2015-12-31 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain

可以通過keep_default_na參數設置是否將空白值設置為缺失值。

Python
df?= pd.read_csv("data/weather_withna.csv", keep_default_na=False)
print(df.tail(5))
# ? ? ? ? ? ? date precipitation temp_max temp_min wind weather
# 1456 ?2015-12-27
# 1457 ?2015-12-28
# 1458 ?2015-12-29
# 1459 ?2015-12-30
# 1460 ?2015-12-31 ? ? ? ? ?20.6 ? ? 12.2 ? ? ?5.0 ?3.8 ? ?rain

可通過na_values參數將指定值設置為缺失值。

Python
df?= pd.read_csv("data/weather_withna.csv", na_values=["2015-12-31"])
print(df.tail(5))
# ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind weather
# 1456 ?2015-12-27 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1457 ?2015-12-28 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1458 ?2015-12-29 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1459 ?2015-12-30 ? ? ? ? ? ?NaN ? ? ? NaN ? ? ? NaN ? NaN ? ? NaN
# 1460 ? ? ? ? NaN ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain

查看缺失值

通過isnull()查看缺失值數量

Python
df?= pd.read_csv("data/weather_withna.csv")
print(df.isnull().sum())
# date ? ? ? ? ? ? ? 0
# precipitation ? ?303
# temp_max ? ? ? ? 303
# temp_min ? ? ? ? 303
# wind ? ? ? ? ? ? 303
# weather ? ? ? ? ?303
# dtype: int64

剔除缺失值

通過dropna()方法來剔除缺失值。

Series剔除缺失值

Python
s?= pd.Series([1, pd.NA, None])
print(s)
# 0 ? ? ? 1
# 1 ? ?<NA>
# 2 ? ?None
# dtype: object
print(s.dropna())
# 0 ? ?1
# dtype: object

DataFrame剔除缺失值

無法從DataFrame中單獨剔除一個值,只能剔除缺失值所在的整行或整列。默認情況下,dropna()會剔除任何包含缺失值的整行數據。

Python
df?= pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(df)
# ? ? ? 0 ? ? 1 ?2
# 0 ? ? 1 ?<NA> ?2
# 1 ? ? 2 ? ? 3 ?5
# 2 ?<NA> ? ? 4 ?6
print(df.dropna())
# ? ?0 ?1 ?2
# 1 ?2 ?3 ?5

可以設置按不同的坐標軸剔除缺失值,比如axis=1(或?axis='columns')會剔除任何包含缺失值的整列數據。

df?= pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])print(df)# ? ? ? 0 ? ? 1 ?2# 0 ? ? 1 ?<NA> ?2# 1 ? ? 2 ? ? 3 ?5# 2 ?<NA> ? ? 4 ?6print(df.dropna(axis=1))# ? ?2# 0 ?2# 1 ?5# 2 ?6

有時只需要剔除全部是缺失值的行或列,或者絕大多數是缺失值的行或列。這些需求可以通過設置how或thresh參數來滿足,它們可以設置剔除行或列缺失值的數量閾值。

df?= pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])print(df)# ? ? ? 0 ? ? 1 ? ? 2# 0 ? ? 1 ?<NA> ? ? 2# 1 ?<NA> ?<NA> ? ? 5# 2 ?<NA> ?<NA> ?<NA>print(df.dropna(how="all")) ?# 如果所有值都是缺失值,則刪除這一行# ? ? ? 0 ? ? 1 ?2# 0 ? ? 1 ?<NA> ?2# 1 ?<NA> ?<NA> ?5print(df.dropna(thresh=2)) ?# 如果至少有2個值不是缺失值,則保留這一行# ? ?0 ? ? 1 ?2# 0 ?1 ?<NA> ?2

可以通過設置subset參數來設置某一列有缺失值則進行剔除。

df?= pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])print(df)# ? ? ? 0 ? ? 1 ? ? 2# 0 ? ? 1 ?<NA> ? ? 2# 1 ?<NA> ?<NA> ? ? 5# 2 ?<NA> ?<NA> ?<NA>print(df.dropna(subset=[0])) ?# 如果0列有缺失值,則刪除這一行# ? ?0 ? ? 1 ?2# 0 ?1 ?<NA> ?2

填充缺失值

  1. 使用固定值填充

通過fillna()方法,傳入值或字典進行填充。

df?= pd.read_csv("data/weather_withna.csv")print(df.fillna(0).tail()) ?# 使用固定值填充# ?print(df.fillna({"temp_max": 60, "temp_min": -60}).tail()) ?# 使用字典來填充# ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind weather# 1456 ?2015-12-27 ? ? ? ? ? ?NaN ? ? ?60.0 ? ? -60.0 ? NaN ? ? NaN# 1457 ?2015-12-28 ? ? ? ? ? ?NaN ? ? ?60.0 ? ? -60.0 ? NaN ? ? NaN# 1458 ?2015-12-29 ? ? ? ? ? ?NaN ? ? ?60.0 ? ? -60.0 ? NaN ? ? NaN# 1459 ?2015-12-30 ? ? ? ? ? ?NaN ? ? ?60.0 ? ? -60.0 ? NaN ? ? NaN# 1460 ?2015-12-31 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain
  1. 使用統計值填充

通過fillna()方法,傳入統計后的值進行填充。

print(df.fillna(df[["precipitation", "temp_max", "temp_min", "wind"]].mean()).tail()) ?# 使用平均值填充# ? ? ? ? ? ? date ?precipitation ? temp_max ?temp_min ? ? ?wind weather# 1456 ?2015-12-27 ? ? ? 3.052332 ?15.851468 ?7.877202 ?3.242055 ? ? NaN# 1457 ?2015-12-28 ? ? ? 3.052332 ?15.851468 ?7.877202 ?3.242055 ? ? NaN# 1458 ?2015-12-29 ? ? ? 3.052332 ?15.851468 ?7.877202 ?3.242055 ? ? NaN# 1459 ?2015-12-30 ? ? ? 3.052332 ?15.851468 ?7.877202 ?3.242055 ? ? NaN# 1460 ?2015-12-31 ? ? ?20.600000 ?12.200000 ?5.000000 ?3.800000 ? ?rain
  1. 使用前后的有效值填充

通過ffill()或bfill()方法使用前面或后面的有效值填充。

print(df.ffill().tail()) ?# 使用前面的有效值填充# ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind weather# 1456 ?2015-12-27 ? ? ? ? ? ?0.0 ? ? ?11.1 ? ? ? 4.4 ? 4.8 ? ? sun# 1457 ?2015-12-28 ? ? ? ? ? ?0.0 ? ? ?11.1 ? ? ? 4.4 ? 4.8 ? ? sun# 1458 ?2015-12-29 ? ? ? ? ? ?0.0 ? ? ?11.1 ? ? ? 4.4 ? 4.8 ? ? sun# 1459 ?2015-12-30 ? ? ? ? ? ?0.0 ? ? ?11.1 ? ? ? 4.4 ? 4.8 ? ? sun# 1460 ?2015-12-31 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rainprint(df.bfill().tail()) ?# 使用后面的有效值填充# ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind weather# 1456 ?2015-12-27 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain# 1457 ?2015-12-28 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain# 1458 ?2015-12-29 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain# 1459 ?2015-12-30 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain# 1460 ?2015-12-31 ? ? ? ? ? 20.6 ? ? ?12.2 ? ? ? 5.0 ? 3.8 ? ?rain

通過線性插值填充

通過interpolate()方法進行線性插值填充。線性插值操作,就是用于在已知數據點之間估算未知數據點的值。interpolate?方法支持多種插值方法,可通過?method?參數指定,常見的方法有:

  • 'linear':線性插值,基于兩點之間的直線來估算缺失值,適用于數據呈線性變化的情況。
  • 'time':適用于時間序列數據,會考慮時間間隔進行插值。
  • 'polynomial':多項式插值,通過擬合多項式曲線來估算缺失值,可通過?order?參數指定多項式的階數。
import?pandas?as?pdimport?numpy?as?np# 創建包含缺失值的?Seriess?= pd.Series([1, np.nan, 3, 4, np.nan, 6])# 使用默認的線性插值方法填充缺失值s_interpolated?= s.interpolate()print(s_interpolated)# 0 ? ?1.0# 1 ? ?2.0# 2 ? ?3.0# 3 ? ?4.0# 4 ? ?5.0# 5 ? ?6.0# dtype: float64
Bash
# 缺失值
import numpy as np
# 缺失值的類型?nan na
s = pd.Series([np.nan, None, pd.NA,2,4])
df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(s)
print(s.isnull()) ?#查看是否是缺失值
print(s.isna()) #查看是否是缺失值
print(s.isna().sum()) # 缺失值的個數
# 剔除缺失值
print(s.dropna()) ?#series剔除缺失值
print(df.dropna()) #只要有缺失值,就剔除一整條記錄
print(df.dropna(how="all")) # 如果所有值都是缺失值,則刪除這一行
print(df.dropna(thresh=2)) # 如果至少有2個值不是缺失值,則保留這一行
print(df.dropna(axis=1)) ?#剔除一列中含缺失值的列
#可以通過設置subset參數來設置某一列有缺失值則進行剔除。
print(df.dropna(subset=[0]))# 如果0列有缺失值,則刪除這一行
#填充缺失值
print('********')
df = pd.read_csv("data/weather_withna.csv")
# df = df.fillna({"temp_max": 60, "temp_min": -60}) # 使用字典來填充
print(df['temp_max'].mean())
df.fillna(df[["precipitation", "temp_max", "temp_min", "wind"]].mean()).tail() # 使用平均值填充
print(df.ffill().tail()) # 使用前面的有效值填充
print(df.bfill().tail()) # 使用后面的有效值填充df1 = pd.read_csv("data/weather_withna.csv")
df2 = pd.read_csv("data/weather_withna.csv", keep_default_na=False)
print(df1.temp_max.count())
print(df1.isnull().sum())
print(df2.temp_max.count())
print(df2.isnull().sum())
# 將
df = pd.read_csv("data/weather_withna.csv", na_values=["2015-12-31"])
# print(df.tail(5))
print(df.isnull().sum())

2. 重復數據處理

方法/操作

語法示例

描述

檢測重復行

df.duplicated()

返回布爾序列標記重復行(首次出現的行標記為False)

刪除重復行

df.drop_duplicates()

保留首次出現的行(默認檢查所有列)

df.drop_duplicates(subset=['col1'])

僅根據指定列去重

df.drop_duplicates(keep='last')

保留最后一次出現的行

1. 檢測重復行

Python
import pandas as pd# 創建包含重復數據的DataFrame
data = {'Name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'],'Age': [25, 30, 25, 35, 30],'City': ['NY', 'LA', 'NY', 'SF', 'LA']
}
df = pd.DataFrame(data)# 檢測重復行(默認檢查所有列)
print("重復行標記(False表示首次出現,True表示重復):")
print(df.duplicated())

輸出

Plain Text
0 ???False
1 ???False
2 ????True
3 ???False
4 ????True
dtype: bool

2. 刪除重復行

Python
# 默認保留首次出現的行
df_unique = df.drop_duplicates()
print("去重后的DataFrame:")
print(df_unique)

輸出

Plain TextName ?Age City
0 ???Alice ??25 ??NY
1 ?????Bob ??30 ??LA
3 ?Charlie ??35 ??SF

3. 按指定列去重

Python
# 僅根據'Name'列去重(保留首次出現)
df_name_unique = df.drop_duplicates(subset=['Name'])
print("按Name列去重:")
print(df_name_unique)

輸出

Plain TextName ?Age City
0 ???Alice ??25 ??NY
1 ?????Bob ??30 ??LA
3 ?Charlie ??35 ??SF

4. 保留最后一次出現的重復行

Python
# 保留最后一次出現的行
df_last = df.drop_duplicates(keep='last')
print("保留最后一次出現的行:")
print(df_last)

輸出

Plain TextName ?Age City
2 ???Alice ??25 ??NY
4 ?????Bob ??30 ??LA
3 ?Charlie ??35 ??SF

5. 綜合案例:處理真實數據

Python
# 加載包含重復值的數據(示例)
df_sales = pd.read_csv("sales_data.csv")# 檢查重復行數量
print("原始數據重復行數:", df_sales.duplicated().sum())# 按'Order_ID'列去重,保留最后一次記錄
df_clean = df_sales.drop_duplicates(subset=['Order_ID'], keep='last')# 驗證結果
print("去重后數據行數:", len(df_clean))

注意事項

  1. 性能優化:對大數據集去重時,可通過?subset?指定關鍵列以減少計算量。
  1. 邏輯一致性:確保?keep='last'?或?keep=False(刪除所有重復)符合業務需求。
  1. 多列去重:subset=['col1', 'col2']?可聯合多列判斷重復。

通過以上案例,可以靈活應對實際數據清洗中的重復值問題!

3. ?數據類型轉換

方法/操作

語法示例

描述

查看數據類型

df.dtypes

顯示每列的數據類型

強制類型轉換

df['col'].astype('int')

將列轉換為指定類型(如int, float, str, datetime)

轉換為日期時間

pd.to_datetime(df['col'])

將字符串列轉為datetime類型

轉換為分類數據

df['col'].astype('category')

將列轉為分類類型(節省內存,提高性能)

數值格式化

df['col'].round(2)

保留2位小數

核心方法

操作

方法/函數

描述

查看數據類型

df.dtypes

顯示每列的數據類型(如int64、float64、object等)。

強制類型轉換

df['col'].astype('type')

將列轉換為指定類型(如int、float、str、bool等)。

轉換為日期時間

pd.to_datetime(df['col'])

將字符串或數值列轉為datetime類型(支持自定義格式)。

轉換為分類數據

df['col'].astype('category')

將列轉為分類類型(節省內存,提高性能,適用于有限取值的列如性別、省份)。

數值格式化

df['col'].round(2)

保留指定小數位數(如2位)。

代碼案例講解

1. 查看數據類型

Python
import pandas as pd# 加載數據(以sleep.csv為例)
df = pd.read_csv("sleep.csv")
print(df.dtypes)

輸出示例

Plain Text
person_id ????????????????????int64
gender ??????????????????????object
age ??????????????????????????int64
occupation ??????????????????object
sleep_duration ?????????????float64
sleep_quality ??????????????float64
... ?????????????????????????...

說明:object通常為字符串或混合類型,需檢查是否需要轉換。

2. 強制類型轉換

將數值列轉換為整數或字符串:

Python
# 將sleep_duration從float轉為int(丟失小數部分)
df['sleep_duration_int'] = df['sleep_duration'].astype('int32')# 將gender轉為字符串
df['gender_str'] = df['gender'].astype('str')print(df[['sleep_duration', 'sleep_duration_int', 'gender_str']].head())

輸出

Plain Text
sleep_duration ?sleep_duration_int gender_str
0 ????????????7.4 ?????????????????7 ??????Male
1 ????????????4.2 ?????????????????4 ????Female
2 ????????????6.1 ?????????????????6 ??????Male

3. 轉換為日期時間

處理時間數據(假設employees.csv有日期列):

Python
# 示例:創建臨時日期列(實際數據可能為hire_date)
df_employees = pd.read_csv("employees.csv")
df_employees['fake_date'] = '2023-01-' + df_employees['employee_id'].astype(str).str[:2]# 轉換為datetime
df_employees['fake_date'] = pd.to_datetime(df_employees['fake_date'])
print(df_employees[['employee_id', 'fake_date']].head())

輸出

Plain Textemployee_id ?fake_date
0 ?????????100 2023-01-10
1 ?????????101 2023-01-10
2 ?????????102 2023-01-10

注意:若原始格式非標準,需指定格式參數,如:??

pd.to_datetime(df['date'], format='%Y/%m/%d')

4. 轉換為分類數據

優化內存和性能(適用于低基數列):

Python
# 將gender列轉為分類類型
df['gender'] = df['gender'].astype('category')
print(df['gender'].dtypes)

輸出

Plain Text
category

優勢:??

  • 減少內存占用(尤其對重復值多的列)。??
  • 加速groupby、sort等操作。

5. 數值格式化

控制小數位數:

Python
# 保留sleep_quality的2位小數
df['sleep_quality_rounded'] = df['sleep_quality'].round(2)
print(df[['sleep_quality', 'sleep_quality_rounded']].head())

輸出

Plain Textsleep_quality ?sleep_quality_rounded
0 ???????????7.0 ??????????????????7.00
1 ???????????4.9 ??????????????????4.90
2 ???????????6.0 ??????????????????6.00

常見問題與技巧

  1. 處理轉換錯誤:使用errors='coerce'將無效值轉為NaN,避免報錯:
Python
df['age'] = pd.to_numeric(df['age'], errors='coerce')

  1. 內存優化:將數值列從int64轉為int32或float32:
Python
df['age'] = df['age'].astype('int32')

  1. 布爾類型轉換:將字符串(如"Yes"/"No")轉為布爾值:
Python
df['is_active'] = df['active_flag'].map({'Yes': True, 'No': False})

  1. 自定義格式化:使用apply實現復雜轉換(如百分比):
Python
df['score_percent'] = df['score'].apply(lambda x: f"{x*100:.1f}%")

實戰案例:處理penguins.csv

Python
df_penguins = pd.read_csv("penguins.csv")# 1. 轉換sex為分類類型
df_penguins['sex'] = df_penguins['sex'].astype('category')# 2. 補全缺失值后轉換bill_length_mm為float32
df_penguins['bill_length_mm'] = df_penguins['bill_length_mm'].fillna(0).astype('float32')# 3. 檢查并輸出結果
print(df_penguins[['species', 'sex', 'bill_length_mm']].dtypes)

輸出

Plain Text
species ??????????object
sex ????????????category
bill_length_mm ???float32

4. ?數據重塑與變形

方法/操作

語法示例

描述

行列轉置

df.T

轉置DataFrame(行變列,列變行)

寬表轉長表

pd.melt(df, id_vars=['id'])

將多列合并為鍵值對形式(variable和value列)

長表轉寬表

df.pivot(index='id', columns='var', values='val')

將長表轉換為寬表(類似Excel數據透視)

分列操作

df['col'].str.split(',', expand=True)

按分隔符拆分字符串為多列

1. 行列轉置(df.T

將DataFrame的行列互換,適用于需要橫向展示數據的場景。

Python
import pandas as pd

# 示例數據
data = {
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['NY', 'LA', 'SF']
}
df = pd.DataFrame(data)

# 行列轉置
df_transposed = df.T
print("原始數據:\n", df)
print("\n轉置后數據:\n", df_transposed)

輸出

Plain Text
原始數據:
Name ?Age City
0 ???Alice ??25 ??NY
1 ?????Bob ??30 ??LA
2 ?Charlie ??35 ??SF

轉置后數據:
0 ????1 ??????2
Name ??Alice ??Bob ?Charlie
Age ??????25 ???30 ??????35
City ????NY ???LA ??????SF

2. 寬表轉長表(**pd.melt()**

將多列合并為鍵值對形式,適合分析多指標數據。

Python

輸出

Plain Text
原始數據:
ID ?Math ?English ?Science
0 ??1 ???90 ??????88 ??????95
1 ??2 ???85 ??????92 ??????89

轉換后數據:
ID ?Subject ?Score
0 ??1 ????Math ????90
1 ??2 ????Math ????85
2 ??1 ?English ????88
3 ??2 ?English ????92
4 ??1 ?Science ????95
5 ??2 ?Science ????89

3. 長表轉寬表(**df.pivot()**

將長表轉換為寬表,類似Excel的數據透視表。

Python
# 示例數據(長表)
data = {
'ID': [1, 1, 1, 2, 2, 2],
'Subject': ['Math', 'English', 'Science', 'Math', 'English', 'Science'],
'Score': [90, 88, 95, 85, 92, 89]
}
df = pd.DataFrame(data)

# 長表轉寬表(以ID為索引,Subject為列,Score為值)
df_pivoted = df.pivot(index='ID', columns='Subject', values='Score')
print("原始數據:\n", df)
print("\n轉換后數據:\n", df_pivoted)

輸出

Plain Text
原始數據:
ID ?Subject ?Score
0 ??1 ????Math ????90
1 ??1 ?English ????88
2 ??1 ?Science ????95
3 ??2 ????Math ????85
4 ??2 ?English ????92
5 ??2 ?Science ????89

轉換后數據:
Subject ?English ?Math ?Science
ID ???????????????????????????
1 ??????????88 ???90 ??????95
2 ??????????92 ???85 ??????89

4. 分列操作(**str.split()**

按分隔符拆分字符串列,生成多列。

Python
# 示例數據
data = {
'Full_Name': ['Alice Smith', 'Bob Johnson', 'Charlie Brown']
}
df = pd.DataFrame(data)

# 拆分Full_Name為FirstName和LastName
df[['First_Name', 'Last_Name']] = df['Full_Name'].str.split(' ', expand=True)
print("原始數據:\n", df[['Full_Name']])
print("\n拆分后數據:\n", df[['First_Name', 'Last_Name']])

輸出

Plain Text
原始數據:
Full_Name
0 ???Alice Smith
1 ??Bob Johnson
2 ?Charlie Brown

拆分后數據:
First_Name Last_Name
0 ?????Alice ????Smith
1 ???????Bob ??Johnson
2 ???Charlie ????Brown

注意事項

  1. pivot**與****pivot_table****的區別**:??
  • pivot要求索引和列的組合唯一,否則報錯。??
  • pivot_table支持聚合(如均值、求和),適合非唯一組合。

  1. 分列操作:??
  • 使用expand=True將拆分結果轉為多列。??
  • 若分隔符數量不一致,需預處理數據(如填充缺失值)。

  1. 內存管理:??
  • 寬表轉長表可能增加行數,需注意內存占用。

Bash
#數據變形
import pandas as pd
data = {
'ID': [1, 2],
'name':['alice','bob'],
'Math': [90, 85],
'English': [88, 92],
'Science': [95, 89]
}
df = pd.DataFrame(data)
df
df.T
#寬表轉長表
df2= pd.melt(df, id_vars=['ID','name'], var_name='科目', value_name='分數')
df2.sort_values(by=['name','科目'])
#長表轉寬表
df3=pd.pivot(df2,index=['ID','name'],columns=['科目'],values='分數')
#分列
data = {
'ID': [1, 2],
'name':['alice smith','bob jack'],
'Math': [90, 85],
'English': [88, 92],
'Science': [95, 89]
}
df = pd.DataFrame(data)
df[['first name','last name']] = df['name'].str.split(' ',expand=True)
# 加載數據
df = pd.read_csv("data/sleep.csv")

df=df[['person_id','blood_pressure']]
df[['high','low']]=df['blood_pressure'].str.split('/',expand=True)
df

5. ??文本數據處理

方法/操作

語法示例

描述

字符串大小寫轉換

df['col'].str.lower()

轉為小寫

去除空格

df['col'].str.strip()

去除兩端空格

字符串替換

df['col'].str.replace('old', 'new')

替換文本

正則表達式提取

df['col'].str.extract(r'(\d+)')

提取匹配正則的文本(如數字)

字符串包含檢測

df['col'].str.contains('abc')

返回布爾序列,判斷是否包含子串

1. 字符串大小寫轉換

統一文本格式,便于后續分析(如姓名、地址等)。

Python
import pandas as pd

# 示例數據
data = {'Name': ['ALICE', 'Bob', 'CHARLIE']}
df = pd.DataFrame(data)

# 轉為小寫
df['Name_lower'] = df['Name'].str.lower()

# 轉為大寫
df['Name_upper'] = df['Name'].str.upper()

print(df)

輸出

Plain Text
Name Name_lower Name_upper
0 ???ALICE ?????alice ?????ALICE
1 ?????Bob ???????bob ???????BOB
2 ?CHARLIE ???charlie ???CHARLIE

2. 去除空格

處理用戶輸入或爬取數據中的多余空格。

Python
# 示例數據(含前后空格)
data = {'Text': [' ?Hello ?', ' ?Pandas ?', ' ?Data ?']}
df = pd.DataFrame(data)

# 去除兩端空格
df['Text_stripped'] = df['Text'].str.strip()

print(df)

輸出

Plain Text
Text Text_stripped
0 ???Hello ????????Hello
1 ??Pandas ???????Pandas
2 ????Data ?????????Data

3. 字符串替換

替換文本中的特定字符或模式(如清理臟數據)。

Python
# 示例數據(含特殊字符)
data = {'Comment': ['Good!', 'Bad?', 'Okay...']}
df = pd.DataFrame(data)

# 替換標點符號為空字符串
df['Comment_clean'] = df['Comment'].str.replace(r'[!?.]', '', regex=True)

print(df)

輸出

Plain Text
Comment Comment_clean
0 ???Good! ?????????Good
1 ????Bad? ??????????Bad
2 ?Okay... ?????????Okay

4. 正則表達式提取

從文本中提取結構化信息(如電話號碼、日期)。

Python
# 示例數據(含混合文本)
data = {'Info': ['Age:25', 'Height:170cm', 'Weight:65kg']}
df = pd.DataFrame(data)

# 提取數字
df['Value'] = df['Info'].str.extract(r'(\d+)')

print(df)

輸出

Plain Text
Info Value
0 ??????Age:25 ???25
1 ?Height:170cm ??170
2 ??Weight:65kg ???65

5. 字符串包含檢測

篩選包含特定關鍵詞的記錄。

Python
# 示例數據(產品評論)
data = {'Review': ['Great product', 'Not good', 'Excellent service']}
df = pd.DataFrame(data)

# 檢測是否包含"good"(不區分大小寫)
df['Is_Positive'] = df['Review'].str.contains('good', case=False)

print(df)

輸出

Plain Text
Review ?Is_Positive
0 ???Great product ????????True
1 ????????Not good ????????True
2 ?Excellent service ???????False

實戰案例:處理employees.csv

清理員工姓名和郵箱數據:

Python
# 加載數據
df_employees = pd.read_csv("employees.csv")

# 1. 將first_name首字母大寫,其余小寫
df_employees['first_name'] = df_employees['first_name'].str.capitalize()

# 2. 提取郵箱域名(@后部分)
df_employees['email_domain'] = df_employees['email'].str.extract(r'@(.+)')

print(df_employees[['first_name', 'email', 'email_domain']].head())

輸出

Plain Text
first_name ??????email email_domain
0 ????Steven ?SKING@abc.com ?????abc.com
1 ?????N_ann ?NKOCHHAR@abc.com ???abc.com
2 ???????Lex ?LDEHAAN@abc.com ???abc.com

6. ?數據分箱與離散化

方法/操作

語法示例

描述

等寬分箱

pd.cut(df['col'], bins=3)

將數值列分為等寬區間(如分為低/中/高)

等頻分箱

pd.qcut(df['col'], q=4)

將數值列分為等頻區間(每箱數據量相同)

cut()

pandas.cut()用于將連續數據(如數值型數據)分割成離散的區間。可以使用cut()來將數據劃分為不同的類別或范圍,通常用于數據的分箱處理。

cut()部分參數說明:

參數

說明

x

要分箱的數組或Series,通常是數值型數據。

bins

切分區間的數值列表或者整數。如果是整數,則表示將數據均勻地分成多少個區間。如果是列表,則需要指定每個區間的邊界。

right

默認True,表示每個區間的右端點是閉區間,即包含右端點。如果設置為False,則左端點為閉區間。

labels

傳入一個列表指定每個區間的標簽。

Bash
df = pd.read_csv("data/employees.csv")# 加載員工數據


df1 = df.iloc[:10]
print(df1["salary"])

salary = pd.cut(df.iloc[9:16]["salary"], 3)
print(salary)

salary = pd.cut(df1["salary"], [0, 10000, 20000])
print(salary)

df['salary_level'] = pd.cut(df["salary"], bins=3, labels=["low", "medium", "high"])
print(df['salary_level'])

df['salary_level'] = pd.cut(df["salary"], bins=[0, 10000, 20000,300000], labels=["low", "medium", "high"])
print(df['salary_level'])


df = pd.read_csv("data/employees.csv")# 加載員工數據
salary = pd.cut(df["salary"], 3)
print(salary.value_counts())
salary2 = pd.qcut(df["salary"], 3)
print(salary2.value_counts())

#睡眠數據分箱
df_sleep = pd.read_csv("data/sleep.csv")

# 將睡眠質量分為3組:差(0-4)、中(4-7)、好(7-10)
bins = [0, 4, 7, 10]
labels = ['差', '中', '好']

df_sleep['quality_level'] = pd.cut(
df_sleep['sleep_quality'],
bins=bins,
labels=labels
)
print(df_sleep[ 'quality_level'])
print(df_sleep[ 'quality_level'].value_counts())

7. ?其他常用轉換

  • df.rename(columns={"score": "成績"})
  • df.set_index("name")
  • df.reset_index()

Python
df?= pd.DataFrame({"age": [20, 30, 40, 10], "name": ["張三", "李四", "王五", "趙六"], "id": [101, 102, 103, 104]})
print(df)
# ? ?age name ? id
# 0 ? 20 ? 張三??101
# 1 ? 30 ? 李四??102
# 2 ? 40 ? 王五??103
# 3 ? 10 ? 趙六??104
#通過set_index()設置行索引
# inplace=True:這是一個布爾類型的參數。當設為?True 時,會直接在原?
# DataFrame上進行修改;若設為?False(默認值),則會返回一個新的?
# DataFrame,原DataFrame 保持不變
df.set_index("id", inplace=True) ?# 設置行索引
print(df)
df.reset_index(inplace=True) ?# 重置索引
print(df)
#修改行索引名和列名??個別修改
df.rename(index={101: "一", 102: "二", 103: "三", 104: "四"}, columns={"age": "年齡", "name": "姓名"}, inplace=True)
print(df)
#重新賦值??批量修改
df.index?= ["Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ"]
df.columns?= ["年齡", "名稱"]
#添加列
通過?df[“列名”] 添加列。
df["phone"] = ["13333333333", "14444444444", "15555555555", "16666666666"]
#刪除列
# 通過?df.drop(“列名”, axis=1) 刪除,也可是刪除行?axis=0
df.drop("phone", axis=1, inplace=True) ?# 刪除phone,按列刪除,inplace=True表示直接在原對象上修改
print(df)
#通過?del df[“列名”] 刪除
del?df["phone"]
print(df)
#插入列?通過?insert(loc, column, value) 插入。該方法沒有inplace參數,直接在原數據上修改。
df.insert(loc=0, column="phone", value=df["age"] *?df.index)
print(df)

3.4 數據的導入與導出

導出數據

方法

說明

to_csv()

將數據保存為csv格式文件,數據之間以逗號分隔,可通過sep參數設置使用其他分隔符,可通過index參數設置是否保存行標簽,可通過header參數設置是否保存列標簽。

to_pickle()

如要保存的對象是計算的中間結果,或者保存的對象以后會在Python中復用,可把對象保存為.pickle文件。如果保存成pickle文件,只能在python中使用。文件的擴展名可以是.p、.pkl、.pickle。

to_excel()

保存為Excel文件,需安裝openpyxl包。

to_clipboard()

保存到剪切板。

to_dict()

保存為字典。

to_hdf()

保存為HDF格式,需安裝tables包。

to_html()

保存為HTML格式,需安裝lxml、html5lib、beautifulsoup4包。

to_json()

保存為JSON格式。

to_feather()

feather是一種文件格式,用于存儲二進制對象。feather對象也可以加載到R語言中使用。feather格式的主要優點是在Python和R語言之間的讀寫速度要比csv文件快。feather數據格式通常只用中間數據格式,用于Python和R之間傳遞數據,一般不用做保存最終數據。需安裝pyarrow包。

to_sql()

保存到數據庫。

Python
import?os
import?pandas?as?pd

os.makedirs("data", exist_ok=True)
df?= pd.DataFrame({"age": [20, 30, 40, 10], "name": ["張三", "李四", "王五", "趙六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)

df.to_csv("data/df.csv")
df.to_csv("data/df.tsv", sep="\t") ?# 設置分隔符為?\t
df.to_csv("data/df_noindex.csv", index=False) ?# index=False 不保存行索引
df.to_pickle("data/df.pkl")
df.to_excel("data/df.xlsx")
df.to_clipboard()
df_dict?= df.to_dict()
df.to_hdf("data/df.h5", key="df")
df.to_html("data/df.html")
df.to_json("data/df.json")
df.to_feather("data/df.feather")

導入數據

方法

說明

read_csv()

加載csv格式的數據。可通過sep參數指定分隔符,可通過index_col參數指定行索引。

read_pickle()

加載pickle格式的數據。

read_excel()

加載Excel格式的數據。

read_clipboard()

加載剪切板中的數據。

read_hdf()

加載HDF格式的數據。

read_html()

加載HTML格式的數據。

read_json()

加載JSON格式的數據。

read_feather()

加載feather格式的數據。

read_sql()

加載數據庫中的數據。

Python
df_csv?= pd.read_csv("data/df.csv", index_col="id") ?# 指定行索引
df_tsv?= pd.read_csv("data/df.tsv", sep="\t") ?# 指定分隔符
df_pkl?= pd.read_pickle("data/df.pkl")
df_excel?= pd.read_excel("data/df.xlsx", index_col="id")
df_clipboard?= pd.read_clipboard(index_col="id")
df_from_dict?= pd.DataFrame(df_dict)
df_hdf?= pd.read_hdf("data/df.h5", key="df")
df_html?= pd.read_html("data/df.html", index_col=0)[0]
df_json?= pd.read_json("data/df.json")
df_feather?= pd.read_feather("data/df.feather")

print(df_csv)
print(df_tsv)
print(df_pkl)
print(df_excel)
print(df_clipboard)
print(df_from_dict)
print(df_hdf)
print(df_html)
print(df_json)
print(df_feather)

3.6 時間數據的處理

Timestamp 是?pandas 對?datetime64 數據類型的一個封裝。datetime64 是?NumPy 中的一種數據類型,用于表示日期和時間,而?pandas 基于?datetime64 構建了?Timestamp 類,以便更方便地在?pandas 的數據結構(如?DataFrame 和?Series)中處理日期時間數據。當?pd.to_datetime 接收單個日期時間值時,會返回?Timestamp 對象

1. 時間戳timestamp

Python
d = pd.Timestamp( "2015-05-01 09:08:07.123456" )
# 屬性
print('年:',d.year)
print('月:',d.month)
print('日:',d.day)
print('小時:',d.hour)
print('分鐘:',d.minute)
print('秒:',d.second)
print('微秒:',d.microsecond)
print('季度:',d.quarter)
print('是否是月底:',d.is_month_end)
print('是否是月初:',d.is_month_start)
print('是否是年底:',d.is_year_end)
print('是否是年初:',d.is_year_start)
# 方法
print('星期幾:',d.day_name())
print('轉換為年度:',d.to_period("Y"))
print('轉換為季度:',d.to_period("Q"))
print('轉換為月度:',d.to_period("M"))
print('轉換為季度:',d.to_period("Q"))
print('轉換為周維度:',d.to_period("W"))

to_period()獲取統計周期

freq:這是?to_period()?方法最重要的參數,用于指定要轉換的時間周期頻率

常見的取值如下:

  • "D":按天周期,例如?2024-01-01?會轉換為?2024-01-01?這個天的周期。
  • "W":按周周期,通常以周日作為一周的結束,比如日期落在某一周內,就會轉換為該周的周期表示。
  • "M":按月周期,像?2024-05-15?會轉換為?2024-05。
  • "Q":按季度周期,一年分為四個季度,日期會轉換到對應的季度周期,例如?2024Q2?。
  • "A"?或?"Y":按年周期,如?2024-07-20?會轉換為?2024?。

2. ?日期數據轉換

Bash
# 字符串字段轉換為日期類型
a = pd.to_datetime('2025-07-01')
a = pd.to_datetime('20250409')
a = pd.to_datetime('2025/04/13')
a = pd.to_datetime('2025-07')
print(a)
print(type(a))

# dateFrame中的日期轉換
df = pd.DataFrame({
'sales':[100,50,40],
'date':['2025-01-01','2023-03-02','2025-03-09']
})
df['datetime'] = pd.to_datetime(df['date'])
print(type(df['datetime'].dt))
df['datetime'].dt.day_name()

Bash
# 導入數據日期的處理
df???= ??pd??.??read_csv??(??"data/weather.csv"??)
print??(??df??[??"date"??].??tail??())
# 1456 ? ?2015-12-27
# 1457 ? ?2015-12-28
# 1458 ? ?2015-12-29
# 1459 ? ?2015-12-30
# 1460 ? ?2015-12-31
# Name: date, dtype: object
print??(??pd??.??to_datetime??(??df??[??"date"??]).??tail??())
# 1456 ? 2015-12-27
# 1457 ? 2015-12-28
# 1458 ? 2015-12-29
# 1459 ? 2015-12-30
# 1460 ? 2015-12-31
# Name: date, dtype: datetime64[ns]
# 在加載數據時也可以通過parse_dates參數將指定列解析為datetime64。
df???= ??pd??.??read_csv??(??"data/weather.csv"??, ??parse_dates??=[??0??])
print??(??df??[??"date"??].??tail??())

3. 將日期數據作為索引

將datetime64類型的數據設置為索引,得到的就是DatetimeIndex。

Bash
df?= pd.read_csv("data/weather.csv")
df["date"] = pd.to_datetime(df["date"]) ?# 將date列轉換為datetime64類型
df.set_index("date", inplace=True) ?# 將date列設置為索引,inplace=true直接修改原對象
df.info()
# <class 'pandas.core.frame.DataFrame'>
# DatetimeIndex: 1461 entries, 2012-01-01 to 2015-12-31

將時間作為索引后可以直接使用時間進行切片取值。

Plain Text
print(df.loc["2013-01":"2013-06"]) ?# 獲取2013年1~6月的數據
# ? ? ? ? ? ? precipitation ?temp_max ?temp_min ?wind weather
# date
# 2013-01-01 ? ? ? ? ? ?0.0 ? ? ? 5.0 ? ? ?-2.8 ? 2.7 ? ? sun
# 2013-01-02 ? ? ? ? ? ?0.0 ? ? ? 6.1 ? ? ?-1.1 ? 3.2 ? ? sun
# ... ? ? ? ? ? ? ? ? ? ... ? ? ? ... ? ? ? ... ? ... ? ? ...
# 2013-06-29 ? ? ? ? ? ?0.0 ? ? ?30.0 ? ? ?18.3 ? 1.7 ? ? sun
# 2013-06-30 ? ? ? ? ? ?0.0 ? ? ?33.9 ? ? ?17.2 ? 2.5 ? ? sun
print??(??df??.??loc??[??"2015"??]) ???# 獲取2015年所有數據
# ? ? ? ? ? ? precipitation ?temp_max ?temp_min ?wind weather
# date
# 2015-01-01 ? ? ? ? ? ?0.0 ? ? ? 5.6 ? ? ?-3.2 ? 1.2 ? ? sun
# 2015-01-02 ? ? ? ? ? ?1.5 ? ? ? 5.6 ? ? ? 0.0 ? 2.3 ? ?rain
# ... ? ? ? ? ? ? ? ? ? ... ? ? ? ... ? ? ? ... ? ... ? ? ...
# 2015-12-30 ? ? ? ? ? ?0.0 ? ? ? 5.6 ? ? ?-1.0 ? 3.4 ? ? sun
# 2015-12-31 ? ? ? ? ? ?0.0 ? ? ? 5.6 ? ? ?-2.1 ? 3.5 ? ? sun

也可以通過between_time()和at_time()獲取某些時刻的數據。

Plain Text
df.between_time("9:00", "11:00") ?# 獲取9:00到11:00之間的數據
df.at_time("3:33") ?# 獲取3:33的數據

4. 時間間隔timedelta

當用一個日期減去另一個日期,返回的結果是timedelta64類型。

Plain Text
d1 = pd.Timestamp( "2015-05-01 09:08:07.123456" )
d2 = pd.Timestamp( "2015-05-31 09:23:07.123456" )
print(d2-d1)
print(type(d1))
print(type(d2-d1))

TimedeltaIndex

將timedelta64類型的數據設置為索引,得到的就是TimedeltaIndex。

Plain Text
df?= pd.read_csv("data/weather.csv", parse_dates=[0])
df_date???= ??pd??.??to_datetime??(??df??[??"date"??])
df??[??"timedelta"??] = ??df_date?????-?????df_date??[??0??] ???# 得到timedelta64類型的數據
df??.??set_index??(??"timedelta"??, ??inplace??=??True??) ???# 將timedelta列設置為索引
df??.??info??()
# <class 'pandas.core.frame.DataFrame'>
# TimedeltaIndex: 1461 entries, 0 days to 1460 days

將時間作為索引后可以直接使用時間進行切片取值。

Plain Text
print(df.loc["0 days":"5 days"])
# ? ? ? ? ? ? ? ? date ?precipitation ?temp_max ?temp_min ?wind ?weather
# timedelta
# 0 days ? ?2012-01-01 ? ? ? ? ? ?0.0 ? ? ?12.8 ? ? ? 5.0 ? 4.7 ?drizzle
# 1 days ? ?2012-01-02 ? ? ? ? ? 10.9 ? ? ?10.6 ? ? ? 2.8 ? 4.5 ? ? rain
# 2 days ? ?2012-01-03 ? ? ? ? ? ?0.8 ? ? ?11.7 ? ? ? 7.2 ? 2.3 ? ? rain
# 3 days ? ?2012-01-04 ? ? ? ? ? 20.3 ? ? ?12.2 ? ? ? 5.6 ? 4.7 ? ? rain
# 4 days ? ?2012-01-05 ? ? ? ? ? ?1.3 ? ? ? 8.9 ? ? ? 2.8 ? 6.1 ? ? rain
# 5 days ? ?2012-01-06 ? ? ? ? ? ?2.5 ? ? ? 4.4 ? ? ? 2.2 ? 2.2 ? ? rain

5. 時間序列

生成時間序列

為了能更簡便地創建有規律的時間序列,pandas提供了date_range()方法。

date_range()通過開始日期、結束日期和頻率代碼(可選)創建一個有規律的日期序列,默認的頻率是天。

Python
print(pd.date_range("2015-07-03", "2015-07-10"))
# DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',
# ? ? ? ? ? ? ? ?'2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='D')

此外,日期范圍不一定非是開始時間與結束時間,也可以是開始時間與周期數periods。

Plain Text
print(pd.date_range("2015-07-03", periods=5))
# DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',
# ? ? ? ? ? ? ? ?'2015-07-07'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='D')

可以通過freq參數設置時間頻率,默認值是D。此處改為h,按小時變化的時間戳。

Plain Text
print(pd.date_range("2015-07-03", periods=5, freq="h"))
# DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00',
# ? ? ? ? ? ? ? ?'2015-07-03 02:00:00', '2015-07-03 03:00:00',
# ? ? ? ? ? ? ? ?'2015-07-03 04:00:00'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='h')

下表為常見時間頻率代碼與說明:

代碼

說明

D

天(calendar day,按日歷算,含雙休日)

B

天(business day,僅含工作日)

W

周(weekly)

ME / M

月末(month end)

BME

月末(business month end,僅含工作日)

MS

月初(month start)

BMS

月初(business month start,僅含工作日)

QE / Q

季末(quarter end)

BQE

季末(business quarter end,僅含工作日)

QS

季初(quarter start)

BQS

季初(business quarter start,僅含工作日)

YE / Y

年末(year end)

BYE

年末(business year end,僅含工作日)

YS

年初(year start)

BYS

年初(business year start,僅含工作日)

h

小時(hours)

bh

小時(business hours,工作時間)

min

分鐘(minutes)

s

秒(seconds)

ms

毫秒(milliseonds)

us

微秒(microseconds)

ns

納秒(nanoseconds)

偏移量

可以在頻率代碼后面加三位月份縮寫字母來改變季、年頻率的開始時間。

  • QE-JAN、BQE-FEB、QS-MAR、BQS-APR等
  • YE-JAN、BYE-FEB、YS-MAR、BYS-APR等

Shell
print??(??pd??.??date_range??(??"2015-07-03"??, ??periods??=??10??, ??freq??=??"QE-JAN"??)) ???# 設置1月為季度末
# DatetimeIndex(['2015-07-31', '2015-10-31', '2016-01-31', '2016-04-30',
# ? ? ? ? ? ? ? ?'2016-07-31', '2016-10-31', '2017-01-31', '2017-04-30',
# ? ? ? ? ? ? ? ?'2017-07-31', '2017-10-31'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='QE-JAN')

同理,也可以在后面加三位星期縮寫字母來改變一周的開始時間。

  • W-SUN、W-MON、W-TUE、W-WED等

Shell
print??(??pd??.??date_range??(??"2015-07-03"??, ??periods??=??10??, ??freq??=??"W-WED"??)) ???# 設置周三為一周的第一天
# DatetimeIndex(['2015-07-08', '2015-07-15', '2015-07-22', '2015-07-29',
# ? ? ? ? ? ? ? ?'2015-08-05', '2015-08-12', '2015-08-19', '2015-08-26',
# ? ? ? ? ? ? ? ?'2015-09-02', '2015-09-09'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='W-WED')

在這些代碼的基礎上,還可以將頻率組合起來創建的新的周期。例如,可以用小時(h)和分鐘(min)的組合來實現2小時30分鐘。

Shell
print??(??pd??.??date_range??(??"2015-07-03"??, ??periods??=??10??, ??freq??=??"2h30min"??))
# DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 02:30:00',
# ? ? ? ? ? ? ? ?'2015-07-03 05:00:00', '2015-07-03 07:30:00',
# ? ? ? ? ? ? ? ?'2015-07-03 10:00:00', '2015-07-03 12:30:00',
# ? ? ? ? ? ? ? ?'2015-07-03 15:00:00', '2015-07-03 17:30:00',
# ? ? ? ? ? ? ? ?'2015-07-03 20:00:00', '2015-07-03 22:30:00'],
# ? ? ? ? ? ? ? dtype='datetime64[ns]', freq='150min')

6. 重新采樣

處理時間序列數據時,經常需要按照新的頻率(更高頻率、更低頻率)對數據進行重新采樣。可以通過resample()方法解決這個問題。resample()方法以數據累計為基礎,會將數據按指定的時間周期進行分組,之后可以對其使用聚合函數。

Bash
df???= ??pd??.??read_csv??(??"data/weather.csv"??)
df??[??"date"??] = ??pd??.??to_datetime??(??df??[??"date"??])
df??.??set_index??(??"date"??, ??inplace??=??True??)
print??(??df??[[??"temp_max"??, ??"temp_min"??]].??resample??(??"YE"??).??mean??()) ???# 將數據按年分組,并計算每年的平均最高最低溫度
# ? ? ? ? ? ? ?temp_max ?temp_min
# date
# 2012-12-31 ?15.276776 ?7.289617
# 2013-12-31 ?16.058904 ?8.153973
# 2014-12-31 ?16.995890 ?8.662466
# 2015-12-31 ?17.427945 ?8.835616

3.7 數據分析與統計

分類

依賴關系

協同應用場景

示例

描述性統計

所有分析的基礎

初步了解數據分布,指導后續分組策略

df.describe()?發現某列標準差大?→ 觸發分組過濾

分組聚合

基于描述性統計或分組過濾結果

按維度拆分后計算指標(如各品類銷售額總和)

df.groupby('category')['sales'].sum()

分組轉換

依賴分組聚合結構

在保留原始行數的前提下,添加組內計算列(如標準化、排名)

df.groupby('group')['value'].transform(lambda x: x/x.max())

分組過濾

依賴描述性統計或分組聚合結果

根據組級條件篩選數據(如剔除樣本量不足的組)

df.groupby('group').filter(lambda x: len(x) > 5)

相關性分析

可結合分組聚合結果

分析不同分組下變量的關聯性(如各地區的價格-銷量相關性)

df.groupby('region')[['price','sales']].corr()

關鍵交互邏輯

  1. 從宏觀到微觀??
  • 描述性統計(宏觀)?→ 分組聚合(細分維度)?→ 分組轉換/過濾(微觀調整)

  1. 數據流閉環??

Python
# 示例:分析高波動品類(閉環流程)
grouped = df.groupby('category')
# 1. 描述性統計?→ 2. 分組過濾?→ 3. 分組轉換
result = (grouped.filter(lambda x: x['price'].std() > 2)
.groupby('category')['price']
.transform(lambda x: (x - x.mean())/x.std()))

  1. 功能互補性??
  • 聚合?vs 轉換:聚合減少行數,轉換保持行數。??
  • 過濾?vs 轉*:過濾刪除整組,轉換修改組內值。

可視化應用場景

通過以上關系圖和表格,可清晰理解如何組合這些方法解決實際問題,例如:??

  1. 數據清洗:描述統計?→ 發現異常?→ 分組過濾??
  1. 特征工程:分組聚合?→ 分組轉換(如生成占比特征)??
  1. 業務分析:分組聚合?→ 相關性分析(如用戶分群行為關聯)

1. 常用聚合函數

方法

說明

sum()

求和

mean()

平均值

min()

最小值

max()

最大值

var()

方差

std()

標準差

median()

中位數

quantile()

指定位置的分位數,如quantile(0.5)

describe()

常見統計信息

size()

所有元素的個數

count()

非空元素的個數

first

第一行

last

最后一行

nth

第n行

2. 分組聚合

df.groupby("分組字段")["要聚合的字段"].聚合函數()

df.groupby(["分組字段", "分組字段2", ...])[["要聚合的字段", "要聚合的字段2", ...]].聚合函數()

DataFrameGroupBy對象

對DataFrame對象調用groupby()方法后,會返回DataFrameGroupBy對象。

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據
print(df.groupby("department_id")) ?# 按department_id分組,返回DataFrameGroupBy對象
# <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000024FCBAFD700>

這個對象可以看成是一種特殊形式的?DataFrame,里面隱藏著若干組數據,但是在沒有應用累計函數之前不會計算。GroupBy對象是一種非常靈活的抽象類型。在大多數場景中,可以將它看成是DataFrame的集合。

查看分組

通過groups屬性查看分組結果,返回一個字典,字典的鍵是分組的標簽,值是屬于該組的所有索引的列表。

Python
print(df.groupby("department_id").groups) ?# 查看分組結果
# {10.0: [100], 20.0: [101, 102], 30.0: [14, 15, 16, 17, 18, 19]...

通過get_group()方法獲取分組。

Python
print(df.groupby("department_id").get_group(50)) ?# 獲取分組為50的數據
# ? ? employee_id first_name ? ?last_name ? ? email...
# 20 ? ? ? ? ?120 ? ?Matthew ? ? ? ?Weiss ? ?MWEISS...
# 21 ? ? ? ? ?121 ? ? ? Adam ? ? ? ?Fripp ? ?AFRIPP...
# 22 ? ? ? ? ?122 ? ? ?Payam ? ? Kaufling ?PKAUFLIN...

按列取值

Python
print(df.groupby("department_id")["salary"]) ?# 按department_id分組,取salary列
# <pandas.core.groupby.generic.SeriesGroupBy object at 0x0000022456D6F2F0>

這里從原來的DataFrame中取某個列名作為一個Series組。與GroupBy對象一樣,直到我們運行累計函數,才會開始計算。

Python
print(df.groupby("department_id")["salary"].mean()) ?# 計算每個部門平均薪資
# department_id
# 10.0 ? ? ?4400.000000
# 20.0 ? ? ?9500.000000
# 30.0 ? ? ?4150.000000

按組迭代

GroupBy對象支持直接按組進行迭代,返回的每一組都是Series或DataFrame。

Python
for?dept_id,group?in?df.groupby("department_id"):
print(f"當前組為{dept_id},組里的數據情況{group.shape}:")
print(group.iloc[:,0:3])
print("-------------------")
# 當前組為10.0,組里的數據情況(1, 10):
# ? ? ?employee_id first_name last_name
# 100 ? ? ? ? ?200 ? Jennifer ? ?Whalen
# -------------------
# 當前組為20.0,組里的數據情況(2, 10):
# ? ? ?employee_id first_name ?last_name
# 101 ? ? ? ? ?201 ? ?Michael ?Hartstein
# 102 ? ? ? ? ?202 ? ? ? ?Pat ? ? ? ?Fay

...

按多字段分組

Python
salary_mean?= df.groupby(["department_id", "job_id"])[
["salary", "commission_pct"]
].mean() ?# 按department_id和job_id分組
print(salary_mean.index) ?# 查看分組后的索引
# MultiIndex([( 10.0, ? ?'AD_ASST'),
# ? ? ? ? ? ? ( 20.0, ? ? 'MK_MAN'),
# ? ? ? ? ? ? ( 20.0, ? ? 'MK_REP'),
# ? ? ? ? ? ? ( 30.0, ? 'PU_CLERK'),
# ? ? ? ? ? ? ( 30.0, ? ? 'PU_MAN'),
# ? ? ? ? ? ? ...
print(salary_mean.columns) ?# 查看分組后的列
# Index(['salary', 'commission_pct'], dtype='object')

按多個字段分組后得到的索引為復合索引。

可通過reset_index()方法重置索引。

Python
print(salary_mean.reset_index())
# ? ? department_id ? ? ?job_id ? ? ? ?salary ?commission_pct
# 0 ? ? ? ? ? ?10.0 ? ? AD_ASST ? 4400.000000 ? ? ? ? ? ? NaN
# 1 ? ? ? ? ? ?20.0 ? ? ?MK_MAN ?13000.000000 ? ? ? ? ? ? NaN
# 2 ? ? ? ? ? ?20.0 ? ? ?MK_REP ? 6000.000000 ? ? ? ? ? ? NaN
# 3 ? ? ? ? ? ?30.0 ? ?PU_CLERK ? 2780.000000 ? ? ? ? ? ? NaN
# 4 ? ? ? ? ? ?30.0 ? ? ?PU_MAN ?11000.000000 ? ? ? ? ? ? NaN

也可以在分組的時候通過as_index = False參數(默認是True)重置索引。

Python
salary_mean?= df.groupby(["department_id", "job_id"], as_index=False)[
["salary", "commission_pct"]
].mean() ?# 按department_id和job_id分組
print(salary_mean)
# ? ? department_id ? ? ?job_id ? ? ? ?salary ?commission_pct
# 0 ? ? ? ? ? ?10.0 ? ? AD_ASST ? 4400.000000 ? ? ? ? ? ? NaN
# 1 ? ? ? ? ? ?20.0 ? ? ?MK_MAN ?13000.000000 ? ? ? ? ? ? NaN
# 2 ? ? ? ? ? ?20.0 ? ? ?MK_REP ? 6000.000000 ? ? ? ? ? ? NaN
# 3 ? ? ? ? ? ?30.0 ? ?PU_CLERK ? 2780.000000 ? ? ? ? ? ? NaN
# 4 ? ? ? ? ? ?30.0 ? ? ?PU_MAN ?11000.000000 ? ? ? ? ? ? NaN

將數據按月分組,并統計最大溫度和最小溫度的平均值

Python
df["month"] = pd.to_datetime(df["date"]).dt.to_period("M").astype(str) ?# 將date轉換為?年-月?的格式

df_groupby_date?= df.groupby("month") ?# 按month分組,返回一個分組對象(DataFrameGroupBy)
month_temp?= df_groupby_date[["temp_max", "temp_min"]] ?# 從分組對象中選擇特定的列
month_temp_mean?= month_temp.mean() ?# 對每個列求平均值

# 以上代碼可以寫在一起
month_temp_mean?= df.groupby("month")[["temp_max", "temp_min"]].mean()
# ? ? ? ? ? temp_max ? temp_min
# month
# 2012-01 ? 7.054839 ? 1.541935
# 2012-02 ? 9.275862 ? 3.203448
# 2012-03 ? 9.554839 ? 2.838710
# 2012-04 ?14.873333 ? 5.993333
# 2012-05 ?17.661290 ? 8.190323

分組后默認會將分組字段作為行索引。如果分組字段有多個,得到的是復合索引。

分組頻數計算

統計每個月不同天氣狀況的數量。

Python
df.groupby("month")["weather"].nunique()
# date
# 2012-01 ? ?4
# 2012-02 ? ?4
# 2012-03 ? ?4
# 2012-04 ? ?4
# 2012-05 ? ?3

3. 一次計算多個統計值

可以通過agg()或aggregate()進行更復雜的操作,如一次計算多個統計值。

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據
# 按department_id分組,計算salary的最小值,中位數,最大值
print(df.groupby("department_id")["salary"].agg(["min", "median", "max"]))
# ? ? ? ? ? ? ? ? ? ?min ? median ? ? ?max
# department_id
# 10.0 ? ? ? ? ? ?4400.0 ? 4400.0 ? 4400.0
# 20.0 ? ? ? ? ? ?6000.0 ? 9500.0 ?13000.0
# 30.0 ? ? ? ? ? ?2500.0 ? 2850.0 ?11000.0
# 40.0 ? ? ? ? ? ?6500.0 ? 6500.0 ? 6500.0
# 50.0 ? ? ? ? ? ?2100.0 ? 3100.0 ? 8200.0

多個列計算不同的統計值

也可以在agg()中傳入字典,對多個列計算不同的統計值。

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據
# 按department_id分組,統計job_id的種類數,commission_pct的平均值
print(df.groupby("department_id").agg({"job_id": "nunique", "commission_pct": "mean"}))
# ? ? ? ? ? ? ? ?job_id ?commission_pct
# department_id
# 10.0 ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? NaN
# 20.0 ? ? ? ? ? ? ? ?2 ? ? ? ? ? ? NaN
# 30.0 ? ? ? ? ? ? ? ?2 ? ? ? ? ? ? NaN
# 40.0 ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? NaN
# 50.0 ? ? ? ? ? ? ? ?3 ? ? ? ? ? ? NaN

重命名統計值

可以在agg()后通過rename()對統計后的列重命名。

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據
# 按department_id分組,統計job_id的種類數,commission_pct的平均值
print(
df.groupby("department_id")
.agg(
{"job_id": "nunique", "commission_pct": "mean"},
)
.rename(
columns={"job_id": "工種數", "commission_pct": "傭金比例平均值"},
)
)
# ? ? ? ? ? ? ? ?工種數??傭金比例平均值
# department_id
# 10.0 ? ? ? ? ? ? 1 ? ? ?NaN
# 20.0 ? ? ? ? ? ? 2 ? ? ?NaN
# 30.0 ? ? ? ? ? ? 2 ? ? ?NaN
# 40.0 ? ? ? ? ? ? 1 ? ? ?NaN
# 50.0 ? ? ? ? ? ? 3 ? ? ?NaN

自定義函數

可以向agg()中傳入自定義函數進行計算。

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據

def?f(x):
"""統計每個部門員工last_name的首字母"""
result?= set()
for?i?in?x:
result.add(i[0])
return?result

print(df.groupby("department_id")["last_name"].agg(f))
# department_id
# 10.0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {W}
# 20.0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{F, H}
# 30.0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{B, T, R, C, K, H}
# 40.0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {M}
# 50.0 ? ? {O, E, K, S, W, L, P, D, C, V, B, T, M, J, F, ...

4. 分組轉換

聚合操作返回的是對組內全量數據縮減過的結果,而轉換操作會返回一個新的全量數據。數據經過轉換之后,其形狀與原來的輸入數據是一樣的。

通過transform()將每一組的樣本數據減去各組的均值,實現數據標準化

df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據

print(df.groupby("department_id")["salary"].transform(lambda?x: x?- x.mean()))

通過transform()按分組使用平均值填充缺失值

Python
df?= pd.read_csv("data/employees.csv") ?# 讀取員工數據
na_index?= pd.Series(df.index.tolist()).sample(30) ?# 隨機挑選30條數據
df.loc[na_index, "salary"] = pd.NA??# 將這30條數據的salary設置為缺失值
print(df.groupby("department_id")["salary"].agg(["size", "count"])) ?# 查看每組數據總數與非空數據數

def?fill_missing(x):
# 使用平均值填充,如果平均值也為NaN,用0填充
if?np.isnan(x.mean()):
return?0
return?x.fillna(x.mean())

df["salary"] = df.groupby("department_id")["salary"].transform(fill_missing)
print(df.groupby("department_id")["salary"].agg(["size", "count"])) ?# 查看每組數據總數與非空數據數

5. 分組過濾

過濾操作可以讓我們按照分組的屬性丟棄若干數據。

例如,我們可能只需要保留commission_pct不包含空值的分組的數據。

Python
commission_pct_filter?= df.groupby("department_id").filter(? ?
lambda?x: x["commission_pct"].notnull().all()
) ?# 按department_id分組,過濾掉commission_pct包含空值的分組
print(commission_pct_filter)

3.8 案例講解

Python
# 導入必要的庫
import pandas as pd
import numpy as np
# 1. 數據加載與初步探索
# 讀取企鵝數據集,注意解析日期列(雖然這個數據集沒有日期列,但展示parse_dates參數的用法)
penguins = pd.read_csv('data/penguins.csv')
print("數據集前5行:")
display(penguins.head())
print("\n數據集信息:")
display(penguins.info())
# 2. 數據清洗
# 檢查缺失值
print("\n每列的缺失值數量:")
print(penguins.isnull().sum())
# 處理缺失值?- 刪除含有缺失值的行
penguins_clean = penguins.dropna()
print("\n清洗后數據集形狀:", penguins_clean.shape)
# 3. 數據轉換與特征工程
# 將性別列轉換為類別類型
penguins_clean['sex'] = penguins_clean['sex'].astype('category')
print("\n性別列數據類型:", penguins_clean['sex'].dtype)
# 創建新特征:喙長與喙深的比值
penguins_clean['bill_ratio'] = penguins_clean['bill_length_mm'] / penguins_clean['bill_depth_mm']
# 4. 數據分析
# 按物種分組計算平均特征值
species_stats = penguins_clean.groupby('species').agg({
'bill_length_mm': 'mean',
'bill_depth_mm': 'mean',
'flipper_length_mm': 'mean',
'body_mass_g': 'mean',
'bill_ratio': 'mean'
}).round(2)

print("\n不同物種的平均特征值:")
display(species_stats)

# 5. 數據分箱?- 將體重分為低、中、高三個等級
labels = ['低', '中', '高']
penguins_clean['mass_category'] = pd.cut(penguins_clean['body_mass_g'], bins=3, labels=labels)

print("\n體重分箱結果:")
display(penguins_clean['mass_category'].value_counts())

# 6. 按島嶼和性別分組分析
island_sex_stats = penguins_clean.groupby(['sex']).agg({
'body_mass_g': ['mean', 'count']
})
print("\n按性別分組的統計數據:")
print(island_sex_stats)

Python
# 導入必要的庫
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns# 設置可視化風格
plt.style.use('seaborn')
sns.set_palette("husl")# 1. 數據加載與初步探索
# 讀取睡眠數據集
sleep_data = pd.read_csv('sleep.csv')# 顯示前5行數據
print("數據集前5行:")
print(sleep_data.head())# 顯示數據集基本信息
print("\n數據集信息:")
print(sleep_data.info())# 2. 數據清洗與預處理
# 檢查缺失值
print("\n每列的缺失值數量:")
print(sleep_data.isnull().sum())# 如果有缺失值,可以刪除或填充
# 這里假設數據已經完整,直接復制
sleep_clean = sleep_data.copy()# 3. 數據轉換與特征工程
# 將性別列轉換為類別類型
sleep_clean['gender'] = sleep_clean['gender'].astype('category')# 分離血壓為收縮壓和舒張壓
sleep_clean[['systolic_bp', 'diastolic_bp']] = sleep_clean['blood_pressure'].str.split('/', expand=True).astype(int)# 創建睡眠質量分類列
bins = [0, 4, 7, 10]
labels = ['差', '中', '優']
sleep_clean['sleep_quality_category'] = pd.cut(sleep_clean['sleep_quality'], bins=bins, labels=labels)# 創建年齡分段列
age_bins = [0, 30, 45, 60, 100]
age_labels = ['18-30', '31-45', '46-60', '60+']
sleep_clean['age_group'] = pd.cut(sleep_clean['age'], bins=age_bins, labels=age_labels)# 4. 基本統計分析
# 描述性統計
print("\n數值變量的描述性統計:")
print(sleep_clean.describe())# 分類變量統計
print("\n分類變量統計:")
print(sleep_clean['gender'].value_counts())
print("\nBMI類別分布:")
print(sleep_clean['bmi_category'].value_counts())
print("\n睡眠障礙分布:")
print(sleep_clean['sleep_disorder'].value_counts())# 5. 睡眠質量分析
# 按性別分析平均睡眠時間和質量
gender_stats = sleep_clean.groupby('gender').agg({'sleep_duration': 'mean','sleep_quality': 'mean','stress_level': 'mean'
}).round(2)
print("\n按性別分組的睡眠統計:")
print(gender_stats)# 按BMI類別分析
bmi_stats = sleep_clean.groupby('bmi_category').agg({'sleep_duration': 'mean','sleep_quality': 'mean','physical_activity_level': 'mean'
}).round(2)
print("\n按BMI類別分組的睡眠統計:")
print(bmi_stats)# 6. 睡眠障礙分析
# 有睡眠障礙和無睡眠障礙的比較
disorder_stats = sleep_clean.groupby('sleep_disorder').agg({'sleep_duration': ['mean', 'count'],'sleep_quality': 'mean','age': 'mean','stress_level': 'mean'
}).round(2)
print("\n按睡眠障礙分組的統計:")
print(disorder_stats)# 7. 相關性分析
# 計算數值變量之間的相關性
correlation = sleep_clean[['sleep_duration', 'sleep_quality', 'age', 'physical_activity_level','stress_level', 'heart_rate', 'daily_steps', 'systolic_bp', 'diastolic_bp']].corr()print("\n變量間相關性矩陣:")
print(correlation)# 8. 高級分析?- 多因素分組
# 按性別和年齡組分析
gender_age_stats = sleep_clean.groupby(['gender', 'age_group']).agg({'sleep_duration': 'mean','sleep_quality': 'mean','stress_level': 'mean'
}).round(2)
print("\n按性別和年齡組分組的統計:")
print(gender_age_stats)# 按職業和BMI類別分析
occupation_bmi_stats = sleep_clean.groupby(['occupation', 'bmi_category']).agg({'sleep_duration': 'mean','sleep_quality': 'mean'
}).round(2)
print("\n按職業和BMI類別分組的統計:")
print(occupation_bmi_stats)# 9. 數據可視化
# 設置圖形大小
plt.figure(figsize=(15, 10))# 睡眠質量分布
plt.subplot(2, 2, 1)
sns.histplot(sleep_clean['sleep_quality'], bins=10, kde=True)
plt.title('睡眠質量分布')
plt.xlabel('睡眠質量評分')
plt.ylabel('人數')# 睡眠持續時間分布
plt.subplot(2, 2, 2)
sns.histplot(sleep_clean['sleep_duration'], bins=10, kde=True)
plt.title('睡眠持續時間分布')
plt.xlabel('睡眠時間(小時)')
plt.ylabel('人數')# 睡眠質量與壓力水平的關系
plt.subplot(2, 2, 3)
sns.scatterplot(x='stress_level', y='sleep_quality', hue='gender', data=sleep_clean)
plt.title('睡眠質量與壓力水平的關系')
plt.xlabel('壓力水平')
plt.ylabel('睡眠質量')# 不同BMI類別的平均睡眠質量
plt.subplot(2, 2, 4)
sns.barplot(x='bmi_category', y='sleep_quality', data=sleep_clean, ci=None)
plt.title('不同BMI類別的平均睡眠質量')
plt.xlabel('BMI類別')
plt.ylabel('平均睡眠質量')plt.tight_layout()
plt.show()# 10. 更多可視化
plt.figure(figsize=(15, 5))# 按年齡組的睡眠質量
plt.subplot(1, 2, 1)
sns.boxplot(x='age_group', y='sleep_quality', hue='gender', data=sleep_clean)
plt.title('不同年齡組的睡眠質量')
plt.xlabel('年齡組')
plt.ylabel('睡眠質量')# 睡眠障礙與睡眠質量的關系
plt.subplot(1, 2, 2)
sns.boxplot(x='sleep_disorder', y='sleep_quality', data=sleep_clean)
plt.title('睡眠障礙與睡眠質量的關系')
plt.xlabel('睡眠障礙類型')
plt.ylabel('睡眠質量')plt.tight_layout()
plt.show()# 11. 保存處理后的數據
sleep_clean.to_csv('cleaned_sleep_data.csv', index=False)
print("\n處理后的數據已保存為?cleaned_sleep_data.csv")

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919159.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919159.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919159.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入探索Go語言標準庫 net 包中的 IP 處理

深入探索Go語言標準庫 net 包中的 IP 處理 文章目錄深入探索Go語言標準庫 net 包中的 IP 處理引言核心知識type IP常用函數常用方法代碼示例常見問題1. DNS 查詢失敗怎么辦&#xff1f;2. 如何區分 IPv4 和 IPv6 地址&#xff1f;使用場景1. 服務器端編程2. 網絡監控和調試3. 防…

2.4 雙向鏈表

目錄 引入 結構定義 結構操作 初始化 插入 刪除 打印 查找 隨機位置插入 隨機位置刪除 銷毀 總結 數據結構專欄https://blog.csdn.net/xyl6716/category_13002640.html 精益求精 追求卓越 【代碼倉庫】&#xff1a;Code Is Here 【合作】 &#xff1a;apollomona…

開發指南132-DOM的寬度、高度屬性

寬度、高度類似。這里以高度為例來說明DOM中有關高度的概念&#xff1a;1、height取法&#xff1a;element.style.height說明&#xff1a;元素內容區域的高度&#xff0c;不含padding、border、margin該屬性可寫2、clientHeight取法&#xff1a;element..clientHeight&#xff…

魔改chromium源碼——解除 iframe 的同源策略

在進行以下操作之前,請確保已完成之前文章中提到的 源碼拉取及編譯 部分。 如果已順利完成相關配置,即可繼續執行后續操作。 同源策略限制了不同源(協議、域名、端口)的網頁腳本訪問彼此的資源。iframe 的跨域限制由 Blink 渲染引擎和 Chromium 的安全層共同實現。 咱們直…

在鴻蒙中實現深色/淺色模式切換:從原理到可運行 Demo

摘要 現在幾乎所有主流應用都支持“深色模式”和“淺色模式”切換&#xff0c;這已經成了用戶習慣。鴻蒙&#xff08;HarmonyOS&#xff09;同樣提供了兩種模式&#xff08;dark / light&#xff09;&#xff0c;并且支持應用根據系統主題切換&#xff0c;或者應用內手動切換。…

Redux搭檔Next.js的簡明使用教程

Redux 是一個用于 JavaScript 應用的狀態管理庫&#xff0c;主要解決組件間共享狀態和復雜狀態邏輯的問題。當應用規模較大、組件層級較深或多個組件需要共享/修改同一狀態時&#xff0c;Redux 可以提供可預測、可追蹤的狀態管理方式&#xff0c;避免狀態在組件間混亂傳遞。Red…

SCAI采用公平發射機制成功登陸LetsBonk,60%代幣供應量已鎖倉

去中心化科學&#xff08;DeSci&#xff09;平臺SCAI宣布&#xff0c;其代幣已于今日以Fair Launch形式在LetsBonk.fun平臺成功發射。為保障資金安全與透明&#xff0c;開發團隊已將代幣總量的60%進行鎖倉&#xff0c;進一步提升社區信任與項目合規性。SCAI是一個專注于高質量科…

【Kubernetes系列】Kubernetes中的resources

博客目錄1. limits&#xff08;資源上限&#xff09;2. requests&#xff08;資源請求&#xff09;關鍵區別其他注意事項示例場景在 Kubernetes (k8s) 中&#xff0c;resources 用于定義容器的資源請求&#xff08;requests&#xff09;和限制&#xff08;limits&#xff09;&a…

hadoop 前端yarn 8088端口查看任務執行情況

圖中資源相關參數含義及簡單分析思路&#xff1a; 基礎資源搶占參數 Total Resource Preempted: <memory:62112, vCores:6> 含義&#xff1a;應用總共被搶占的資源量&#xff0c; memory:62112 表示累計被收回的內存&#xff08;單位通常是MB &#xff0c;結合Hadoop生態…

基于SpringBoot的個性化教育學習平臺的設計與實現(源碼+lw+部署文檔+講解等)

課題介紹在教育數字化轉型與學習者需求差異化的背景下&#xff0c;傳統學習平臺 “統一內容、統一進度” 的模式已顯局限。當前&#xff0c;平臺多提供標準化課程資源&#xff0c;無法根據學習者年齡、基礎、目標&#xff08;如升學、技能提升&#xff09;定制學習路徑&#xf…

UE5多人MOBA+GAS 48、制作閃現技能

文章目錄添加標簽添加GA_Blink添加標簽 CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Blink_Teleport)CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Blink_Cooldown)UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Blink_Teleport, "Ability.Blink.Teleport"…

Swift 實戰:實現一個簡化版的 Twitter(LeetCode 355)

文章目錄摘要描述示例解決答案設計思路題解代碼分析測試示例和結果時間復雜度空間復雜度總結摘要 在社交媒體平臺里&#xff0c;推送機制是核心功能之一。比如你關注了某人&#xff0c;就希望在自己的時間線上能看到他們的最新消息&#xff0c;同時自己的消息也要能出現在別人…

在瀏覽器端使用 xml2js 遇到的報錯及解決方法

在瀏覽器端使用 xml2js 遇到的報錯及解決方法 一、引言 在前端開發過程中&#xff0c;我們常常需要處理 XML 數據。xml2js 是一個非常流行的用于將 XML 轉換為 JavaScript 對象的庫。然而&#xff0c;當我們在瀏覽器端使用它時&#xff0c;可能會遇到一些問題。本文將介紹在瀏覽…

eChart餅環pie中間顯示總數_2個以上0值不擠掉

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>環餅圖顯示總數</title><script src"https://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js"></script><style>#main { widt…

Ansible 核心功能進階:自動化任務的靈活控制與管理

一、管理 FACTS&#xff1a;獲取遠程主機的 “身份信息”FACTS 是 Ansible 自動收集的遠程主機詳細信息&#xff08;類似 “主機身份證”&#xff09;&#xff0c;包括主機名、IP、系統版本、硬件配置等。通過 FACTS 可以動態獲取主機信息&#xff0c;讓 Playbook 更靈活1. 查看…

gRPC網絡模型詳解

gRPC協議框架 TCP層&#xff1a;底層通信協議&#xff0c;基于TCP連接。 TLS層&#xff1a;該層是可選的&#xff0c;基于TLS加密通道。 HTTP2層&#xff1a;gRPC承載在HTTP2協議上&#xff0c;利用了HTTP2的雙向流、流控、頭部壓縮、單連接上的多 路復用請求等特性。 gRPC層…

[優選算法專題二滑動窗口——將x減到0的最小操作數]

題目鏈接 將x減到0的最小操作數 題目描述 題目解析 問題重述 給定一個整數數組 nums 和一個整數 x&#xff0c;每次只能從數組的左端或右端移除一個元素&#xff0c;并將該元素的值從 x 中減去。我們需要找到將 x 恰好減為 0 的最少操作次數&#xff0c;如果不可能則返回 -…

AOP配置類自動注入

本文主要探究AopAutoConfiguration配置類里面的bean怎么被自動裝配的。代碼如下&#xff1a;package com.example.springdemo.demos.a05;import com.example.springdemo.demos.a04.Bean1; import com.example.springdemo.demos.a04.Bean2; import com.example.springdemo.demos…

云計算-K8s 實戰:Pod、安全上下文、HPA 、CRD、網絡策略、親和性等功能配置實操指南

簡介 此次圍繞Kubernetes 日常管理中的核心場景,提供了從基礎到進階的實操配置指南。內容涵蓋 9 大關鍵知識點:從使用 nginx 鏡像創建 QoS 類為 Guaranteed 的 Pod,到為 Pod 配置安全上下文以指定運行用戶和組;從自定義 Student 資源類型(CRD),到配置 Sidecar 實現跨命…

嵌入式LINUX——————TCP并發服務器

一、服務器1.服務器分類單循環服務器&#xff1a;只能處理一個客戶端任務的服務器 并發服務器&#xff1a;可同時處理多個客戶端任務的服務器二、TCP并發服務器的構建1.如何構建&#xff1f; &#xff08;1&#xff09;多進程&#xff08;每一次創建都非常耗時耗空間&#…