Python Pandas超详

72 阅读26分钟

pandas

Pandas是一个开源的Python库,广泛应用于数据处理和数据分析。它提供了高性能、易于使用的数据结构和数据分析工具。以下是Pandas的一些主要用途:

  1. 数据清洗:Pandas提供了一系列功能来清理数据集,包括缺失数据的处理、重复记录的删除、错误值的修正等。
  2. 数据整理:可以轻松地对数据进行转换操作,比如数据类型的转换、字符串操作、日期时间格式的数据处理等。
  3. 数据分析:Pandas支持大量的数据操作类似SQL的功能,如合并(join、merge)、分组(group by)、聚合(aggregate)、透视表(pivot tables)等,使得数据分析变得更加简单。
  4. 数据可视化:虽然Pandas主要用于数据处理,但它也可以与Matplotlib、Seaborn等绘图库结合使用,直接从DataFrame或Series对象生成图表,简化了数据可视化的流程。
  5. 导入/导出数据:Pandas支持从多种格式读取数据(如CSV、Excel、SQL数据库、JSON等),并且可以将处理后的数据写入这些格式,便于数据交换和报告生成。
  6. 高效性能:Pandas的设计考虑了性能因素,其底层采用C或Cython编写,确保在处理大规模数据集时依然保持高效的执行速度。

总之,Pandas是数据科学家和分析师用来处理复杂数据任务的一个强大工具,无论是进行初步的数据探索还是构建复杂的分析模型,Pandas都提供了灵活而强大的支持


Series

在 Pandas 中,Series 是一种一维的带有标签数组的数据结构

它可以存储任何类型的数据(整数、字符串、浮点数、Python 对象等),并且每个元素都有一个对应的索引标签

Series 可以被视为一个固定大小的字典,其中键是索引标签,值是数据

一维性:Series 是一维的数据结构,这意味着它只能保存单列或多行数据。

索引标签:每个元素都有一个与之关联的索引标签,默认是从 0 开始的整数序列,但也可以自定义为其他类型的标签(如字符串)。

同质性:虽然 Series 可以包含不同类型的数据,但它通常用于存储相同类型的数据,类似于 Python 列表或 NumPy 数组。

基于 NumPy:Pandas 的 Series 建立在 NumPy 的基础上,因此支持许多快速的数值运算和操作

# 默认索引从0开始
s = pd.Series([1, 2, 3, 4])
"""
0    1
1    2
2    3
3    4
dtype: int64
"""

# 自定义索引
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']) 
"""
a    1
b    2
c    3
d    4
dtype: int64
"""

# 字典的key做索引
s = {'a': 1, 'b': 2, 'c': 3}
"""
a    1
b    2
c    3
dtype: int64
"""

# 统一value
s = pd.Series(5, index=['a', 'b', 'c'])
"""
a    5
b    5
c    5
dtype: int64
"""

访问和修改数据

访问数据
  • 使用索引标签访问特定元素:
print(s['a'])  # 输出: 5
  • 使用位置访问:
print(s[0])  # 输出: 5
修改数据
  • 直接赋值修改特定元素:
s['a'] = 10
print(s)
a    10
b     5
c     5
dtype: int64

常见操作

基本统计计算
s = pd.Series([1, 2, 3, 4])
print("Sum:", s.sum())        # 求和
print("Mean:", s.mean())      # 平均值
print("Max:", s.max())        # 最大值
print("Min:", s.min())        # 最小值
条件选择
print(s[s > 2])  # 选择大于2的元素
应用函数
print(s.apply(lambda x: x * 2))  # 将每个元素乘以2

DataFrame 是由多个 Series 组成的二维表格型数据结构。每个列都是一个 Series。

你可以将 Series 视为 DataFrame 的一列,反之亦然,可以轻松地从 DataFrame 中提取出某一列作为 Series

DataFrame

DataFrame,这是pandas的核心数据结构,它被设计用来处理表格型的数据

DataFrame 可以被视为是一个二维的、大小可变的表格,包含一组有序的列,每列可以是不同的值类型(如数值、字符串、布尔值等)

它不仅提供了对数据进行排序、过滤、聚合等多种操作的方法,还允许执行更为复杂的数据分析任务。

二维标签:DataFrame 支持行和列的双向标签系统。行标签通常被称为“索引”,而列标签就是列名。

异构数据:每一列的数据类型可以不同,这使得 DataFrame 非常适合处理真实世界中多样的数据集。

大小可变:可以在已有 DataFrame 的基础上添加或删除行或列。

灵活操作:支持各种数据操作,包括切片、选择、过滤、分组、合并等。

数据对齐:自动进行数据对齐,这意味着在运算过程中,Pandas 会自动根据行或列的标签对齐数据,而不是依赖位置。

在这个例子中,我们将创建一个包含学生名字和他们对应年龄的数据表

import pandas as pd
# 创建数据字典
data = {'Name': ['Tom', 'nick', 'krish', 'jack'],
        'Age': [20, 21, 19, 18]}

# 使用数据字典创建DataFrame
df = pd.DataFrame(data)

# 打印DataFrame
print(df)

如下结果

    Name  Age
0    Tom   20
1   nick   21
2  krish   19
3   jack   18

使用Pandas进行数据筛选、分组和聚合

import pandas as pd

# 创建一个更丰富的数据字典
data = {'Name': ['Tom', 'Nick', 'Krish', 'Jack', 'Alex', 'Jill'],
        'Age': [20, 21, 19, 18, 20, 22],
        'Gender': ['Male', 'Male', 'Male', 'Female', 'Female', 'Female']}

df = pd.DataFrame(data)
print("Original DataFrame:")
  • 筛选:筛选出所有年龄大于等于20岁的学生
older_students = df[df['Age'] >= 20]
print("\nStudents aged 20 or older:")
print(older_students)
Students aged 20 or older:
   Name  Age  Gender
0   Tom   20    Male
1  Nick   21    Male
4  Alex   20  Female
5  Jill   22  Female
  • 分组,聚合:按性别对数据进行分组,并计算每个性别的平均年龄
# 按性别分组并计算每组的平均年龄
gender_age_mean = df.groupby('Gender')['Age'].mean() # 平均函数
print("\nAverage age by gender:")
print(gender_age_mean)
Average age by gender:
Gender
Female    20.0
Male      20.0
Name: Age, dtype: float64

初始化

CSV 文件

CSV(逗号分隔值)是最常见的数据存储格式之一。Pandas 提供了 read_csv() 方法来读取 CSV 文件。

import pandas as pd

# 读取 CSV 文件
df = pd.read_csv('data.csv')

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

Excel文件

Excel 文件通常用于存储表格数据。Pandas 使用 read_excel() 方法读取 Excel 文件

# 读取 Excel 文件
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

JSON文件

JSON 格式常用于存储结构化数据。Pandas 提供了 read_json() 方法来读取 JSON 文件

# 读取 JSON 文件
df = pd.read_json('data.json')

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

SQL数据库

Pandas 可以通过 SQLAlchemy 或原生的数据库连接读取 SQL 数据库中的数据

import pandas as pd
import sqlite3

# 创建 SQLite 连接
conn = sqlite3.connect('example.db')

# 查询 SQL 数据并加载到 DataFrame
query = "SELECT * FROM users"
df = pd.read_sql_query(query, conn)

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

HTML表格

HTML 表格可以嵌入在网页中,Pandas 提供了 read_html() 方法来解析 HTML 表格

# 读取 HTML 表格
url = 'https://example.com/table.html'
tables = pd.read_html(url)

# 假设页面中有多个表格,选择第一个表格
df = tables[0]

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

HDF5文件

HDF5 是一种用于存储大规模科学数据的格式。Pandas 提供了 read_hdf() 方法读取 HDF5 文件

# 读取 HDF5 文件
df = pd.read_hdf('data.h5', key='table')

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

Parquet文件

Parquet 是一种高效的列式存储格式,适合大数据分析。Pandas 提供了 read_parquet() 方法读取 Parquet 文件

# 读取 Parquet 文件
df = pd.read_parquet('data.parquet')

# 打印前几行
print(df.head())

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()
print("\nNumPy array from DataFrame:")
print(numpy_array)

结合NumPy

NumPy 和 Pandas 的结合可以实现更复杂的数值计算。例如:

  • 将 NumPy 数组转换为 DataFrame
import numpy as np
import pandas as pd

# 创建一个 NumPy 数组
numpy_array = np.random.rand(5, 3)  # 5行3列的随机数组

# 将 NumPy 数组转换为 DataFrame
df = pd.DataFrame(numpy_array, columns=['A', 'B', 'C'])
print(df)
  • 对 DataFrame 进行 NumPy 风格的操作
# 计算每列的均值
mean_values = df.mean()  # Pandas 方法
print("Mean values using Pandas:", mean_values)

# 使用 NumPy 直接计算均值
mean_values_numpy = np.mean(df.to_numpy(), axis=0)
print("Mean values using NumPy:", mean_values_numpy)
  • 利用 NumPy 进行矩阵运算
# 对 DataFrame 的数值进行矩阵乘法
matrix = np.array([[1, 2], [3, 4]])
result = np.dot(df.to_numpy()[:, :2], matrix)  # 仅取前两列进行矩阵乘法
print("Matrix multiplication result:")
print(result)

总结

  • Pandas 支持从多种文件格式(如 CSV、Excel、JSON、SQL、HTML 等)读取数据并生成 DataFrame。
  • 通过 .to_numpy() 方法,可以轻松地将 DataFrame 转换为 NumPy 数组,从而利用 NumPy 的高效计算能力。

查看数据

查看开头 DataFrame.head()

不提供参数,它将默认显示前 5 行

DataFrame.head(n=5) # 返回 DataFrame 的前 n 行

查看结尾 DataFrame.tail()

DataFrame.tail(n=5) # 默认显示最后 5 行

例子

import pandas as pd

# 创建一个示例 DataFrame
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Hugo'],
    'Age': [25, 30, 35, 40, 45, 50, 55, 60],
    'Department': ['HR', 'RD', 'Sales', 'Marketing', 'HR', 'RD', 'Sales', 'Marketing']
}

df = pd.DataFrame(data)

print("Original DataFrame:")
print(df)
      Name  Age Department
0    Alice   25         HR
1      Bob   30         RD
2  Charlie   35      Sales
3    David   40  Marketing
4      Eve   45         HR
5    Frank   50         RD
6    Grace   55      Sales
7     Hugo   60  Marketing
# 显示前3行
print("\nFirst 3 rows of the DataFrame:")
print(df.head(3))
First 3 rows of the DataFrame:
      Name  Age Department
0    Alice   25         HR
1      Bob   30         RD
2  Charlie   35      Sales
# 显示最后3行
print("\nLast 3 rows of the DataFrame:")
print(df.tail(3))
Last 3 rows of the DataFrame:
   Name  Age Department
5 Frank   50         RD
6 Grace   55      Sales
7  Hugo   60  Marketing

获取统计摘要

DataFrame.describe() 是 Pandas 中的一个非常有用的方法,它提供了对 DataFrame 数值列的基本统计摘要

这个方法能够快速生成数据的描述性统计信息,帮助你了解数据的分布和基本特征,是数据分析中探索性数据分析(EDA)阶段的重要工具。

describe() 方法的主要功能

  • 计数(count):非空值的数量。
  • 平均值(mean):数值列的平均值。
  • 标准差(std):数值列的标准差,衡量数据的离散程度。
  • 最小值(min):数值列中的最小值。
  • 四分位数(25%,50%,75%):分别对应下四分位数、中位数和上四分位数。这些值将数据分为四个等分,有助于理解数据的分布情况。
  • 最大值(max):数值列中的最大值

包含学生成绩信息的 DataFrame

import pandas as pd

# 创建一个示例 DataFrame
data = {
    'Math': [90, 80, 75, 95, 85],
    'English': [88, 82, 90, 75, 85],
    'History': [70, 72, 68, 79, 75]
}

df = pd.DataFrame(data)

print("Original DataFrame:")
print(df)
   Math  English  History
0    90       88       70
1    80       82       72
2    75       90       68
3    95       75       79
4    85       85       75

调用 .describe() 方法来查看每列的基本统计信息

print("\nDescriptive statistics:")
print(df.describe())
Descriptive statistics:
            Math   English   History
count   5.000000   5.00000   5.00000
mean   85.000000  84.00000  72.80000
std     7.905694   5.87367   4.32435
min    75.000000  75.00000  68.00000
25%    80.000000  82.00000  70.00000
50%    85.000000  85.00000  72.00000
75%    90.000000  88.00000  75.00000
max    95.000000  90.00000  79.00000

对于每一列('Math', 'English', 'History'),describe() 提供了包括计数、平均值、标准差、最小值、四分位数以及最大值在内的统计数据

四分位数(Quartiles)是统计学中的一个概念,用于描述数据集的分布情况

它们将数据集分成四个等份,每个部分包含大约25%的数据点。四分位数有助于了解数据的中心趋势和离散程度,并且是识别异常值的重要工具

四分位数的定义

  1. 第一四分位数(Q1 或 25th 百分位数):数据集中最小的25%数值位于此处之下,也就是说,它是使得至少25%的数据小于或等于它的最大值
  2. 第二四分位数(Q2 或 50th 百分位数,即中位数):数据集的中间值,将数据集分为上下两半。一半的数据小于这个值,另一半大于这个值
  3. 第三四分位数(Q3 或 75th 百分位数):数据集中最大的25%数值位于此处之下,意味着至少有75%的数据小于或等于它

对于非数值列,默认情况下,describe() 只对数值列进行计算。如果 DataFrame 包含非数值列(如字符串或布尔值),你可以通过设置参数 include=['object']include='all' 来包括这些列的描述性统计(例如,不同值的数量、最频繁出现的值及其出现次数等)

# 假设有一列包含类别数据
df['Grade'] = ['A', 'B', 'B', 'A', 'B']

print(df.describe(include=['object']))

行索引

获取索引 .index

DataFrame.index 属性用于获取或设置 DataFrame 的行标签(即索引)

默认情况下,这些是整数从 0 开始的序列,但它们也可以被设置为其他类型的值,如日期时间、字符串或其他自定义值

(一些数据定义的方式可以竖着看更好理解)

import pandas as pd

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

print("Index:", df.index)

没有特别指定,输出将是默认的整数索引:RangeIndex(start=0, stop=3, step=1)


创建 DataFrame 时指定了 .index,可以为你的数据行赋予有意义的标签,而不是使用默认的整数索引

这可以极大地提高数据的可读性和易用性,特别是在处理时间序列数据或任何需要通过特定标识符来访问行的数据集时

设置索引 .set_index

可以在创建 DataFrame 时直接通过 index 参数指定行索引

import pandas as pd

data = {'A': [1, 2, 3],
        'B': [4, 5, 6]}

df = pd.DataFrame(data, index=['row1', 'row2', 'row3'])
print(df)
      A  B
row1  1  4
row2  2  5
row3  3  6

或者使用set_index对已有列设置索引

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40],
    'Department': ['HR', 'RD', 'Sales', 'Marketing']
}

df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)

df.set_index('Name', inplace=True) # inplace=True 表示直接在原 DataFrame 上进行修改
print("\nDataFrame with 'Name' as index:")
print(df)
Original DataFrame:
      Name  Age Department
0    Alice   25         HR
1      Bob   30         RD
2  Charlie   35      Sales
3    David   40  Marketing

DataFrame with 'Name' as index:
         Age Department
Name                   
Alice     25         HR
Bob       30         RD
Charlie   35      Sales
David     40  Marketing

重置索引 .reset_index

如果你需要恢复默认的整数索引,可以使用 reset_index() 方法

df.reset_index(inplace=True)

修改索引 .index

通过直接赋值给 .index 属性来修改它的索引

df.index = ['newRow1', 'newRow2', 'newRow3']
print(df)
         A  B
newRow1  1  4
newRow2  2  5
newRow3  3  6

日期时间作为索引

对于时间序列数据,通常会使用日期时间对象作为索引

Pandas 提供了方便的方法来生成日期范围,并将其作为索引

dates = pd.date_range('20250301', periods=3) # 从2025年3月1日开始的3个连续日期
df = pd.DataFrame(data, index=dates)
print(df)
            A  B
2025-03-01  1  4
2025-03-02  2  5
2025-03-03  3  6

列名

DataFrame.columns 属性用于获取或设置 DataFrame 的列名

可以通过这个属性查看当前列名或者修改它们

获取列名 .columns

import pandas as pd

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

print("Columns:", df.columns)
Columns: Index(['A', 'B'], dtype='object')

修改列名 .columns

import pandas as pd

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

df.columns = ['Col1', 'Col2']
print(df)
   Col1  Col2
0     1     4
1     2     5
2     3     6

转换numpy数据

DataFrame.to_numpy() 是 Pandas 中用于将 DataFrame 转换为 NumPy 数组的方法

这个功能非常有用,尤其是在你需要利用 NumPy 提供的高效计算能力或与其他需要 NumPy 数组作为输入的库进行交互时

  • 转换数据结构:将 Pandas DataFrame 转换为 NumPy 数组,便于使用 NumPy 的各种数学运算和操作
  • 性能优化:对于某些数值计算任务,NumPy 数组可能提供比 Pandas DataFrame 更高效的执行速度
  • 兼容性:许多科学计算和机器学习库(如 SciPy、scikit-learn)都是基于 NumPy 构建的,因此它们通常接受 NumPy 数组作为输入

假设我们有一个简单的 DataFrame

import pandas as pd

# 创建一个示例 DataFrame
data = {
    'A': [1, 2, 3],
    'B': [4, 5, 6]
}

df = pd.DataFrame(data)

print("Original DataFrame:")
print(df)
   A  B
0  1  4
1  2  5
2  3  6

通过调用 .to_numpy() 方法将 DataFrame 转换为 NumPy 数组

# 将 DataFrame 转换为 NumPy 数组
numpy_array = df.to_numpy()

print("\nConverted NumPy array:")
print(numpy_array)
[[1 4]
 [2 5]
 [3 6]]

注意

  • 数据类型:在转换过程中需要注意的是,如果 DataFrame 包含混合数据类型(例如整数和字符串),生成的 NumPy 数组的数据类型将会是能够容纳所有这些类型的最宽泛类型(通常是 object 类型)
  • 索引和列信息丢失:转换为 NumPy 数组后,原始 DataFrame 的行和列标签(即索引和列名)将不会被保留

排序

sort_index()

sort_index() 方法用于根据 DataFrame 的行索引或列名进行排序,默认情况下是对行索引进行升序排序

DataFrame.sort_index(axis=0, ascending=True, inplace=False, ...)
"""
axis:指定排序的方向。默认值为 0,表示按行索引排序;如果设置为 1,则表示按列名排序。
ascending:布尔值,决定是升序还是降序排列。默认为 True(升序)。
inplace:如果设置为 True,则直接在原 DataFrame 上进行修改;否则返回一个新的 DataFrame
"""
import pandas as pd

data = {'A': [3, 2, 1], 'B': [6, 5, 4]}
df = pd.DataFrame(data, index=['c', 'b', 'a'])
print("Original DataFrame:")
print(df)

# 按索引升序排序
sorted_df = df.sort_index()
print("\nDataFrame after sorting by index in ascending order:")
print(sorted_df)

输出结果

Original DataFrame:
   A  B
c  3  6
b  2  5
a  1  4

DataFrame after sorting by index in ascending order:
   A  B
a  1  4
b  2  5
c  3  6

当你在 DataFrame.sort_index() 方法中设置 axis=1 时,这意味着你希望按照列名(即 DataFrame 的列标签)而不是行索引来进行排序,这在你需要根据字母顺序或其他自定义顺序对列进行重新排列时特别有用

假设我们有一个包含多个列的 DataFrame,并且我们想要根据列名的字母顺序对其进行排序

下面是如何使用 sort_index(axis=1) 来实现这一点的具体示例

import pandas as pd

data = {
    'Beta': [3, 6, 9],
    'Alpha': [1, 4, 7],
    'Gamma': [2, 5, 8]
}

df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
Original DataFrame:
   Beta  Alpha  Gamma
0     3      1      2
1     6      4      5
2     9      7      8

在这个例子中,列的顺序是 'Beta', 'Alpha', 'Gamma'

接下来,我们将使用 sort_index(axis=1) 按照列名的字母顺序对 DataFrame 进行排序

# 按列名升序排序
sorted_columns_df = df.sort_index(axis=1)
print("\nDataFrame after sorting by column names in ascending order:")
print(sorted_columns_df)
DataFrame after sorting by column names in ascending order:
   Alpha  Beta  Gamma
0      1     3      2
1      4     6      5
2      7     9      8

sort_values()

sort_values() 方法允许你根据一个或多个列的具体数值来对 DataFrame 进行排序

DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, ...)
"""
by:可以是一个字符串(单列名称)或一个列表(多列名称),指定了要根据哪些列的值进行排序
axis:同上,但通常保持默认值 0
ascending:可以是布尔值或布尔值列表,分别对应于每个排序列的升序/降序设置
inplace:是否直接修改原 DataFrame
"""
import pandas as pd

data = {'A': [3, 1, 3], 'B': [5, 6, 4]}
df = pd.DataFrame(data)

# 基于'A'列降序排序
sorted_by_A = df.sort_values(by='A', ascending=False)
print("\nDataFrame sorted by column 'A' in descending order:")
print(sorted_by_A)

# 同时基于'A'和'B'两列排序,先按'A'降序,再按'B'升序
sorted_by_A_B = df.sort_values(by=['A', 'B'], ascending=[False, True])
print("\nDataFrame sorted by columns 'A' (descending) and 'B' (ascending):")
print(sorted_by_A_B)
DataFrame sorted by column 'A' in descending order:
   A  B
0  3  5
2  3  4
1  1  6

DataFrame sorted by columns 'A' (descending) and 'B' (ascending):
   A  B
2  3  4
0  3  5
1  1  6

获取数据

df[]

访问单个或多个列

df['column_name']
df[['column_name1', 'column_name2']]
import pandas as pd

data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
df = pd.DataFrame(data)

# 获取单列'A'
print(df['A'])

# 获取多列['A', 'B']
print(df[['A', 'B']])

行的选择(基于布尔索引)

df[boolean_expression] # 通过布尔表达式来筛选满足条件的行
# 筛选出'A'列值大于1的所有行
print(df[df['A'] > 1])

行的选择(基于位置的切片)

# 基于位置的切片,仅当行索引为默认整数时有效
print(df[0:2])  # 获取前两行

DataFrame.at[]

df.at[row_label, column_label] # 用于通过标签获取单个值(即行和列的名称)。它只能访问单个值
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])
print(df.at[0, 'A'])  # 注意:这里的行索引是字符串形式,如果是整数则不需要引号
"""
   A  B
0  1  2
1  3  4
"""

对应位置的值是

1

DataFrame.iat[]

df.iat[row_position, column_position] # 通过位置(即行和列的整数索引)获取单个值。与 at[] 类似,但它基于位置而非标签
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])
print(df.iat[1, 1])  # 访问第一行第一列的值
"""
   A  B
0  1  2
1  3  4
"""

对应位置的值是

4

DataFrame.loc[]

df.loc[row_indexer, column_indexer] # 通过标签访问一组值。可以用来选择行、列或两者组合的数据
import pandas as pd
df = pd.DataFrame([['A1', 'B1'], ['A2', 'B2']], columns=['A', 'B'])

# 获取所有行中'A'列的数据
print(df.loc[:, 'A'], end='\n\n')

# 获取特定行(例如第0行)的所有列的数据
print(df.loc[0, :])


"""
    A   B
0  A1  B1
1  A2  B2
"""
0    A1
1    A2
Name: A, dtype: object

A    A1
B    B1
Name: 0, dtype: object

DataFrame.iloc[]

df.iloc[row_position, column_position] # 通过位置访问一组值。类似于 loc[],但它是基于位置而非标签进行索引
import pandas as pd
df = pd.DataFrame([['A1', 'B1'], ['A2', 'B2']], columns=['A', 'B'])

# 获取前两行中的所有列
print(df.iloc[0:2, :], end='\n\n')

# 获取所有行中的第一列
print(df.iloc[:, 0])

"""
    A   B
0  A1  B1
1  A2  B2
"""
    A   B
0  A1  B1
1  A2  B2

0    A1
1    A2
Name: A, dtype: object

修改数据

索引赋值

import pandas as pd

# 创建一个示例 DataFrame
data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
df = pd.DataFrame(data)

print("Original DataFrame:")
print(df)

# 修改第一行第一列的值
df.at[0, 'A'] = 10  # 使用 .at[] 修改单个值
df.iat[1, 1] = 20   # 使用 .iat[] 修改单个值(基于位置)

print("\nDataFrame after modification:")
print(df)
Original DataFrame:
   A  B
0  1  4
1  2  5
2  3  6

DataFrame after modification:
    A   B
0  10   4
1   2  20
2   3   6

布尔索引修改

# 将'A'列中大于1的所有值改为99
df.loc[df['A'] > 1, 'A'] = 99

修改整列

# 将'B'列的所有值改为0
df['B'] = 0
   A  B
0  1  0
1  2  0
2  3  0

替换特定值

replace() 方法可以用来替换 DataFrame 中的特定值

# 将所有99替换为-1
df.replace(6, -1, inplace=True)
print(df)
   A  B
0  1  4
1  2  5
2  3 -1

添加新列

# 添加一列'C',值为'A'和'B'的和
df['C'] = df['A'] + df['B']
   A  B  C
0  1  4  5
1  2  5  7
2  3  6  9

更新现有列

# 更新'B'列的值为'A'列的平方'
df['B'] = df['A'] ** 2
   A  B
0  1  1
1  2  4
2  3  9

函数加工修改

.apply().applymap() 是 Pandas 中用于应用自定义函数对值进行修改的强大工具

  • 某个列
df['A'] = df['A'].apply(lambda x: x + 10)
    A  B
0  11  4
1  12  5
2  13  6
  • 整个dataframe
# 将所有值乘以2
df = df.applymap(lambda x: x * 2)
   A  B
0  1  4
1  2  5
2  3  6

批量修改行

.loc[].iloc[] 可以用来批量修改特定行或列的数据

# 修改第1行的所有值 索引0起
df.loc[0] = [99, 99]

# 修改第2列的所有值
df.iloc[:, 1] = [0, 0, 0]
    A   B
0  99  99
1   2   5
2   3   6
    A  B
0   1  0
1   2  0
2   3  0

删除列和行

使用 drop() 方法

  • 删除列
# 删除'B'列
df.drop('B', axis=1, inplace=True)
  • 删除行
# 删除第2行
df.drop(1, axis=0, inplace=True)

布尔索引

布尔索引(Boolean Indexing)是 Pandas 中非常强大的一个特性,它允许你根据某些条件来筛选数据

通过布尔索引来过滤 DataFrame 或 Series 的行,可以让你更专注于满足特定条件的数据子集

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40],
    'Score': [88, 92, 81, 79]
}

df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)
Original DataFrame:
      Name  Age  Score
0    Alice   25     88
1      Bob   30     92
2  Charlie   35     81
3    David   40     79

基于单个条件的筛选

filtered_df = df[df['Score'] >= 85]
print("\nStudents with score >= 85:")
print(filtered_df)
Students with score >= 85:
    Name  Age  Score
0  Alice   25     88
1    Bob   30     92

基于多个条件的筛选

filtered_df = df[(df['Age'] < 35) & (df['Score'] > 80)]
print("\nStudents younger than 35 and score > 80:")
print(filtered_df)
Students younger than 35 and score > 80:
    Name  Age  Score
0  Alice   25     88
1    Bob   30     92

在组合多个条件时,必须使用括号 () 来明确优先级,并且使用位运算符 &(和)、|(或)而不是逻辑运算符 andor

条件满足于

如果想晒选可能在某个条件集合内的记录,使用.isin方法

names_to_select = ['Alice', 'David']
filtered_df = df[df['Name'].isin(names_to_select)]
print("\nSelected students by name:")
print(filtered_df)
Selected students by name:
    Name  Age  Score
0  Alice   25     88
3  David   40     79

基于条件修改

df.loc[df['Age'] > 30, 'Score'] += 5
print("\nUpdated scores for students older than 30:")
print(df)
Updated scores for students older than 30:
      Name  Age  Score
0    Alice   25     88
1      Bob   30     92
2  Charlie   35     86 # 81
3    David   40     84 # 79

缺失数据

Pandas 使用 NaN(Not a Number)来表示浮点数数组中的缺失数据,并且对其他类型的数据也提供了类似的机制

可以使用以下方法来检测缺失数据

  • isna()isnull():返回一个布尔值的 DataFrame 或 Series,指示哪些位置是存在缺失数据的
  • notna()notnull():与上述相反
import pandas as pd
import numpy as np

# 创建一个包含缺失数据的 DataFrame
data = {'A': [1, 2, np.nan], 'B': [5, np.nan, np.nan], 'C': [1, 2, 3]}
df = pd.DataFrame(data)

print("Original DataFrame with missing values:")
print(df)

# 检测缺失数据
missing_data = df.isna()
print("\nBoolean DataFrame indicating missing values:")
print(missing_data)
  • 缺失位置bool标记
Boolean DataFrame indicating missing values:
       A      B      C
0  False  False  False
1  False   True  False
2   True   True  False

删除缺失

dropna():删除任何含有缺失值的行或列

# 删除含有任何缺失值的行
df_cleaned = df.dropna()

# 删除含有任何缺失值的列
df_cleaned_cols = df.dropna(axis=1)

填充缺失

fillna():用指定值替换所有缺失值

# 使用0填充缺失值
df_filled = df.fillna(0)

# 使用前向填充(ffill)或后向填充(bfill)
df_ffilled = df.fillna(method='ffill')  # 前向填充

df_bfilled = df.fillna(method='bfill')  # 后向填充

# 使用每列的均值填充缺失值
df_mean_filled = df.fillna(df.mean())

前后向取方向上最近的有效值进行填充

统计

基本统计方法

mean():计算平均值

sum():求和

min()max():找出最小值和最大值

std():计算标准差

var():计算方差

median()`:计算中位数

quantile(q):计算指定分位数(q 是0到1之间的数值)

count():非空观测数量

describe():生成描述性统计信息

计算平均值

# 计算每列的平均值,默认忽略NaN
print("\nMean of each column (ignoring NaN):")
print(df.mean())

# 按行计算平均值
print("\nMean of each row:")
print(df.mean(axis=1))

求和

# 计算每列的总和
print("\nSum of each column:")
print(df.sum())

# 按行计算总和
print("\nSum of each row:")
print(df.sum(axis=1))

找出最小值和最大值

# 最小值
print("\nMin values of each column:")
print(df.min())

# 最大值
print("\nMax values of each column:")
print(df.max())

标准差和方差

# 标准差
print("\nStandard deviation of each column:")
print(df.std())

# 方差
print("\nVariance of each column:")
print(df.var())

中位数

# 中位数
print("\nMedian of each column:")
print(df.median())

分位数

# 第一四分位数 (Q1)
print("\nFirst quartile (Q1) of each column:")
print(df.quantile(0.25))

# 第三四分位数 (Q3)
print("\nThird quartile (Q3) of each column:")
print(df.quantile(0.75))

非空观测数量

# 计算每列中的非空观测数量
print("\nCount of non-null observations in each column:")
print(df.count())

描述性统计

# 生成描述性统计信息
print("\nDescriptive statistics for the DataFrame:")
print(df.describe())

GroupBy

除了直接在 DataFrame 或 Series 上应用统计方法外,还可以结合 groupby() 方法按某些条件分组后进行统计分析。

# 创建一个带有分类数据的 DataFrame
data_grouped = pd.DataFrame({
    'Category': ['X', 'Y', 'X', 'Y'],
    'Values': [10, 20, 30, 40]
})

# 按 Category 分组并计算每组的平均值
print("\nGroup by Category and calculate mean:")
print(data_grouped.groupby('Category').mean())

合并拼接

concat 主要用于简单地沿行或列拼接多个 DataFrame 或 Series,适合处理无索引对齐需求的情况

join 更适合基于索引进行复杂的连接操作,类似于 SQL 中的 JOIN 操作

合并

join 是用于合并两个 DataFrame 的方法,基于索引进行连接操作。它类似于 SQL 中的 JOIN 操作

DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='')
"""
other:要连接的另一个 DataFrame
on:指定主 DataFrame 的列作为连接键(默认基于索引)
how:
	'left'(默认):左连接。
	'right':右连接。
	'outer':外连接。
	'inner':内连接。
lsuffix 和 rsuffix:当左右 DataFrame 的列名重复时,添加后缀区分
"""
  • 左连接
import pandas as pd

df1 = pd.DataFrame({'A': [1, 2]}, index=['a', 'b'])
df2 = pd.DataFrame({'B': [3, 4]}, index=['a', 'c'])

# 左连接
result = df1.join(df2, how='left')
print(result)
   A    B
a  1  3.0
b  2  NaN
  • 外链接
# 外连接
result = df1.join(df2, how='outer')
     A    B
a  1.0  3.0
b  2.0  NaN
c  NaN  4.0
  • 内连接
result = df1.join(df2, how='inner')
   A  B
a  1  3
  • 解决列名冲突
import pandas as pd

df1 = pd.DataFrame({'key': ['a', 'b'], 'A': [1, 2]})
df2 = pd.DataFrame({'key': ['a', 'c'], 'A': [3, 4]})

# 连接并解决列名冲突
result = df1.set_index('key').join(df2.set_index(
    'key'), lsuffix='_left', rsuffix='_right', how='outer')
print(result)
     A_left  A_right
key                 
a       1.0      3.0
b       2.0      NaN
c       NaN      4.0

拼接

concat 是 Pandas 中用于合并多个 DataFrame 或 Series 的方法,可以沿指定轴(行或列)进行拼接,默认是按行(axis=0)拼接

pd.concat(objs, axis=0, join='outer', ignore_index=False, keys=None)
"""
objs:要合并的对象列表,可以是 DataFrame 或 Series。
axis:
	0(默认):按行拼接。
	1:按列拼接。
join:
	'outer'(默认):外连接,保留所有索引。
	'inner':内连接,仅保留交集索引。
ignore_index:
	False(默认):保留原有索引。
	True:重新生成索引。
keys:为每个拼接对象添加层级索引
"""
  • 按行拼接
import pandas as pd

df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})

# 默认按行拼接
result = pd.concat([df1, df2])
   A  B
0  1  3
1  2  4
0  5  7
1  6  8
  • 按列拼接
# 按列拼接
result = pd.concat([df1, df2], axis=1)
   A  B  A  B
0  1  3  5  7
1  2  4  6  8
  • 重新生成索引
# 忽略原有索引,重新生成索引
result = pd.concat([df1, df2], ignore_index=True)
   A  B
0  1  3
1  2  4
2  5  7
3  6  8
  • 层级索引
result = pd.concat([df1, df2], keys=['df1', 'df2'])
       A  B
df1 0  1  3
    1  2  4
df2 0  5  7
    1  6  8