一、基础
1.概述
“pandas”是“Panel Data”(面板数据)的缩写,也与“Python Data Analysis”(python数据分析)相关。
基于 NumPy 构建,专注于灵活高效的数据结构,填补NumPy在表格和复杂数据处理中的不足。
主要用途:数据清洗与整理、数据分析与计算、时间序列处理、数据输入/输出、可视化集成、机器学习的预处理等等
优势:高灵活性、高性能、高兼容性、API统一
局限:内存限制(大数据集处理)、性能瓶颈(非向量操作)
2.安装
打开Anaconda Prompt,切换到需要安装地虚拟环境输入以下指令
pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/
3.内置数据结构
- Series:一维带标签数组,类似增强版字典或Excel列,支持异构数据类型。
- DataFrame:二维表格结构(行列索引),类似SQL表或Excel工作表,是pandas的核心对象
4.Series
Series是一维带标签的数组,能够保存任何数据类型(整数、字符串、浮点数、Python对象等)。类似增强版的字典,索引(keys)与值的对应,但支持向量化操作。
Series = 数据值(Values) + 索引(Index)
- Values:存储数据的NumPy数组(可通过
.values
访问)- Index:数据的标签(可通过
.index
访问),默认从0开始,但可自定义(如字符串、时间等)
4.1创建Series对象
使用Panda中的Series(data,index,dtype,copy )方法
- data:一组数据(ndarray 类型)
- index:数据索引标签,如果不指定,默认从 0 开始
- dtype:数据类型,默认会自己判断
- copy:表示对 data 进行拷贝,默认为 False
创建空Series对象
import pandas as pd
#输出数据为空
s = pd.Series()
print(s)
从列表创建(默认索引)
import pandas as pd
# 示例:学生成绩列表
scores = [85, 90, 78, 92, 88]
s = pd.Series(scores, name="MathScore") # 推荐指定name参数便于后续识别
print(s)
0 85
1 90
2 78
3 92
4 88
Name: MathScore, dtype: int64
从字典创建(自定义索引)
# 示例:城市温度字典
temps = {"北京": 22.5, "上海": 25.3, "广州": 28.1, "深圳": 26.8}
s_temps = pd.Series(temps)
print(s_temps)
北京 22.5
上海 25.3
广州 28.1
深圳 26.8
dtype: float64
从标量值创建(需要指定索引)
# 示例:统一初始值
s_default = pd.Series(0, index=["a", "b", "c", "d"])
print(s_default)
a 0
b 0
c 0
d 0
dtype: int64
从Numpy数组创建(保留数据类型特性)
import numpy as np
arr = np.array([10, 20, 30], dtype=np.float32)
s_np = pd.Series(arr, index=["X", "Y", "Z"])
print(s_np)
X 10.0
Y 20.0
Z 30.0
dtype: float32
4.2访问Series数据
位置索引访问:这种访问方式与 ndarray 和 list 相同,使用元素自身的下标进行访问。
import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
print(s[0]) #输出为1
索引标签访问:Series 类似于固定大小的 dict,把 index 中的索引标签当做 key,而把 Series 序列中的元素值当做 value,然后通过 index 索引标签来访问或者修改元素值。
import pandas as pd
s = pd.Series([6,7,8,9,10],index = ['a','b','c','d','e'])
print(s['a'])#输出为 6
4.3遍历Series数据
直接遍历值(最快但不推荐显式循环)
s = pd.Series([10, 20, 30], index=["A", "B", "C"])
for val in s.values:
print(val * 2) # 输出: 20, 40, 60
遍历索引和值(使用items()
或迭代器
# 使用items()
s = pd.Series({"X": 100, "Y": 200, "Z": 300})
for idx, val in s.items():
print(f"索引 {idx} 的值是 {val}")
用for
循环隐式遍历索引(低效但明确)
for idx in s.index:
print(s[idx]) # 输出对应索引的值
通过位置遍历(.iloc
或range
)
for i in range(len(s)):
value = s.iloc[i] # 或 s[i](当索引是数字时)
利用apply()
或map()
向量化替代遍历
# 使用apply替代逐元素计算平方根
s = pd.Series([4, 9, 16])
squared = s.apply(lambda x: x ** 0.5)
print(squared) # 输出: 2.0, 3.0, 4.0
# 使用map替换值
replace_dict = {4: "A", 9: "B"}
replaced = s.map(replace_dict)
print(replaced) # 输出: A, B, NaN
4.4Series常用属性和方法
isnull() 和 notnull() 用于检测 Series、DataFrame 中的缺失值(如NaN
、None
、NaT
等)。所谓缺失值,顾名思义就是值不存在、丢失、缺少
-
isnull():如果为值不存在或者缺失,则返回 True
-
notnull():如果值不存在或者缺失,则返回 False
import pandas as pd
import numpy as np
s = pd.Series([1, np.nan, "Hello", None, pd.NaT]) # 包含多种缺失类型
result = s.isnull()
print(result)
0 False
1 True
2 False
3 True
4 True
dtype: bool
补充:
s = pd.Series([10, 20, 30], index=["A", "B", "C"], name="Example")
属性 | 说明 | 示例 |
---|---|---|
s.values | 获取值的NumPy数组 | array([10,20,30]) |
s.index | 获取索引对象 | Index(['A','B','C']) |
s.dtype | 数据类型(自动推断或指定) | int64 |
s.name | Series的名称 | 'Example' |
s.size | 元素数量 | 3 |
方法 | 作用 | 示例 |
---|---|---|
s.head(n) | 显示前n行(默认5) | s.head(2) → 显示前2项 |
s.tail(n) | 显示后n行 | s.tail(1) → 显示最后1项 |
s.describe() | 统计摘要(计数、均值、标准差等) | 输出统计概况 |
s.isna() | 检测缺失值(返回布尔Series) | 用于缺失值定位 |
s.fillna(value) | 填充缺失值 | 常用0或均值填充 |
s.unique() | 返回唯一值数组 | 去重操作基础 |
s.value_counts() | 统计各值出现次数 | 分析数据分布 |
5.DataFrame
DataFrame是二维带标签的表格型数据结构,类似于Excel工作表或SQL表:
- 行(Index):行标签(默认0开始,可自定义为时间、字符串等)。
- 列(Columns):列标签(字段名),不同列可存储不同数据类型。
底层由多个Series(列)构成,共享相同的行索引。
DataFrame = 行索引(Index) + 列索引(Columns) + 数据块(二维数组)
- 本质:由多个Series组成的字典(键为列名,值为Series)。
5.1创建DataFrame
pd.DataFrame( data, index, columns, dtype, copy)
- data:一组数据(ndarray、series, map, lists, dict 等类型)
- index:索引值,或者可以称为行标签
- columns:列标签,默认为 RangeIndex (0, 1, 2, …, n)
- dtype:数据类型
- copy:默认为 False,表示复制数据 data
创建空对象
import pandas as pd
result = pd.DataFrame()
print(result)
Empty DataFrame
Columns: []
Index: []
从字典(键为列名,值为列表/Series)
data = {
"Name": ["Alice", "Bob", "Charlie"],
"Age": [25, 30, 35],
"City": ["北京", "上海", "广州"]
}
df = pd.DataFrame(data)
print(df)
Name Age City
0 Alice 25 北京
1 Bob 30 上海
2 Charlie 35 广州
从列表嵌套字典(每行一个字典)
rows = [
{"Name": "Alice", "Age": 25, "City": "北京"},
{"Name": "Bob", "Age": 30, "City": "上海"},
{"Name": "Charlie", "Age": 35, "City": "广州"}
]
df = pd.DataFrame(rows)
从二维NumPy数组(需指定列名和索引)
import numpy as np
arr = np.array([[1, "A"], [2, "B"], [3, "C"]])
df = pd.DataFrame(arr, columns=["ID", "Label"], index=["X", "Y", "Z"])
print(df)
ID Label
X 1 A
Y 2 B
Z 3 C
从Series字典(各Series长度需一致)
s1 = pd.Series([25, 30, 35], name="Age")
s2 = pd.Series(["北京", "上海", "广州"], name="City")
df = pd.DataFrame({"Age": s1, "City": s2})
print(df)
Age City
0 25 北京
1 30 上海
2 35 广州
空的DataFrame初始化(动态添加列)
df = pd.DataFrame(columns=["Time", "Value"], index=pd.date_range("2025-01-01", periods=5))
print(df)
df["Value"] = np.random.rand(5) # 动态添加列
print(df)
Time Value
2025-01-01 NaN NaN
2025-01-02 NaN NaN
2025-01-03 NaN NaN
2025-01-04 NaN NaN
2025-01-05 NaN NaN
Time Value
2025-01-01 NaN 0.723050
2025-01-02 NaN 0.258095
2025-01-03 NaN 0.408905
2025-01-04 NaN 0.033379
2025-01-05 NaN 0.376655
5.2列索引
df = pd.DataFrame({
"Name": ["Alice", "Bob", "Charlie"],
"Age": [25, 30, 35],
"City": ["北京", "上海", "广州"]
})
单列选择(返回Series):
print(df["Age"]) # 或 df.Age(不推荐,列名含空格时失效)
0 25
1 30
2 35
Name: Age, dtype: int64
多列选择(返回新DataFrame):
print(df[["Name", "City"]])
Name City
0 Alice 北京
1 Bob 上海
2 Charlie 广州
添加/修改列:
df["Salary"] = [50000, 60000, 70000] # 新增列
df["Age"] = df["Age"] + 1 # 修改列
print(df)
Name Age City Salary
0 Alice 26 北京 50000
1 Bob 31 上海 60000
2 Charlie 36 广州 70000
删除数据:通过drop方法删除 DataFrame 中的数据,默认情况下,drop() 不会修改原 DataFrame,而是返回一个新的 DataFrame。
DataFrame.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
5.3行索引
显式索引(loc[]
,基于标签):
df.loc[0] # 单行 → Series
df.loc[[0, 2]] # 多行 → DataFrame
df.loc[0, "Age"] # 指定行和列的值
df.loc[0:2, "Name":"City"] # 切片行和列(注意闭区间)
隐式索引(iloc[]
,基于位置)
df.iloc[0] # 第一行
df.iloc[1:3, 0:2] # 行1-2(前闭后开),列0-1
df.iloc[[0,2], [1,3]] # 第0、2行,第1、3列
5.4 布尔索引(条件过滤)
# 单条件筛选
df[df["Age"] > 25]
# 多条件组合(用&, |, ~)
df[(df["City"] == "上海") & (df["Age"] < 40)]
# 使用query方法(字符串表达式)
df.query("Age > 25 and City in ['北京','广州']")
5.4删除数据
删除行/列(drop
方法)
语法:
df.drop(labels, axis=0/1, inplace=False, errors='raise')
labels
: 要删除的行或列标签(支持单个标签或列表)axis
:0
(行,默认)或1
(列)inplace
: 是否原地修改(默认False
,返回新对象)errors
:'ignore'
(忽略不存在标签)或'raise'
(默认,报错)
# 删除单行(标签为0的行)
df_new = df.drop(0, axis=0)
# 删除多列(列名"City"和"Age")
df.drop(["City", "Age"], axis=1, inplace=True)
条件删除(布尔索引筛选)
# 删除年龄小于18的行
df = df[df["Age"] >= 18]
# 删除所有城市为空的行
df = df.dropna(subset=["City"])
删除重复值(drop_duplicates
)
# 删除所有列完全重复的行(保留第一条)
df_unique = df.drop_duplicates()
# 针对特定列去重(如按"ID"列去重)
df = df.drop_duplicates(subset=["ID"], keep="last") # 保留最后一条重复值
删除缺失值(dropna
)
# 删除任何包含NaN的行
df_clean = df.dropna(axis=0, how="any")
# 删除所有列均为NaN的行
df = df.dropna(axis=0, how="all")
# 删除指定列(如"Salary")存在NaN的行
df = df.dropna(subset=["Salary"])
5.5修改元素
直接赋值修改
按标签或位置(推荐使用loc
/iloc
避免歧义):
# 修改单个值(行标签为2,列名"Age")
df.loc[2, "Age"] = 40
# 按位置修改(第3行,第1列)
df.iloc[2, 0] = "Bob"
条件批量修改
使用布尔索引定位符合条件的元素并批量修改:
# 将年龄超过60的行的"退休"列设为True
df.loc[df["Age"] > 60, "退休"] = True
# 将所有城市的"北京"替换为"Beijing"
df["City"] = df["City"].replace("北京", "Beijing")
替换操作(replace
)
支持全局或列级替换,可处理数值、字符串、正则表达式:
# 全局替换0为NaN
df.replace(0, np.nan, inplace=True)
# 字典形式替换(按列指定)
df["City"].replace({"上海": "Shanghai", "广州": "Guangzhou"}, inplace=True)
# 正则替换(将数字后加"kg")
df["Weight"] = df["Weight"].replace(r'(\d+)', r'\1kg', regex=True)