当前位置: 首页 > news >正文

【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

深度学习系列文章目录

01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战


文章目录

  • Langchain系列文章目录
  • Python系列文章目录
  • PyTorch系列文章目录
  • 机器学习系列文章目录
  • 深度学习系列文章目录
  • Java系列文章目录
  • JavaScript系列文章目录
  • 深度学习系列文章目录
  • 前言
  • 一、Pandas 核心数据结构
    • 1.1 Series 数据结构
      • 1.1.1 Series 的创建
        • (1) 从列表创建 Series
        • (2) 从 NumPy 数组创建 Series
        • (3) 从字典创建 Series
      • 1.1.2 Series 的属性与方法
        • (1) 常用属性
        • (2) 常用方法
      • 1.1.3 Series 的索引与切片
        • (1) 标签索引
        • (2) 位置索引
        • (3) 切片
    • 1.2 DataFrame 数据结构
      • 1.2.1 DataFrame 的创建
        • (1) 从字典创建 DataFrame
        • (2) 从列表的列表(或 NumPy 二维数组)创建 DataFrame
        • (3) 从 Series 列表/字典创建 DataFrame
      • 1.2.2 DataFrame 的属性与方法
        • (1) 常用属性
        • (2) 常用方法
      • 1.2.3 DataFrame 的索引与切片
        • (1) 选择列
        • (2) 选择行:`.loc[]` 和 `.iloc[]`
  • 二、数据读取与写入
    • 2.1 读取 CSV 文件
      • 2.1.1 基本读取
      • 2.1.2 常用参数
    • 2.2 写入 CSV 文件
    • 2.3 其他数据格式
  • 三、数据选择与过滤
    • 3.1 基于标签的选择:`.loc[]`
    • 3.2 基于位置的选择:`.iloc[]`
    • 3.3 条件选择
    • 3.4 组合条件
  • 四、基本的数据清洗和转换操作
    • 4.1 处理缺失值
      • 4.1.1 检测缺失值
      • 4.1.2 填充缺失值
      • 4.1.3 删除缺失值
    • 4.2 处理重复值
      • 4.2.1 检测重复值
      • 4.2.2 删除重复值
    • 4.3 数据类型转换
    • 4.4 应用函数
  • 五、实践:加载并简单探索一个表格数据集
    • 5.1 数据集介绍
    • 5.2 加载数据
    • 5.3 查看数据基本信息
    • 5.4 初步探索与清洗
        • (1) 处理缺失值
        • (2) 处理重复值
        • (3) 简单数据查询
        • (4) 计算新列
  • 六、总结


前言

在深度学习的征途中,数据扮演着至关重要的角色。正所谓“工欲善其事,必先利其器”,要高效地处理和分析数据,一个强大的工具必不可少。Pandas 就是这样一把在 Python 数据科学生态系统中熠熠生辉的“瑞士军刀”。它提供了高性能、易用的数据结构和数据分析工具,使得我们能够轻松应对各种结构化数据的挑战。无论是数据清洗、转换、分析还是可视化前的准备,Pandas 都能提供强有力的支持。本篇文章将带您深入了解 Pandas 的核心概念、常用操作以及如何在实际项目中运用它来处理表格数据,为后续的深度学习模型训练打下坚实的数据基础。

一、Pandas 核心数据结构

Pandas 之所以强大,首先归功于其两大核心数据结构:SeriesDataFrame。它们为我们处理不同类型的数据提供了灵活且高效的容器。

1.1 Series 数据结构

可以将 Series 理解为一个一维的、带标签的数组。它能够存储任何数据类型(整数、字符串、浮点数、Python 对象等),并且每个元素都有一个与之关联的标签,称为索引(index)。

1.1.1 Series 的创建

创建 Series 的方式多种多样,最常见的是从列表、NumPy 数组或字典创建。

(1) 从列表创建 Series
import pandas as pd
import numpy as np# 从列表创建 Series,默认索引为 0, 1, 2...
data_list = [10, 20, 30, 40, 50]
s_from_list = pd.Series(data_list)
print("从列表创建的 Series:")
print(s_from_list)# 创建时指定索引
index_labels = ['a', 'b', 'c', 'd', 'e']
s_with_labels = pd.Series(data_list, index=index_labels)
print("\n带指定标签的 Series:")
print(s_with_labels)

代码解释:

  • pd.Series(data): data 可以是列表、NumPy 数组等。
  • index: 可选参数,用于指定 Series 的索引标签。若不指定,则默认为从0开始的整数索引。
(2) 从 NumPy 数组创建 Series
# 从 NumPy 数组创建 Series
data_numpy = np.array([5.0, 6.0, 7.0, 8.0])
s_from_numpy = pd.Series(data_numpy, index=['w', 'x', 'y', 'z'])
print("\n从 NumPy 数组创建的 Series:")
print(s_from_numpy)
(3) 从字典创建 Series

当从字典创建 Series 时,字典的键(keys)会自动成为 Series 的索引,字典的值(values)则成为 Series 的数据。

# 从字典创建 Series
data_dict = {'apple': 3, 'banana': 5, 'cherry': 2, 'date': 7}
s_from_dict = pd.Series(data_dict)
print("\n从字典创建的 Series:")
print(s_from_dict)# 如果同时传递了 index 参数,则会按照 index 中的标签进行选取和排序
s_from_dict_indexed = pd.Series(data_dict, index=['banana', 'apple', 'orange', 'cherry'])
print("\n从字典创建并指定索引的 Series (orange 会是 NaN):")
print(s_from_dict_indexed) # 注意:'orange' 在 data_dict 中不存在,其值为 NaN

关键点: 如果字典的键和指定的 index 不完全匹配,Pandas 会根据 index 来构建 Series,缺失的键对应的值会是 NaN (Not a Number),表示缺失数据。

1.1.2 Series 的属性与方法

Series 对象拥有许多有用的属性和方法,帮助我们理解和操作数据。

(1) 常用属性
  • index: 获取 Series 的索引。
  • values: 获取 Series 的数据,以 NumPy 数组形式返回。
  • dtype: 获取 Series 中数据的数据类型。
  • name: 获取或设置 Series 的名称。
  • size: 获取 Series 中元素的数量。
  • shape: 获取 Series 的形状(元组形式,对于 Series 总是 (n,))。
  • ndim: 获取 Series 的维度数量(总是 1)。
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'], name='MyNumbers')
print(f"\nSeries 名称: {s.name}")
print(f"Series 索引: {s.index}")
print(f"Series 值 (NumPy 数组): {s.values}")
print(f"Series 数据类型: {s.dtype}")
print(f"Series 大小: {s.size}")
print(f"Series 形状: {s.shape}")
print(f"Series 维度: {s.ndim}")
(2) 常用方法
  • head(n): 查看前 n 个元素,默认为 5。
  • tail(n): 查看后 n 个元素,默认为 5。
  • describe(): 生成描述性统计信息(计数、均值、标准差、最小值、最大值、分位数等)。
  • isnull() / notnull(): 检测缺失值,返回布尔型 Series
  • mean(), sum(), min(), max(), std(): 计算统计量。
  • value_counts(): 计算每个唯一值的出现次数。
  • apply(func): 将函数 func 应用于 Series 的每个元素。
  • astype(dtype): 转换 Series 的数据类型。
s_data = pd.Series([10, 20, 10, 30, 20, 20, np.nan, 40])
print("\n示例 Series:")
print(s_data)
print("\n前3个元素 (head(3)):")
print(s_data.head(3))
print("\n描述性统计 (describe()):")
print(s_data.describe())
print("\n是否为空值 (isnull()):")
print(s_data.isnull())
print("\n值计数 (value_counts()):")
print(s_data.value_counts()) # NaN 不会被计算在内
print("\n值计数 (包括 NaN, value_counts(dropna=False)):")
print(s_data.value_counts(dropna=False))
print(f"\n平均值: {s_data.mean()}") # NaN 会被忽略

1.1.3 Series 的索引与切片

Series 的索引方式非常灵活,既可以使用标签索引,也可以使用位置索引(类似 Python 列表)。

(1) 标签索引

使用中括号 [] 配合索引标签。

s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(f"\n通过标签 'b' 获取元素: {s['b']}") # 输出 20
# 获取多个元素
print("\n通过标签列表 ['a', 'c'] 获取元素:")
print(s[['a', 'c']])
(2) 位置索引

使用中括号 [] 配合整数位置。

s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(f"\n通过位置 0 获取元素: {s[0]}") # 输出 10
# 获取多个元素(注意:这里使用整数列表作为索引器)
print("\n通过位置列表 [0, 2] 获取元素:")
print(s[[0, 2]])
(3) 切片

切片操作也支持标签和位置。

  • 标签切片: 包含结束标签。
  • 位置切片: 不包含结束位置(与 Python 列表切片行为一致)。
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
print("\n标签切片 'b':'d':")
print(s['b':'d']) # 包含 'b', 'c', 'd'print("\n位置切片 1:4:")
print(s[1:4]) # 包含位置 1, 2, 3 (对应标签 'b', 'c', 'd')

注意: 当索引是整数时,直接使用 s[整数] 进行切片可能会产生歧义(是标签索引还是位置索引?)。Pandas 推荐使用 .loc[] (基于标签) 和 .iloc[] (基于位置) 来进行明确的索引,这在 DataFrame 中更为常用和重要。

1.2 DataFrame 数据结构

DataFrame 是 Pandas 中最核心的数据结构,它是一个二维的、表格型的数据结构,类似于电子表格、SQL 表或字典对象。DataFrame 既有行索引也有列索引,每列可以包含不同的数据类型。

可以将 DataFrame 理解为共享相同索引的 Series 的集合(或字典)。

1.2.1 DataFrame 的创建

创建 DataFrame 的方式同样很多,常见的方法包括:

(1) 从字典创建 DataFrame

最常用的方式之一是用一个字典来创建 DataFrame,其中字典的键将成为列名,字典的值(通常是列表、NumPy 数组或 Series)将成为列的数据。所有传入的列表/数组长度必须一致。

# 字典的键是列名,值是该列的数据
data_dict_df = {'Name': ['Alice', 'Bob', 'Charlie', 'David'],'Age': [25, 30, 35, 28],'City': ['New York', 'Paris', 'London', 'Tokyo']
}
df_from_dict = pd.DataFrame(data_dict_df)
print("从字典创建的 DataFrame:")
print(df_from_dict)# 创建时指定行索引
df_from_dict_indexed = pd.DataFrame(data_dict_df, index=['id1', 'id2', 'id3', 'id4'])
print("\n从字典创建并指定行索引的 DataFrame:")
print(df_from_dict_indexed)
(2) 从列表的列表(或 NumPy 二维数组)创建 DataFrame

可以提供一个嵌套列表或 NumPy 二维数组作为数据,并可选地指定列名和行索引。

data_list_of_lists = [['Alice', 25, 'New York'],['Bob', 30, 'Paris'],['Charlie', 35, 'London']
]
df_from_lol = pd.DataFrame(data_list_of_lists, columns=['Name', 'Age', 'City'], index=['p1', 'p2', 'p3'])
print("\n从列表的列表创建的 DataFrame:")
print(df_from_lol)data_numpy_2d = np.array([[1.1, 1.2, 1.3],[2.1, 2.2, 2.3],[3.1, 3.2, 3.3]
])
df_from_numpy_2d = pd.DataFrame(data_numpy_2d, columns=['A', 'B', 'C'])
print("\n从 NumPy 二维数组创建的 DataFrame:")
print(df_from_numpy_2d)
(3) 从 Series 列表/字典创建 DataFrame
s1 = pd.Series([1, 2, 3], name='Col1')
s2 = pd.Series([4, 5, 6], name='Col2')
# 使用字典,键是列名
df_from_series_dict = pd.DataFrame({'A': s1, 'B': s2})
print("\n从 Series 字典创建的 DataFrame:")
print(df_from_series_dict)

1.2.2 DataFrame 的属性与方法

Series 类似,DataFrame 也有一系列属性和方法。

(1) 常用属性
  • index: 获取行索引。
  • columns: 获取列索引(列名)。
  • dtypes: 获取每列的数据类型(返回一个 Series)。
  • values: 获取 DataFrame 的数据,以 NumPy 二维数组形式返回。
  • shape: 获取 DataFrame 的形状(行数, 列数)。
  • size: 获取 DataFrame 中元素的总数(行数 * 列数)。
  • ndim: 获取 DataFrame 的维度数量(总是 2)。
  • T: 转置 DataFrame(行和列互换)。
df = pd.DataFrame({'A': [1, 2, 3],'B': [4.0, 5.5, 6.1],'C': ['x', 'y', 'z']
})
print("\n示例 DataFrame:")
print(df)
print(f"行索引: {df.index}")
print(f"列索引: {df.columns}")
print(f"每列数据类型:\n{df.dtypes}")
print(f"数据 (NumPy 数组):\n{df.values}")
print(f"形状: {df.shape}")
print(f"大小: {df.size}")
print(f"维度: {df.ndim}")
print(f"转置:\n{df.T}")
(2) 常用方法

许多 Series 的方法也适用于 DataFrame,通常会按列进行操作或返回一个 DataFrame

  • head(n), tail(n): 查看头部/尾部数据。
  • describe(): 生成描述性统计(默认只对数值列)。
  • info(): 提供 DataFrame 的简洁摘要,包括索引类型、列类型、非空值数量和内存使用情况。
  • isnull(), notnull(): 检测缺失值,返回布尔型 DataFrame
  • sum(), mean(), min(), max(), std(): 默认按列计算统计量(可通过 axis=1 按行计算)。
  • apply(func, axis=0): 将函数 func 应用于每列 (axis=0) 或每行 (axis=1)。
  • astype(dtype_dict): 转换列的数据类型,dtype_dict 是一个列名到目标类型的映射。
  • sort_values(by, ascending=True): 按指定列的值排序。
  • sort_index(axis=0, ascending=True): 按索引排序。
  • drop(labels, axis=0): 删除指定的行 (axis=0) 或列 (axis=1)。
df_example = pd.DataFrame({'col1': [1, 2, np.nan, 4, 2],'col2': [5.0, 6.1, 7.3, 5.0, 6.1],'col3': ['a', 'b', 'a', 'c', 'b']
})
print("\n示例 DataFrame for methods:")
print(df_example)
print("\nDataFrame 信息 (info()):")
df_example.info()
print("\n描述性统计 (describe()):")
print(df_example.describe())
print("\n按 col3 排序:")
print(df_example.sort_values(by='col3'))
print("\n删除 col1 (drop('col1', axis=1)):")
print(df_example.drop('col1', axis=1)) # 注意:drop 默认不修改原 DataFrame,除非 inplace=True

1.2.3 DataFrame 的索引与切片

DataFrame 的索引比 Series 更为复杂,因为它涉及行和列。

(1) 选择列
  • 使用中括号 [] 加列名: df['column_name'] (返回一个 Series)。
  • 使用点号 . 加列名: df.column_name (仅当列名是有效的 Python 标识符且不与 DataFrame 方法名冲突时可用,返回一个 Series)。
  • 使用中括号 [] 加列名列表: df[['col1', 'col2']] (返回一个新的 DataFrame)。
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'Score': [88, 92, 78]
})
print("\n选择 'Age' 列 (Series):")
print(df['Age'])
print("\n选择 'Name' 和 'Score' 列 (DataFrame):")
print(df[['Name', 'Score']])
(2) 选择行:.loc[].iloc[]

为了避免混淆并进行精确的行选择(以及行列组合选择),Pandas 强烈推荐使用 .loc[].iloc[]

  • .loc[] (Label-based selection): 基于标签(行索引名和列索引名)进行选择。

    • df.loc[row_label]:选择单行 (返回 Series)。
    • df.loc[[row_label1, row_label2]]:选择多行 (返回 DataFrame)。
    • df.loc[row_label_slice]:行标签切片 (包含结束标签)。
    • df.loc[row_selection, column_selection]:同时选择行和列。
  • .iloc[] (Integer-location based selection): 基于整数位置进行选择。

    • df.iloc[row_position]:选择单行 (返回 Series)。
    • df.iloc[[row_pos1, row_pos2]]:选择多行 (返回 DataFrame)。
    • df.iloc[row_pos_slice]:行位置切片 (不包含结束位置)。
    • df.iloc[row_pos_selection, col_pos_selection]:同时选择行和列。
df_indexed = pd.DataFrame({'A': [10, 20, 30, 40],'B': [50, 60, 70, 80],'C': [90, 100, 110, 120]
}, index=['r1', 'r2', 'r3', 'r4'])print("\n使用 .loc[] 选择行 'r2':")
print(df_indexed.loc['r2'])print("\n使用 .loc[] 选择行 'r1' 到 'r3':")
print(df_indexed.loc['r1':'r3']) # 包含 'r3'print("\n使用 .loc[] 选择 'r2' 行的 'A' 和 'C' 列:")
print(df_indexed.loc['r2', ['A', 'C']])print("\n使用 .iloc[] 选择第 0 行 (位置):")
print(df_indexed.iloc[0])print("\n使用 .iloc[] 选择第 1 到 3 行 (位置, 不含3):")
print(df_indexed.iloc[1:3])print("\n使用 .iloc[] 选择第 0 行的第 0 和第 2 列 (位置):")
print(df_indexed.iloc[0, [0, 2]])print("\n使用 .iloc[] 选择所有行的第 1 列 (位置):")
print(df_indexed.iloc[:, 1])

场景驱动: .loc[] 非常适合当你知道行或列的名称时使用,而 .iloc[] 则在你需要基于它们的数字位置来选择数据时非常有用,例如在循环中。

二、数据读取与写入

Pandas 提供了非常方便的函数来读取和写入多种格式的数据文件,其中最常用的是 CSV 文件。

2.1 读取 CSV 文件

逗号分隔值(CSV)文件是一种非常常见的纯文本数据存储格式。Pandas 的 read_csv() 函数可以轻松地将 CSV 文件加载到 DataFrame 中。

2.1.1 基本读取

假设我们有一个名为 data.csv 的文件,内容如下:

Name,Age,City
Alice,25,New York
Bob,30,Paris
Charlie,,London
David,28,Tokyo
Eve,22,

我们可以这样读取它:

# 为了演示,我们先用代码创建一个示例 CSV 文件
csv_content = """Name,Age,City
Alice,25,New York
Bob,30,Paris
Charlie,,London
David,28,Tokyo
Eve,22,""" # Eve 的 City 是空字符串with open('example_data.csv', 'w') as f:f.write(csv_content)# 基本读取
df_csv = pd.read_csv('example_data.csv')
print("从 CSV 文件读取的 DataFrame:")
print(df_csv)

观察: 注意 CharlieAgeEveCity 在 DataFrame 中显示为 NaN(如果CSV中是空字段)或空字符串(如果CSV中是 "")。read_csv 会尝试智能地推断数据类型。

2.1.2 常用参数

pd.read_csv() 函数有很多可选参数,可以帮助我们更精确地控制读取过程。

  • filepath_or_buffer: 文件路径、URL 或任何带有 read() 方法的对象。
  • sep (或 delimiter): 字段间的分隔符,默认为 ,。如果文件使用其他分隔符(如制表符 \t、分号 ;),需要指定。
  • header: 指定哪一行作为列名。默认为 0(第一行)。如果文件没有列名,可以设置为 None,Pandas 会自动生成数字列名。
  • index_col: 指定某一列或多列作为行索引。
  • names: 当 header=None 时,用于提供列名列表。
  • usecols: 一个列表或可调用对象,用于指定要读取的列。例如 ['Name', 'City'] 只读取这两列。
  • dtype: 一个字典,用于指定某些列的数据类型,例如 {'Age': int, 'City': str}。这在自动类型推断不准确时很有用。
  • na_values: 一个标量、字符串、列表或字典,指定哪些值应被视作 NaN(缺失值)。
  • skiprows: 一个整数或列表,表示跳过文件顶部的指定行数或特定行号。
  • nrows: 只读取文件的前 n 行,对于快速检查大文件非常有用。
# 示例:使用不同参数读取
# 假设有一个 tab 分隔的文件 (data.tsv) 且没有 header
tsv_content = """Alice\t25\tNew York
Bob\t30\tParis"""
with open('example_data.tsv', 'w') as f:f.write(tsv_content)df_tsv_no_header = pd.read_csv('example_data.tsv', sep='\t', header=None, names=['PersonName', 'Years', 'Location'])
print("\n读取TSV文件,无表头,自定义列名:")
print(df_tsv_no_header)# 读取 example_data.csv,并将 'Name' 列作为行索引
df_csv_indexed = pd.read_csv('example_data.csv', index_col='Name')
print("\n读取CSV,并将 'Name' 列作为行索引:")
print(df_csv_indexed)# 读取 example_data.csv,只读取 'Name' 和 'City' 列
df_csv_usecols = pd.read_csv('example_data.csv', usecols=['Name', 'City'])
print("\n读取CSV,只选择 'Name' 和 'City' 列:")
print(df_csv_usecols)# 读取 example_data.csv,并将空字符串视为空值
df_csv_na_values = pd.read_csv('example_data.csv', na_values=['']) # 将 Charlie 的 Age 识别为 NaN
print("\n读取CSV,并将空字符串视为空值:")
print(df_csv_na_values)

2.2 写入 CSV 文件

DataFrame 保存到 CSV 文件同样简单,使用 to_csv() 方法。

df_to_save = pd.DataFrame({'Product': ['Apple', 'Banana', 'Orange'],'Price': [1.0, 0.5, 0.75],'Quantity': [100, 150, 200]
})# 基本写入
df_to_save.to_csv('output_data.csv')
print("\nDataFrame 已保存到 output_data.csv (包含行索引和表头)")# 不保存行索引
df_to_save.to_csv('output_data_no_index.csv', index=False)
print("DataFrame 已保存到 output_data_no_index.csv (不包含行索引)")# 使用不同的分隔符,并指定编码
df_to_save.to_csv('output_data_custom.tsv', sep='\t', encoding='utf-8', index=False)
print("DataFrame 已保存到 output_data_custom.tsv (制表符分隔,UTF-8编码,无索引)")

常用参数:

  • path_or_buf: 文件路径或类文件对象。
  • sep: 分隔符,默认为 ,
  • na_rep: 用于替换缺失值的字符串,默认为空字符串。
  • columns: 要写入的列的序列,默认为所有列。
  • header: 是否写入列名,默认为 True
  • index: 是否写入行索引,默认为 True
  • mode: 写入模式,'w' 为覆盖,'a' 为追加。
  • encoding: 文件编码。

2.3 其他数据格式

Pandas 不仅仅能处理 CSV 文件,它还支持多种其他数据格式的读写:

  • Excel 文件: pd.read_excel()df.to_excel() (通常需要 openpyxlxlrd 库)。
  • SQL 数据库: pd.read_sql_query(), pd.read_sql_table()df.to_sql() (需要 SQLAlchemy 等库)。
  • JSON 文件: pd.read_json()df.to_json()
  • HTML 表格: pd.read_html() (可以读取网页中的表格)。
  • HDF5 文件: pd.read_hdf()df.to_hdf() (高效存储大型数据集)。
  • Parquet 文件: pd.read_parquet()df.to_parquet() (列式存储,高效且压缩好)。
# 示例:写入和读取 Excel (需要安装 openpyxl: pip install openpyxl)
# df_to_save.to_excel('output_data.xlsx', sheet_name='Sheet1', index=False)
# df_excel_read = pd.read_excel('output_data.xlsx', sheet_name='Sheet1')
# print("\n从 Excel 文件读取的 DataFrame:")
# print(df_excel_read)

实践建议: 根据你的数据来源和存储需求,选择合适的读写函数。对于大型数据集,Parquet 或 HDF5 通常是更好的选择。

三、数据选择与过滤

DataFrame 中准确地选择和过滤出你需要的数据子集是数据分析中的核心操作。Pandas 提供了多种强大的方式来实现这一点。

3.1 基于标签的选择:.loc[]

如前所述,.loc[] 主要用于基于行和列的标签(名称)进行选择。

  • 选择单行: df.loc[row_label]
  • 选择多行: df.loc[[row_label1, row_label2]]
  • 选择行切片: df.loc[start_label:end_label] (包含 end_label)
  • 选择特定行和列: df.loc[row_selection, column_selection]
  • 选择所有行和特定列: df.loc[:, column_selection]
  • 选择特定行和所有列: df.loc[row_selection, :] (或者直接 df.loc[row_selection])
data = {'col1': [1, 2, 3, 4], 'col2': [5, 6, 7, 8], 'col3': [9, 10, 11, 12]}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
print("\n示例 DataFrame for selection:")
print(df)# 选择 'b' 行
print("\n.loc['b']:")
print(df.loc['b'])# 选择 'a' 和 'd' 行
print("\n.loc[['a', 'd']]:")
print(df.loc[['a', 'd']])# 选择从 'b' 到 'd' 的行
print("\n.loc['b':'d']:")
print(df.loc['b':'d'])# 选择 'c' 行的 'col2' 列
print("\n.loc['c', 'col2']:")
print(df.loc['c', 'col2']) # 返回一个标量# 选择 'a' 和 'c' 行的 'col1' 和 'col3' 列
print("\n.loc[['a', 'c'], ['col1', 'col3']]:")
print(df.loc[['a', 'c'], ['col1', 'col3']])# 选择所有行的 'col2' 列
print("\n.loc[:, 'col2']:")
print(df.loc[:, 'col2']) # 返回一个 Series

3.2 基于位置的选择:.iloc[]

.iloc[] 用于基于整数位置(从0开始)进行选择。

  • 选择单行: df.iloc[row_position]
  • 选择多行: df.iloc[[row_pos1, row_pos2]]
  • 选择行切片: df.iloc[start_pos:end_pos] (不包含 end_pos)
  • 选择特定行和列: df.iloc[row_pos_selection, col_pos_selection]
  • 选择所有行和特定列: df.iloc[:, col_pos_selection]
  • 选择特定行和所有列: df.iloc[row_pos_selection, :] (或者直接 df.iloc[row_pos_selection])
print("\n示例 DataFrame (same as above):")
print(df)# 选择位置为 1 的行 (即第二行,索引 'b')
print("\n.iloc[1]:")
print(df.iloc[1])# 选择位置为 0 和 2 的行
print("\n.iloc[[0, 2]]:")
print(df.iloc[[0, 2]])# 选择位置从 1 到 3 的行 (不包括位置3)
print("\n.iloc[1:3]:")
print(df.iloc[1:3]) # 行 'b' 和 'c'# 选择位置为 2 的行的位置为 1 的列 (即 'c' 行的 'col2' 列)
print("\n.iloc[2, 1]:")
print(df.iloc[2, 1]) # 返回标量 11# 选择位置为 0 和 3 的行的位置为 0 和 2 的列
print("\n.iloc[[0, 3], [0, 2]]:")
print(df.iloc[[0, 3], [0, 2]])# 选择所有行的位置为 1 的列
print("\n.iloc[:, 1]:")
print(df.iloc[:, 1]) # 返回 Series col2

重要提示: 同时使用标签和位置进行混合索引是不推荐的,容易出错。坚持使用 .loc[] 进行纯标签索引,使用 .iloc[] 进行纯位置索引。

3.3 条件选择

这是数据分析中最常用的功能之一:根据一个或多个条件来筛选数据。这通常会返回一个布尔型 Series,然后用这个布尔 Series 来索引 DataFrame

data_people = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'Age': [25, 30, 22, 30, 28],'Score': [88, 92, 75, 92, 85]
}
df_people = pd.DataFrame(data_people)
print("\n人员数据 DataFrame:")
print(df_people)# 条件:年龄大于 25
condition_age_gt_25 = df_people['Age'] > 25
print("\n年龄大于 25 的布尔 Series:")
print(condition_age_gt_25)# 应用条件选择
df_age_gt_25 = df_people[condition_age_gt_25]
print("\n年龄大于 25 的人员:")
print(df_age_gt_25)# 直接在索引中写条件
df_score_lt_90 = df_people[df_people['Score'] < 90]
print("\n分数小于 90 的人员:")
print(df_score_lt_90)

原理透彻: 当你写 df[boolean_series] 时,Pandas 会取出 boolean_series 中为 True 的那些行对应的原始 DataFrame 中的数据。

3.4 组合条件

你可以使用逻辑运算符 & (与, AND)、| (或, OR) 和 ~ (非, NOT) 来组合多个条件。非常重要的是,当组合多个条件时,每个条件都应该用括号 () 括起来,因为这些逻辑运算符的优先级问题。

print("\n人员数据 DataFrame (same as above):")
print(df_people)# 条件1: Age >= 28
cond1 = df_people['Age'] >= 28
# 条件2: Score > 90
cond2 = df_people['Score'] > 90# 组合条件:年龄大于等于28 且 分数大于90
df_combined_and = df_people[(cond1) & (cond2)] # 注意括号
print("\n年龄 >= 28 且 分数 > 90 的人员:")
print(df_combined_and)# 组合条件:年龄小于25 或 分数等于92
df_combined_or = df_people[(df_people['Age'] < 25) | (df_people['Score'] == 92)]
print("\n年龄 < 25 或 分数 == 92 的人员:")
print(df_combined_or)# 条件:Name 不是 'Alice'
df_not_alice = df_people[~(df_people['Name'] == 'Alice')]
print("\n不是 Alice 的人员:")
print(df_not_alice)

常见问题:

  • 忘记给每个条件加括号,例如 df_people[df_people['Age'] >= 28 & df_people['Score'] > 90] 会因为运算符优先级导致错误。正确写法是 df_people[(df_people['Age'] >= 28) & (df_people['Score'] > 90)]
  • 使用 Python 的 and, or, not 关键字代替 &, |, ~。在 Pandas 条件表达式中,必须使用位运算符。

四、基本的数据清洗和转换操作

真实世界的数据往往是不完美的:可能包含缺失值、重复值,或者数据类型不正确。Pandas 提供了强大的工具来进行数据清洗和转换,这是数据预处理的关键步骤。

4.1 处理缺失值

缺失值(通常表示为 NaN, NoneNaT (for datetime))在数据集中很常见。

4.1.1 检测缺失值

  • isnull(): 返回一个布尔型的 DataFrameSeriesTrue 表示对应位置是缺失值。
  • notnull(): 与 isnull() 相反。
  • any(axis=...): 在指定轴上检查是否有任何 True
  • all(axis=...): 在指定轴上检查是否所有都为 True
data_missing = {'A': [1, 2, np.nan, 4, 5],'B': [np.nan, 7, 8, np.nan, 10],'C': [11, 12, 13, 14, np.nan],'D': [16, 17, 18, 19, 20] # 无缺失值
}
df_missing = pd.DataFrame(data_missing)
print("\n包含缺失值的 DataFrame:")
print(df_missing)print("\n检测缺失值 (isnull()):")
print(df_missing.isnull())print("\n每列是否有缺失值 (isnull().any()):")
print(df_missing.isnull().any()) # 默认 axis=0,即按列print("\n每行是否有缺失值 (isnull().any(axis=1)):")
print(df_missing.isnull().any(axis=1))print("\n缺失值总数 (isnull().sum().sum()):")
print(df_missing.isnull().sum().sum())print("\n每列的缺失值数量 (isnull().sum()):")
print(df_missing.isnull().sum())

4.1.2 填充缺失值

使用 fillna() 方法可以用指定的值或策略来填充 NaN

  • df.fillna(value): 用标量 value 填充所有 NaN
  • df.fillna(method='ffill'): 前向填充(用前一个非缺失值填充)。
  • df.fillna(method='bfill'): 后向填充(用后一个非缺失值填充)。
  • 可以为不同列指定不同的填充值:df.fillna({'A': 0, 'B': df['B'].mean()})
  • inplace=True: 修改原始 DataFrame
print("\n用 0 填充所有缺失值:")
print(df_missing.fillna(0))print("\n用每列的平均值填充 (只对数值列B有效,A因为有NaN无法直接求mean, C不能求mean):")
# 注意: Series.mean() 会自动忽略 NaN
df_filled_mean = df_missing.copy() # 创建副本以避免修改原始 df_missing
df_filled_mean['A'] = df_filled_mean['A'].fillna(df_filled_mean['A'].mean())
df_filled_mean['B'] = df_filled_mean['B'].fillna(df_filled_mean['B'].mean())
df_filled_mean['C'] = df_filled_mean['C'].fillna('Unknown') # 假设 C 是类别,用特定字符串填充
print(df_filled_mean)print("\n前向填充 (ffill):")
print(df_missing.fillna(method='ffill'))print("\n后向填充 (bfill):")
print(df_missing.fillna(method='bfill'))

场景驱动: 填充策略的选择取决于数据的特性和分析的目的。例如,时间序列数据常用 ffill。对于数值特征,可以用均值、中位数填充。对于类别特征,可以用众数或一个特定的占位符填充。

4.1.3 删除缺失值

使用 dropna() 方法可以删除包含缺失值的行或列。

  • df.dropna()df.dropna(axis=0): 删除任何包含 NaN 的行 (默认行为)。
  • df.dropna(axis=1): 删除任何包含 NaN 的列。
  • how='all': 只删除所有值都为 NaN 的行/列。默认 how='any' (只要有一个 NaN 就删除)。
  • thresh=N: 保留至少有 N 个非 NaN 值的行/列。
  • subset=['col1', 'col2']: 只在指定的列子集中检查 NaN 来决定是否删除行。
  • inplace=True: 修改原始 DataFrame
print("\n删除任何包含 NaN 的行:")
print(df_missing.dropna())print("\n删除任何包含 NaN 的列 (列D会被保留):")
print(df_missing.dropna(axis=1))print("\n删除所有值都为 NaN 的行 (本例中无此类行):")
df_all_nan_row = df_missing.append(pd.Series([np.nan, np.nan, np.nan, np.nan], index=df_missing.columns, name='new_row')) # 添加一行全是NaN
print(df_all_nan_row.dropna(how='all'))print("\n只在 'A' 和 'B' 列检查 NaN,并删除对应行:")
print(df_missing.dropna(subset=['A', 'B'])) # 只要A或B是NaN,该行就被删print("\n保留至少有3个非NaN值的行:")
print(df_missing.dropna(thresh=3))

实用建议: 删除数据是一种简单粗暴的方法,可能会丢失有价值的信息。除非缺失比例非常高,或者特定分析不容许缺失值,否则优先考虑填充。

4.2 处理重复值

数据集中可能存在完全重复的行。

4.2.1 检测重复值

duplicated() 方法返回一个布尔型 Series,标记出重复的行。默认情况下,第一次出现的行不被标记为重复。

  • df.duplicated(): 标记除了第一次出现之外的重复行。
  • df.duplicated(keep='last'): 标记除了最后一次出现之外的重复行。
  • df.duplicated(keep=False): 标记所有重复的行。
  • subset=['col1', 'col2']: 只考虑指定列的组合来判断是否重复。
data_duplicates = {'ID': [1, 2, 1, 3, 2, 4],'Name': ['A', 'B', 'A', 'C', 'B', 'D'],'Value': [100, 200, 100, 300, 200, 400]
}
df_duplicates = pd.DataFrame(data_duplicates)
print("\n包含重复值的 DataFrame:")
print(df_duplicates)print("\n检测重复行 (默认 keep='first'):")
print(df_duplicates.duplicated()) # 行索引2和4 (0-based) 是重复的print("\n检测重复行 (keep='last'):")
print(df_duplicates.duplicated(keep='last')) # 行索引0和1 是重复的print("\n检测所有重复的行 (keep=False):")
print(df_duplicates.duplicated(keep=False))print("\n基于 'ID' 列检测重复:")
print(df_duplicates.duplicated(subset=['ID']))

4.2.2 删除重复值

drop_duplicates() 方法用于删除重复行。

  • df.drop_duplicates(): 删除重复行,保留第一次出现的 (默认 keep='first')。
  • df.drop_duplicates(keep='last'): 删除重复行,保留最后一次出现的。
  • df.drop_duplicates(keep=False): 删除所有重复的行。
  • subset=['col1', 'col2']: 基于指定列删除重复。
  • inplace=True: 修改原始 DataFrame
print("\n删除重复行 (保留第一个):")
print(df_duplicates.drop_duplicates())print("\n基于 'ID' 列删除重复行 (保留第一个):")
print(df_duplicates.drop_duplicates(subset=['ID']))print("\n删除 'ID' 和 'Name' 都重复的行,保留最后一个,并原地修改:")
df_temp = df_duplicates.copy()
df_temp.drop_duplicates(subset=['ID', 'Name'], keep='last', inplace=True)
print(df_temp)

4.3 数据类型转换

有时,数据被加载后类型不正确(例如,数字被当作字符串)。astype() 方法用于转换 DataFrameSeries 的数据类型。

data_types = {'ProductID': [1, 2, 3],'Price': ['10.5', '20.0', '5.75'], # Price 是字符串'Quantity': [100, '50', 120]      # Quantity 部分是字符串
}
df_types = pd.DataFrame(data_types)
print("\n原始数据类型 DataFrame:")
print(df_types)
print(df_types.dtypes)# 转换 'Price' 为 float
df_types['Price'] = df_types['Price'].astype(float)# 转换 'Quantity' 为 int (如果包含不能转为int的,如 '50.0' 或非数字字符串,会报错)
# 为了安全,可以先处理可能存在的非整数字符串
df_types['Quantity'] = pd.to_numeric(df_types['Quantity'], errors='coerce').fillna(0).astype(int) # errors='coerce' 会将无法转换的变为NaNprint("\n转换后数据类型 DataFrame:")
print(df_types)
print(df_types.dtypes)# 也可以使用字典一次转换多列
# df_types = df_types.astype({'Price': float, 'Quantity': int})

注意: 如果转换不兼容(例如,将包含字母的字符串转换为 int),astype() 会引发错误。使用 pd.to_numeric() 配合 errors='coerce' 参数可以在转换失败时将其设为 NaN,之后再进行处理。

4.4 应用函数

Pandas 允许你对数据应用自定义函数或已有的 Python 函数。

  • Series.apply(func)Series.map(func_or_dict): 对 Series 的每个元素应用函数。map 也可以接受字典或 Series 来进行元素映射。
  • DataFrame.apply(func, axis=0): 将函数 func 应用于 DataFrame 的每列 (axis=0,默认) 或每行 (axis=1)。传递给 func 的是 Series 对象。
  • DataFrame.applymap(func): 将函数 func 应用于 DataFrame 的每个元素。
df_apply = pd.DataFrame({'A': [1, 2, 3, 4],'B': [10, 20, 30, 40],'C': ['foo', 'bar', 'baz', 'qux']
})
print("\n示例 DataFrame for apply/map:")
print(df_apply)# Series.apply
print("\n对 'A' 列每个元素平方:")
print(df_apply['A'].apply(lambda x: x**2))# Series.map (常用于基于字典的替换)
category_map = {'foo': 1, 'bar': 2, 'baz': 3, 'qux': 4}
print("\n用字典映射 'C' 列:")
print(df_apply['C'].map(category_map))# DataFrame.apply (对每列求和)
print("\n对 DataFrame 每列求和 (axis=0):")
print(df_apply[['A', 'B']].apply(sum, axis=0)) # 或者 df_apply[['A','B']].sum()# DataFrame.apply (对每行计算 A+B)
print("\n对 DataFrame 每行计算 A+B (axis=1):")
print(df_apply.apply(lambda row: row['A'] + row['B'], axis=1))# DataFrame.applymap (对所有数值元素 +5,非数值元素会报错,需小心使用)
df_numeric = df_apply[['A', 'B']]
print("\n对 DataFrame 所有数值元素 +5 (applymap):")
print(df_numeric.applymap(lambda x: x + 5))

场景驱动:

  • 当需要对 Series 的每个值进行转换时,applymap 非常有用。
  • 当需要对 DataFrame 的行或列进行聚合或复杂转换时,apply 是强大的工具。
  • applymap 适用于对 DataFrame 中所有元素执行相同的元素级操作。

五、实践:加载并简单探索一个表格数据集

理论学习后,实践是巩固知识的最佳方式。让我们加载一个简单的数据集并进行初步探索。

5.1 数据集介绍

我们将创建一个简单的学生分数 CSV 文件 students_scores.csv

StudentID,Name,Math,Science,English,History
S001,Alice,85,92,78,88
S002,Bob,90,88,92,85
S003,Charlie,72,65,80,70
S004,David,95,98,90,92
S005,Eve,60,70,65,75
S006,Frank,88,np.nan,85,90
S007,Grace,78,82,79,
S008,Alice,85,92,78,88

注意:

  • FrankScience 成绩缺失。
  • GraceHistory 成绩为空(将被 read_csv 读为 NaN)。
  • Alice 有两条重复记录。

5.2 加载数据

首先,创建这个 CSV 文件,然后用 Pandas 加载它。

# 创建示例 CSV 文件
students_csv_content = """StudentID,Name,Math,Science,English,History
S001,Alice,85,92,78,88
S002,Bob,90,88,92,85
S003,Charlie,72,65,80,70
S004,David,95,98,90,92
S005,Eve,60,70,65,75
S006,Frank,88,,85,90
S007,Grace,78,82,79,
S008,Alice,85,92,78,88
"""
with open('students_scores.csv', 'w') as f:f.write(students_csv_content)# 加载数据
students_df = pd.read_csv('students_scores.csv')
print("加载的学生分数 DataFrame:")
print(students_df)

5.3 查看数据基本信息

加载数据后,通常第一步是了解数据的概况。

print("\n--- 数据基本信息 ---")
# 查看前几行
print("\n前3行 (head(3)):")
print(students_df.head(3))# 查看后几行
print("\n后2行 (tail(2)):")
print(students_df.tail(2))# 查看 DataFrame 的简要信息
print("\nDataFrame 信息 (info()):")
students_df.info()
# 从 info() 输出可以看到:
# - 行数和列数
# - 每列的非空值数量 (可以发现 Science 和 History 有缺失)
# - 每列的数据类型 (Science 和 History 因为有空值可能被读为 float)# 查看数值列的描述性统计
print("\n数值列描述性统计 (describe()):")
print(students_df.describe())
# describe() 会给出 count, mean, std, min, 25%, 50%, 75%, max
# 对于非数值列,可以指定 include='object' 或 include='all'
print("\n所有列描述性统计 (describe(include='all')):")
print(students_df.describe(include='all'))
# 对于对象类型 (object) 或类别类型 (category) 的列,会给出 count, unique, top, freq

5.4 初步探索与清洗

接下来,进行一些初步的数据探索和简单的清洗。

(1) 处理缺失值
print("\n--- 处理缺失值 ---")
print("\n每列的缺失值数量:")
print(students_df.isnull().sum())# 假设我们决定用0填充 Science 的缺失值,用该科目的平均分填充 History 的缺失值
science_mean = students_df['Science'].mean()
print(f"\nScience 平均分 (忽略NaN): {science_mean}")
students_df['Science'].fillna(0, inplace=True) # 用0填充 Frank 的 Science
students_df['History'].fillna(students_df['History'].mean(), inplace=True) # 用平均分填充 Grace 的 Historyprint("\n填充缺失值后的 DataFrame (info()):")
students_df.info() # 再次查看,确认没有缺失值了
print("\n填充缺失值后的前几行:")
print(students_df.head())
(2) 处理重复值
print("\n--- 处理重复值 ---")
print("\n检测重复行:")
print(students_df.duplicated()) # 应该能看到最后一行 Alice 是重复的# 删除重复行,保留第一个出现的
students_df.drop_duplicates(inplace=True)
print("\n删除重复行后的 DataFrame:")
print(students_df)
(3) 简单数据查询
print("\n--- 简单数据查询 ---")
# 查询数学成绩大于90分的学生
math_gt_90 = students_df[students_df['Math'] > 90]
print("\n数学成绩大于 90 分的学生:")
print(math_gt_90)# 查询 Alice 的所有成绩
alice_scores = students_df[students_df['Name'] == 'Alice']
print("\nAlice 的成绩:")
print(alice_scores)# 查询数学和科学都大于85分的学生
high_achievers = students_df[(students_df['Math'] > 85) & (students_df['Science'] > 85)]
print("\n数学和科学都大于 85 分的学生:")
print(high_achievers)
(4) 计算新列
print("\n--- 计算新列 ---")
# 计算总分 (Math, Science, English, History)
subject_cols = ['Math', 'Science', 'English', 'History']
students_df['TotalScore'] = students_df[subject_cols].sum(axis=1)
# 计算平均分
students_df['AverageScore'] = students_df[subject_cols].mean(axis=1)print("\n添加了总分和平均分后的 DataFrame:")
print(students_df.head())

这个实践环节展示了如何将前面学到的知识点(加载数据、查看信息、处理缺失/重复值、条件选择、创建新列)串联起来,完成一个基本的数据探索和预处理流程。

六、总结

本篇文章详细介绍了 Python 数据处理库 Pandas 的核心功能和实际应用。通过学习,我们掌握了:

  1. 核心数据结构:

    • Series: 一维带标签数组,是构建 DataFrame 的基础。理解了其创建方式、常用属性和方法,以及灵活的索引机制。
    • DataFrame: 二维表格型数据结构,是 Pandas 中进行数据分析和处理的主力。学习了其多种创建途径、重要属性和方法,并重点掌握了基于标签 (.loc[]) 和基于位置 (.iloc[]) 的强大索引与切片能力。
  2. 数据读取与写入:

    • 掌握了使用 pd.read_csv() 从 CSV 文件读取数据,并了解了其常用参数以应对不同格式的 CSV 文件。
    • 学会了使用 df.to_csv() 将 DataFrame 写入 CSV 文件,并能控制是否包含索引、表头等。
    • 了解 Pandas 支持读取和写入多种其他数据格式,如 Excel、SQL 数据库等。
  3. 数据选择与过滤:

    • 熟练运用 .loc[].iloc[] 进行精确的行和列选择。
    • 掌握了如何根据单条件或组合条件 (&, |, ~,注意括号使用) 筛选 DataFrame 中的数据子集。
  4. 基本的数据清洗和转换操作:

    • 处理缺失值: 能够检测 (isnull())、填充 (fillna()) 和删除 (dropna()) 数据中的缺失值。
    • 处理重复值: 能够检测 (duplicated()) 和删除 (drop_duplicates()) 重复数据。
    • 数据类型转换: 能够使用 astype()pd.to_numeric() 转换列的数据类型。
    • 应用函数: 能够使用 apply(), map(), applymap() 对数据进行灵活的函数应用和转换。
  5. 实践应用:

    • 通过一个加载并探索表格数据集的实例,将所学知识点融会贯通,体验了从数据加载、信息查看、数据清洗到初步分析的完整流程。

Pandas 是数据科学和深度学习项目进行数据预处理不可或缺的工具。熟练掌握 Pandas,将为我们后续进行更复杂的数据分析、特征工程以及模型训练打下坚实的基础。希望大家通过本文的学习和实践,能够真正领会 Pandas 的强大之处,并将其灵活运用于未来的项目中。


相关文章:

【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

如何测试 esp-webrtc-solution_solutions_doorbell_demo 例程?

软件准备 esp-webrtc-solution/solutions/doorbell_demo 例程 此例程集成了 WebSocket 传输视频流的应用 硬件准备 ESP32P4-Function-Ev-Board 环境搭建 推荐基于 esp-idf v5.4.1 版本的环境来编译此例程 若编译时出现依赖的组件报错&#xff0c;可进行如下修改&#xff…...

default和delete final和override

1.default和delete default 1.生成默认成员函数 2.仅适用于特殊成员函数&#xff08;如构造函数、析构函数、拷贝/移动操作等&#xff09; delete 1.删除函数 2.可应用于任何函数&#xff08;不限于特殊成员函数&#xff09; 2.final 和override final 用于类&#xff1a;…...

Nvidia Orin 安装onnxruntime-gpu

在用英伟达边缘设备Nvidia Orin 安装onnxruntime-gpu环境时&#xff0c; 通常会遇到很多问题。 在正常的Nvidia 服务器上安装onnxruntime-gpu 是非常简单的&#xff0c; 直接pip install onnxruntime-gpu即可&#xff0c; 但是在边缘设备上就没有这么简单了。 直接pip install…...

C++ CRTP技术(奇异递归模版模式)

C 的CRTP技术 最近了解到C的CRTP技术&#xff0c;通过博客来这里记录一下。 我们首先可以了解一下什么是CRTP技术。CRTP是C的一种高级模版变成模式。 他主要的用途有以下的几点&#xff1a; 编译时实现多态&#xff08;静态多态&#xff09;&#xff1a;通过CRTP技术&#xf…...

验证es启动成功

1. 查看命令行输出信息 在启动 Elasticsearch 时&#xff0c;命令行窗口会输出一系列日志信息。若启动成功&#xff0c;日志里通常会有类似下面的信息&#xff1a; plaintext [2025-05-06T13:20:00,000][INFO ][o.e.n.Node ] [node_name] started其中 [node_na…...

AI工场全面激活电商创意链

在当今科技飞速发展的时代&#xff0c;北京先智先行科技有限公司凭借其卓越的创新能力&#xff0c;推出了“先知大模型”、“先行AI商学院”以及“先知AIGC超级工场”这三款旗舰产品&#xff0c;在市场上掀起了不小的波澜。  传统电商设计流程&#xff0c;从需求确认到营销策…...

数 学 函数

gcd int gcd(int a,int b){while(a%b){int ca%b;ab;bc;}return b; } 错位排列 typedef long long ll; ll d(int n){if(n1) return 0;if(n2) return 1;return (n-1)*(d(n-1)d(n-2)); } 快速幂 //注意看是否有mod的需求 int q_pow(int a,int b){int ans1,tempa;while(b){if(…...

springboot集成langchain4j记忆对话

流式输出 LLM 一次生成一个标记&#xff08;token&#xff09;&#xff0c;因此许多 LLM 提供商提供了一种方式&#xff0c;可以逐个标记地流式传输响应&#xff0c;而不是等待整个文本生成完毕。 这显著改善了用户体验&#xff0c;因为用户不需要等待未知的时间&#xff0c;几…...

C语言初阶:数组

目录 0.数组要讲的知识点 1.一维数组的创建和初始化 1.1 数组的创建&#xff1a; 1.2数组实例&#xff1a; 1.3 数组的初识化&#xff1a; 例子&#xff1a; 2.一维数组的使用 例子&#xff1a; 总结&#xff1a; 3.一维数组在内存中的存储 4.二维数组的创建和初始化 4.…...

案例分享 | 攻克ADAS开发测试难题,实现单元动态测试新突破

汽车行业中的代码动态测试&#xff1a;守护智能汽车的安全与质量 在当今汽车行业&#xff0c;智能网联汽车的快速发展让软件成为了汽车的核心竞争力之一。从自动驾驶辅助系统到车载信息娱乐系统&#xff0c;汽车中的软件数量和复杂度都在不断增加。然而&#xff0c;软件的复杂…...

K8S 基于本地存储的持久卷

假设有如下三个节点的 K8S 集群&#xff1a; ​ k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、背景分析 阅读本文&#xff0c;默认您有 PV-PVC、hostPath 相关知识。 由于安全方面的考虑&#xff0c;K8S 官方并不推荐 hostPath …...

LED实验

目录 1.LED介绍 1.1LED原理图&#xff1a; 2.单片机运行代码的流程 3.进制的转换 4.C51数据类型 5.小编的单片机型号&#xff1a;STC89C52RC/LE52RC&#xff0c;最高波特率&#xff1a;9600 6.点亮一个LED 代码 步骤 代码&#xff1a; 7.LED闪烁 在STC内操作&#x…...

python+pytest接口自动化测试--日志记录

前言:代码可以直接复制使用 解决问题: 问题1:日志重复记录的问题,比如运行一个模块日志会记录很多遍(通过handlers是否存在解决的) 问题2:运行测试用例进行多个模块相互调用.日志记录不全的问题(通过共享公共的handlers解决问题) 首先写一个日志记录的工具 # 这个是个日志的…...

Android 蓝牙开发调试总结

Android 蓝牙开发调试总结 文章目录 Android 蓝牙开发调试总结一、前言二、蓝牙开发1、开关和连接控制2、相关日志3、相关广播4、demo示例 三、其他1、Android 蓝牙开发调试小结2、Android14 蓝牙启动流程3、Android14 蓝牙 BluetoothService 启动和相关代码介绍4、Android13 蓝…...

混淆矩阵(Confusion Matrix)

混淆矩阵&#xff08;Confusion Matrix&#xff09;是一个用于评估分类模型性能的工具&#xff0c;特别是在机器学习和统计学领域。它展示了模型预测结果与实际结果之间的关系。混淆矩阵通常用于二分类或多分类问题中&#xff0c;但也可以扩展到更多类别的情况。 一、混淆矩阵…...

C语言——操作符

一.操作符的分类 算术操作符&#xff1a; - * / %移位操作符&#xff1a;<< >>位操作符: & | ^赋值操作符: - * / % > & | ^单⽬操作符&#xff1a; &#xff01; -- & * - ~ sizeof …...

大数据处理利器:Hadoop 入门指南

一、Hadoop 是什么&#xff1f;—— 分布式计算的基石 在大数据时代&#xff0c;处理海量数据需要强大的技术支撑&#xff0c;Hadoop 应运而生。Apache Hadoop 是一个开源的分布式计算框架&#xff0c;致力于为大规模数据集提供可靠、可扩展的分布式处理能力。其核心设计理念是…...

追踪大型语言模型的思想(上)(来自针对Claude的分析)

概述 像 Claude 这样的语言模型并非由人类直接编程&#xff0c;而是通过大量数据进行训练。在训练过程中&#xff0c;它们会学习解决问题的策略。这些策略被编码在模型为每个单词执行的数十亿次计算中。对于我们这些模型开发者来说&#xff0c;这些策略是难以捉摸的。这意…...

系统 Python 与 Conda 环境的灵活切换

在现代 Python 开发中,经常需要在系统 Python 和 Conda 环境中的 Python 之间切换。无论是处理不同项目的依赖冲突,还是测试代码在不同 Python 版本下的兼容性,灵活切换 Python 环境都是开发者的必备技能。本文将详细介绍如何实现 Python 环境的灵活切换,并提供 Conda 命令…...

【HTTP】《HTTP 全原理解析:从请求到响应的奇妙之旅》

文章目录 一、HTTP 协议1.1、HTTP 是什么1.2、理解 "应用层协议"1.3、理解 HTTP 协议的工作过程1.4、HTTP协议格式1.5、协议格式总结 二、HTTP 请求1.1、认识 URL1.1.1、URL 基本格式1.1.2、关于 URL encode 1.2、认识 "方法"1.2.1 、GET 方法1.2.2、 POST…...

重生之我在2024学Fine-tuning

一、Fine-tuning&#xff08;微调&#xff09;概述 Fine-tuning&#xff08;微调&#xff09;是机器学习和深度学习中的一个重要概念&#xff0c;特别是在预训练模型的应用上。它指的是在模型已经通过大量数据训练得到一个通用的预训练模型后&#xff0c;再针对特定的任务或数据…...

若依前后端分离项目中可以删除哪些原若依有的?

在若依&#xff08;RuoYi&#xff09;前后端分离项目中完成二次开发后&#xff0c;可以删除以下未使用的模块和文件以简化项目结构。以下分模块和风险点说明&#xff1a; --- ### **一、后端&#xff08;Spring Boot&#xff09;可删除内容** #### 1. **未使用的功能模块** …...

element-plus中,vue3项目,el-input密码框禁止浏览器自动弹出浏览器历史密码提示框

原代码&#xff08;密码框是text框&#xff09;&#xff1a; <el-form-item label"用户名" :label-width"formLabelWidth" v-if"!localOrhuawei" prop"userName"><el-input v-model"formDialog.userName" />&l…...

二叉树的遍历与构造

唉&#xff0c;好想回家&#xff0c;我想回家跟馒头酱玩&#xff0c;想老爸老妈。如果上天再给我一次选择的机会&#xff0c;我会选择当一只小动物&#xff0c;或者当棵大树也好&#xff0c;或者我希望自己不要有那么多多余的情绪&#xff0c;不要太被别人影响&#xff0c;开心…...

「Mac畅玩AIGC与多模态23」开发篇19 - Markdown 富文本输出工作流示例

一、概述 本篇基于格式化文本整合的经验&#xff0c;进一步介绍如何通过 LLM 输出标准 Markdown 内容&#xff0c;并在前端正确渲染出标题、列表、加粗等富文本格式&#xff0c;提升展示效果与内容结构可读性。 二、环境准备 macOS 系统Dify 平台已部署并可访问 三、在 Dif…...

记录学习《手动学习深度学习》这本书的笔记(十)

因为最近在做《语音与语言理解综合处理》的实验&#xff0c;所以打算先看第14章&#xff1a;自然语言处理&#xff1a;预训练和第15章&#xff1a;自然语言处理&#xff1a;应用&#xff0c;之后再来看第13章&#xff1a;计算机视觉。 第十四章&#xff1a;自然语言处理&#…...

Flowable7.x学习笔记(二十一)查看我的发起

前言 “查看我的发起”功能&#xff0c;就是将当前用户作为流程发起人启动的所有流程实例集中展示&#xff0c;帮助用户随时跟踪自己提交的业务请求的状态与历史&#xff0c;提升透明度与可控性。 业务人员通常不知道流程引擎底层如何运转&#xff0c;只关心“我提交的报销/申请…...

【Bootstrap V4系列】学习入门教程之 组件-折叠(Collapse)

Bootstrap V4系列 学习入门教程之 组件-折叠&#xff08;Collapse&#xff09; 折叠&#xff08;Collapse&#xff09;How it works一、Example二、Horizontal 水平的三、Multiple targets 多个目标四、Accordion example 手风琴示例 折叠&#xff08;Collapse&#xff09; 通…...

ROS1和ROS2使用桥接工具通信

前提&#xff1a;主从机在同一局域网内&#xff0c;可以互相ping通 我的两个设备其中一个无法连接wifi,ubuntu老生常谈的问题.....&#xff0c;获得新的技能&#xff1a;手机蓝牙提供网络&#xff0c;两个设备连接手机蓝牙就可以连接网络并且处于同一个局域网内。 我的主机为…...

尤雨溪宣布:Vue 生态正式引入 AI

在前端开发领域,Vue 框架一直以其易用性和灵活性受到广大开发者的喜爱。 而如今,Vue 生态在人工智能(AI)领域的应用上又迈出了重要的一步。 尤雨溪近日宣布,Vue、Vite 和 Rolldown 的文档网站均已添加了llms.txt文件,这一举措旨在让大型语言模型(LLM)更方便地理解这些…...

分布式id的两大门派!时钟回拨问题的解决方案!

2.1 两大门派 目前业界的分布式ID实现路径归结起来有两派&#xff1a;一派以雪花算法为代表&#xff0c;不强依赖DB能力&#xff0c;只使用分布式节点自身信息&#xff08;时间戳节点ID序列号&#xff09;的编码生成唯一序列&#xff0c;好处是去中心化、无单点风险&#xff1…...

QMK键盘固件配置详解

QMK键盘固件配置详解 前言 大家好&#xff01;今天给大家带来QMK键盘固件配置的详细指南。如果你正在DIY机械键盘或者想要给自己的键盘刷固件&#xff0c;这篇文章绝对不容错过。QMK是目前最流行的开源键盘固件框架之一&#xff0c;它允许我们对键盘进行高度自定义。接下来&a…...

Jenkins 服务器上安装 Git

安装 Git # 更新包列表 sudo apt update# 安装 Git sudo apt install git 验证安装 # 检查 Git 版本 git --version 查看所有全局配置 git config --global --list 查看特定配置项 # 查看用户名配置 git config --global user.name# 查看邮箱配置 git config --global u…...

自由浮动时间和总浮动时间对比

一、自由浮动时间的定义 在项目进度管理中&#xff0c;自由浮动时间&#xff08;Free Float&#xff09;是指在不推迟项目后续任务最早开始时间的前提下&#xff0c;一个任务能够延迟的时间长度。它是针对单个任务而言的&#xff0c;主要考虑该任务与其紧后任务之间的关系。 …...

2025.05.07-华为机考第二题200分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. 社区智能安防系统设计 问题描述 随着智慧社区建设的发展,LYA小区需要设计一套高效的安防监控系统。该小区布局可以用一棵二叉树来表示,树的每个节点代表一户居民家庭。 为了…...

分布式架构详解

一、分布式架构的概念与设计目标 1. 基本概念 分布式架构&#xff08;Distributed Architecture&#xff09;是分布式计算技术的应用和工具,指将一个复杂系统拆分为多个独立的组件&#xff08;或服务&#xff09;&#xff0c;并将这些组件部署在不同物理节点&#xff08;服务…...

码蹄集——平方根X、整除幸运数

目录 MT1075 平方根X MT1078 整除幸运数 MT1075 平方根X 知识点&#xff1a; 上取整&#xff1a;ceil&#xff1b;下取整&#xff1a;floor&#xff1b;四舍五入&#xff1a;round 判断是否为完全平方数的方法&#xff1a;利用sqrt函数结果为double&#xff0c;将其结果相乘&a…...

【MATLAB源码-第277期】基于matlab的AF中继系统仿真,AF和直传误码率对比、不同中继位置误码率对比、信道容量、中继功率分配以及终端概率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 在AF&#xff08;放大转发&#xff09;中继通信系统中&#xff0c;信号的传输质量和效率受到多个因素的影响&#xff0c;理解这些因素对于系统的优化至关重要。AF中继通信的基本架构由发射端、中继节点和接收端组成。发射端负…...

ACE-Step - 20秒生成4分钟完整歌曲,音乐界的Stable Diffusion,支持50系显卡 本地一键整合包下载

ACE-Step 是由ACE Studio与StepFun联合开发的音乐生成模型&#xff0c;被誉为“音乐界的Stable Diffusion”。该模型以其惊人的生成速度和多样化功能引发行业热议&#xff0c;支持19种语言&#xff0c;可在短短20秒内生成一首长达4分钟的完整音乐作品&#xff0c;效率比主流模型…...

007 Linux 开发工具(上)—— vim、解放sudo、gc+

&#x1f984; 个人主页: 小米里的大麦-CSDN博客 &#x1f38f; 所属专栏: Linux_小米里的大麦的博客-CSDN博客 &#x1f381; GitHub主页: 小米里的大麦的 GitHub ⚙️ 操作环境: Visual Studio 2022 文章目录 Linux 开发工具&#xff08;上&#xff09;Linux 编辑器 —— vim…...

React学习路线图-Gemini版

前端开发学习路线图 (针对编程新手&#xff0c;主攻 React 框架) 总原则&#xff1a;先打好地基&#xff0c;再盖楼。 无论学习哪个框架&#xff0c;扎实的 HTML、CSS 和 JavaScript 基础是成功的关键。React 是基于 JavaScript 构建的&#xff0c;所以深入理解 JS 至关重要。…...

注意力(Attention)机制详解(附代码)

Attention机制是深度学习中的一种技术&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;和计算机视觉领域中得到了广泛的应用。它的核心思想是模仿人类的注意力机制&#xff0c;即人类在处理信息时会集中注意力在某些关键部分上&#xff0c;而忽略其他不那么重要的…...

国内外Agent产品进展汇总

MCP&#xff08;Model Context Protocol&#xff09;是一个开放标准协议&#xff0c;旨在标准化应用程序向大型语言模型提供上下文信息的方式。通过集成MCP扩展&#xff0c;Agent可以访问和利用各种外部工具和服务&#xff0c;丰富了Agent的功能范围&#xff0c;使其能够执行更…...

AI Workflow

AI Workflow&#xff08;人工智能工作流&#xff09;指的是在构建、部署和管理AI模型与应用时所涉及的一系列步骤和流程。它将数据处理、模型训练、评估、部署及监控等环节有机结合起来&#xff0c;以实现高效、可重复的AI解决方案开发过程。以下是对AI Workflow核心组成部分及…...

MySQL OCP 认证限时免费活动​ 7 月 31 日 前截止!!!

为庆祝 MySQL 数据库发布 30 周年&#xff0c;Oracle 官方推出限时福利&#xff1a;2025 年 4 月 20 日至 7 月 31 日期间&#xff0c;所有人均可免费报考 MySQL OCP&#xff08;Oracle Certified Professional&#xff09;认证考试。该认证验证持证者在 MySQL 数据库管理、优化…...

【无标题】MPC软件

MPC软件是一款先进的多变量预测控制解决方案 专为复杂工业过程优化设计 **核心功能** 实时动态建模 多变量协调控制 滚动时域优化 自适应调整策略 干扰抑制 鲁棒性强 适用于时变系统 **技术优势** 基于模型预测算法 提前计算最优控制序列 处理输入输出约束 保障系…...

【EasyPan】loadDataList方法及checkRootFilePid方法解析

【EasyPan】项目常见问题解答&#xff08;自用&持续更新中…&#xff09;汇总版 一、loadDataList方法概览 /*** 文件列表加载接口* param session HTTP会话对象* param shareId 必须参数&#xff0c;分享ID&#xff08;使用VerifyParam进行非空校验&#xff09;* param …...

Java程序题案例分析

目录 一、基础语法 1. 类与对象 2. 接口与抽象类 二、面向对象语法 1. 继承与多态 2. 四种访问修饰符 三、设计模式相关语法 一、策略模式&#xff08;接口回调实现&#xff09; 1. 完整实现与解析 二、工厂模式&#xff08;静态工厂方法实现&#xff09; 1. 完整实…...

【Lanqiao】数位翻转

题目&#xff1a; 思路&#xff1a; 写蓝桥不能不写dp&#xff0c;就像.... 题目数据给的不大&#xff0c;所以我们可以考虑一种 n*m 的做法&#xff0c;那么对于这种题目可以想到的是用dp来写&#xff0c;但是如何构造转移方程与状态是个难事 由于这题对于任意一个数我们有两…...