Pandas 基础教程:初学者必看 – wiki基地


Pandas 基础教程:初学者必看

欢迎来到 Pandas 的世界!如果你刚开始接触 Python 数据分析,那么 Pandas 将是你最得力的助手。它是一个强大且灵活的开源库,专为处理和分析结构化数据而设计。无论你是要处理 Excel 文件、CSV 数据,还是关系型数据库中的表格,Pandas 都能让你事半功倍。

本教程将从零开始,带你了解 Pandas 的核心概念和基本操作,助你迈出数据分析的第一步。

1. 为什么选择 Pandas?

在深入学习之前,我们先来了解一下 Pandas 的优势:

  1. 强大的数据结构: Pandas 提供了两种核心数据结构:Series(一维带标签数组)和 DataFrame(二维带标签表格)。它们能够轻松地存储和处理各种类型的数据。
  2. 便捷的数据处理: Pandas 提供了大量用于数据清洗、转换、合并、重塑、切片、聚合等操作的函数和方法,极大地简化了数据处理流程。
  3. 高效性能: Pandas 底层使用 NumPy 优化,并且许多操作都在 C 语言层面实现,因此处理大规模数据时通常效率很高。
  4. 广泛的I/O支持: 轻松读取和写入多种格式的数据,如 CSV, Excel, SQL数据库, JSON, HDF5等。
  5. 时间序列分析支持: 对时间序列数据有特别优秀的支持。

简而言之,如果你需要用 Python 处理表格或类似结构的数据,Pandas 是不二之选。

2. 安装 Pandas

如果你已经安装了 Anaconda 或 Miniconda,那么 Pandas 通常已经预装好了。如果没有,或者你使用标准的 Python 环境,可以通过 pip 包管理器进行安装:

打开你的终端或命令提示符,运行以下命令:

bash
pip install pandas

安装完成后,就可以在 Python 脚本或 Jupyter Notebook 中导入并使用了。

3. 导入 Pandas

按照惯例,我们通常会给 Pandas 起一个别名 pd,这样可以简化代码书写。

“`python
import pandas as pd

可以检查一下安装的版本

print(pd.version)
“`

4. Pandas 的核心数据结构

Pandas 主要提供了两个核心数据结构:SeriesDataFrame。理解它们是掌握 Pandas 的关键。

4.1 Series (序列)

  • 定义: Series 是一种一维的、带有标签的数组。它可以存储任何数据类型(整数、浮点数、字符串、Python 对象等)。
  • 组成: Series 由两部分组成:
    • 数据 (Data): 存储实际的值。
    • 索引 (Index): 为每个数据点提供标签,类似于字典的键,或者列表的下标,但更灵活。

创建 Series:

你可以通过多种方式创建 Series:

a) 从 Python 列表或 NumPy 数组创建:

“`python
import pandas as pd
import numpy as np

从列表创建 Series (默认整数索引)

s1 = pd.Series([10, 20, 30, 40, 50])
print(“Series s1:”)
print(s1)

从 NumPy 数组创建 Series (默认整数索引)

s2 = pd.Series(np.array([1.1, 2.2, 3.3, 4.4]))
print(“\nSeries s2:”)
print(s2)
“`

输出会显示数据和对应的索引:

“`
Series s1:
0 10
1 20
2 30
3 40
4 50
dtype: int64

Series s2:
0 1.1
1 2.2
2 3.3
3 4.4
dtype: float64
``
这里的
0, 1, 2, 3, 40, 1, 2, 3就是默认的整数索引。dtype` 表示数据类型。

b) 创建时指定索引:

你可以自己指定索引标签,这使得 Series 的索引比列表更灵活。

“`python

从列表创建 Series,并指定字符串索引

s3 = pd.Series([95, 90, 88, 92], index=[‘数学’, ‘语文’, ‘英语’, ‘物理’])
print(“\nSeries s3 (带自定义索引):”)
print(s3)
“`

输出:

Series s3 (带自定义索引):
数学 95
语文 90
英语 88
物理 92
dtype: int64

c) 从 Python 字典创建:

字典的键将成为 Series 的索引,值成为数据。

“`python

从字典创建 Series

data_dict = {‘apple’: 3, ‘banana’: 1, ‘cherry’: 5}
s4 = pd.Series(data_dict)
print(“\nSeries s4 (从字典创建):”)
print(s4)
“`

输出:

Series s4 (从字典创建):
apple 3
banana 1
cherry 5
dtype: int64

访问 Series 元素:

可以使用索引来访问 Series 中的元素,这与访问列表或字典类似。

“`python
print(“\n访问 Series 元素:”)
print(s3[‘数学’]) # 使用标签索引
print(s3[0]) # 使用位置索引 (如果索引是默认整数或可以解析为位置)
print(s4[‘banana’])

print(s4[1]) # 注意:如果索引是字符串,不能直接使用位置索引访问,会报错!

“`

Series 的基本操作:

Series 支持很多类似 NumPy 数组的操作,例如广播、数学运算、布尔筛选等。

“`python

数学运算

s1_plus_5 = s1 + 5
print(“\ns1 + 5:”)
print(s1_plus_5)

布尔筛选 (只选择大于等于 90 的成绩)

high_scores = s3[s3 >= 90]
print(“\n高分科目 (>= 90):”)
print(high_scores)
“`

4.2 DataFrame (数据框)

  • 定义: DataFrame 是一个二维的、大小可变的、带有标签的表格数据结构,类似于电子表格或 SQL 表。
  • 组成: DataFrame 可以看作是 Series 的容器。它由以下几个部分组成:
    • 数据 (Data): 表格中的实际值。
    • 行索引 (Row Index): 对应表格的每一行,用于标识行。
    • 列索引 (Column Index): 对应表格的每一列,通常是列名。每一列实际上就是一个 Series 对象。

创建 DataFrame:

创建 DataFrame 的最常用方式是从字典,其中字典的键是列名,值是列表、NumPy 数组或 Series。

a) 从字典创建 (最常见):

“`python

从字典创建 DataFrame

data = {
‘姓名’: [‘张三’, ‘李四’, ‘王五’, ‘赵六’],
‘年龄’: [25, 30, 22, 28],
‘城市’: [‘北京’, ‘上海’, ‘广州’, ‘深圳’]
}
df = pd.DataFrame(data)
print(“\nDataFrame df:”)
print(df)
“`

输出:

DataFrame df:
姓名 年龄 城市
0 张三 25 北京
1 李四 30 上海
2 王五 22 广州
3 赵六 28 深圳

这里 0, 1, 2, 3 是默认的行索引,姓名, 年龄, 城市 是列索引。

你也可以在创建时指定行索引和列顺序:

“`python

指定行索引

df_with_index = pd.DataFrame(data, index=[‘a’, ‘b’, ‘c’, ‘d’])
print(“\nDataFrame df_with_index (指定行索引):”)
print(df_with_index)

指定列顺序

df_ordered_cols = pd.DataFrame(data, columns=[‘姓名’, ‘城市’, ‘年龄’])
print(“\nDataFrame df_ordered_cols (指定列顺序):”)
print(df_ordered_cols)
“`

b) 从 Series 字典创建:

DataFrame 也可以从 Series 组成的字典创建,这样更明确地体现了 DataFrame 是 Series 的集合。

“`python
names = pd.Series([‘张三’, ‘李四’, ‘王五’, ‘赵六’])
ages = pd.Series([25, 30, 22, 28])
cities = pd.Series([‘北京’, ‘上海’, ‘广州’, ‘深圳’])

data_series = {‘姓名’: names, ‘年龄’: ages, ‘城市’: cities}
df_from_series = pd.DataFrame(data_series)
print(“\nDataFrame df_from_series (从 Series 字典创建):”)
print(df_from_series)
“`
这和从列表字典创建的效果类似,但如果你已经有了 Series 数据,这种方法很方便。

c) 从列表字典创建:

每个字典代表一行数据。

python
data_list_dict = [
{'姓名': '张三', '年龄': 25, '城市': '北京'},
{'姓名': '李四', '年龄': 30, '城市': '上海'},
{'姓名': '王五', '年龄': 22, '城市': '广州'},
{'姓名': '赵六', '年龄': 28, '城市': '深圳'}
]
df_list_dict = pd.DataFrame(data_list_dict)
print("\nDataFrame df_list_dict (从列表字典创建):")
print(df_list_dict)

5. 查看 DataFrame 信息

创建 DataFrame 后,你需要了解它的基本信息。

“`python

查看前几行 (默认前5行)

print(“\ndf.head():”)
print(df.head())

查看后几行 (默认后5行)

print(“\ndf.tail():”)
print(df.tail())

查看 DataFrame 的维度 (行数, 列数)

print(“\ndf.shape:”, df.shape)

查看 DataFrame 的数据类型

print(“\ndf.dtypes:\n”, df.dtypes)

查看 DataFrame 的列名

print(“\ndf.columns:”, df.columns)

查看 DataFrame 的行索引

print(“\ndf.index:”, df.index)

查看 DataFrame 的基本信息 (非空值数量,数据类型等)

print(“\ndf.info():”)
df.info()

查看数值列的描述性统计信息 (计数、均值、标准差、最小值、最大值、四分位数)

print(“\ndf.describe():”)
print(df.describe())
“`
这些方法在你刚加载一个数据集时非常有用,能让你快速了解数据的概况。

6. 选择 DataFrame 中的数据

选择(或称索引、切片)是数据操作中最基础也最频繁的步骤。Pandas 提供了多种方式。

6.1 选择列

选择单列会得到一个 Series。选择多列会得到一个 DataFrame。

“`python

选择单列 (使用列名)

names_col = df[‘姓名’]
print(“\n选择单列 ‘姓名’:”)
print(names_col)
print(“类型:”, type(names_col))

选择多列 (使用列名列表)

subset_cols = df[[‘姓名’, ‘城市’]]
print(“\n选择多列 [‘姓名’, ‘城市’]:”)
print(subset_cols)
print(“类型:”, type(subset_cols))
“`

注意: 使用点号 df.列名 也可以选择列(例如 df.姓名)。但这种方式不推荐,因为它不支持包含空格或特殊字符的列名,并且可能与 DataFrame 的方法名冲突。使用 df['列名'] 是更安全和通用的方法。

6.2 选择行:使用 .loc.iloc

这是初学者容易混淆的地方,理解 .loc.iloc 至关重要。

  • .loc基于标签 (Label) 的索引。它使用行索引标签和列索引标签(列名)。
  • .iloc基于位置 (Integer-location) 的索引。它使用整数位置(从 0 开始)来访问行和列,就像 Python 的列表和 NumPy 数组一样。

使用 .loc (基于标签):

“`python
df_with_custom_index = pd.DataFrame(data, index=[‘a’, ‘b’, ‘c’, ‘d’])

选择单行 (使用行标签)

row_a = df_with_custom_index.loc[‘a’]
print(“\n使用 .loc 选择行 ‘a’:”)
print(row_a)

选择多行 (使用行标签列表)

rows_ac = df_with_custom_index.loc[[‘a’, ‘c’]]
print(“\n使用 .loc 选择多行 [‘a’, ‘c’]:”)
print(rows_ac)

选择特定行和列 (使用行标签和列标签)

age_of_a = df_with_custom_index.loc[‘a’, ‘年龄’]
print(“\n使用 .loc 选择行 ‘a’ 的 ‘年龄’:”, age_of_a)

选择特定行和多列

subset_ac_name_city = df_with_custom_index.loc[[‘a’, ‘c’], [‘姓名’, ‘城市’]]
print(“\n使用 .loc 选择行 [‘a’, ‘c’] 的列 [‘姓名’, ‘城市’]:”)
print(subset_ac_name_city)

使用切片 (包含起始和结束标签)

rows_a_to_c = df_with_custom_index.loc[‘a’:’c’, ‘姓名’:’城市’]
print(“\n使用 .loc 切片行 ‘a’ 到 ‘c’,列 ‘姓名’ 到 ‘城市’:”)
print(rows_a_to_c)
“`

使用 .iloc (基于位置):

“`python

使用 .iloc 选择单行 (使用行位置,从 0 开始)

row_0 = df.iloc[0] # 对应原df中的第一行
print(“\n使用 .iloc 选择第 0 行:”)
print(row_0)

使用 .iloc 选择多行 (使用行位置列表)

rows_0_2 = df.iloc[[0, 2]]
print(“\n使用 .iloc 选择第 0 和第 2 行:”)
print(rows_0_2)

使用 .iloc 选择特定行和列 (使用行位置和列位置)

age_0 = df.iloc[0, 1] # 第 0 行,第 1 列 (年龄)
print(“\n使用 .iloc 选择第 0 行的第 1 列 (年龄):”, age_0)

使用 .iloc 选择特定行和多列

subset_0_2_0_2 = df.iloc[[0, 2], [0, 2]] # 第 0, 2 行,第 0, 2 列 (姓名, 城市)
print(“\n使用 .iloc 选择第 0, 2 行的第 0, 2 列:”)
print(subset_0_2_0_2)

使用切片 (不包含结束位置,类似 Python 列表切片)

rows_0_to_2 = df.iloc[0:3, 0:2] # 第 0, 1, 2 行,第 0, 1 列 (姓名, 年龄)
print(“\n使用 .iloc 切片行 0 到 2 (不含 3),列 0 到 1 (不含 2):”)
print(rows_0_to_2)
“`

总结 .loc vs .iloc:
.loc:基于你看到的标签,包括字符串、数字或 datetime 标签。切片时包含结束标签。
.iloc:基于从 0 开始的位置。切片时不包含结束位置。

6.3 布尔索引 (过滤数据)

这是数据分析中最常用的操作之一。你可以使用布尔表达式来筛选满足特定条件的行。

“`python

选择年龄大于 25 岁的行

age_filter = df[‘年龄’] > 25
print(“\n年龄 > 25 的布尔 Series:”)
print(age_filter)

older_than_25 = df[age_filter] # 将布尔 Series 放到 DataFrame 中进行筛选
print(“\n年龄大于 25 岁的人员:”)
print(older_than_25)

更简洁的写法

older_than_25_concise = df[df[‘年龄’] > 25]
print(“\n年龄大于 25 岁的人员 (简洁写法):”)
print(older_than_25_concise)

组合多个条件 (使用 & 表示与,| 表示或,~ 表示非)

选择年龄大于 25 岁 并且 城市是上海或深圳的人

condition = (df[‘年龄’] > 25) & ((df[‘城市’] == ‘上海’) | (df[‘城市’] == ‘深圳’))
filtered_data = df[condition]
print(“\n年龄大于 25 岁且城市为上海或深圳的人员:”)
print(filtered_data)
``
进行多条件组合筛选时,每个条件必须用括号
()` 包围,否则会因为运算符优先级导致错误。

7. 添加、修改和删除数据

7.1 添加新列

可以通过直接赋值的方式添加新列。新列的长度必须与 DataFrame 的行数一致。

“`python

添加性别列

df[‘性别’] = [‘男’, ‘女’, ‘男’, ‘男’]
print(“\n添加 ‘性别’ 列后:”)
print(df)

添加计算列 (例如:假设有一列身高,计算 BMI,这里我们直接添加一个学历列作为示例)

df[‘学历’] = [‘本科’, ‘硕士’, ‘本科’, ‘博士’]
print(“\n添加 ‘学历’ 列后:”)
print(df)
“`

7.2 修改现有列

直接使用列选择和赋值即可修改整列或部分数据。

“`python

修改整列的值

df[‘年龄’] = df[‘年龄’] + 1 # 所有年龄都加 1
print(“\n所有年龄加 1 后:”)
print(df)

修改特定行和列的值 (使用 .loc 或 .iloc)

df.loc[0, ‘城市’] = ‘南京’ # 修改第一行的城市为南京
print(“\n修改第一行城市后:”)
print(df)

df.iloc[1, 2] = ‘杭州’ # 修改第二行的城市为杭州
print(“\n修改第二行城市后:”)
print(df)
“`

7.3 删除列

可以使用 del 关键字或 .drop() 方法删除列。.drop() 更常用,因为它灵活且可以指定删除行或列。

“`python

使用 del 删除列

del df[‘学历’]

print(“\n使用 del 删除 ‘学历’ 列后:”)

print(df)

使用 .drop() 删除列 (axis=1 表示列,axis=0 表示行)

inplace=True 会直接修改原 DataFrame,否则会返回一个新的 DataFrame

df_dropped = df.drop(‘性别’, axis=1)
print(“\n使用 .drop 删除 ‘性别’ 列 (返回新 DataFrame):”)
print(df_dropped)

或者直接修改原 DataFrame

df.drop(‘学历’, axis=1, inplace=True)

print(“\n使用 .drop 删除 ‘学历’ 列 (inplace=True) 后:”)

print(df)

``
注意
drop()方法默认不会修改原始 DataFrame,需要设置inplace=True。通常推荐不使用inplace=True`,而是将结果赋值给一个新变量,以避免意外修改数据。

7.4 删除行

使用 .drop() 方法,指定行标签或行位置,并设置 axis=0 (默认值)。

“`python

删除标签为 0 的行

df_no_row_0 = df.drop(0, axis=0)
print(“\n删除标签为 0 的行后:”)
print(df_no_row_0)

删除标签为 1 和 3 的行

df_no_rows_1_3 = df.drop([1, 3], axis=0)
print(“\n删除标签为 1 和 3 的行后:”)
print(df_no_rows_1_3)

使用 .iloc 删除行 (需要先获取位置对应的标签)

例如删除第三行 (位置索引 2)

row_to_drop_index = df.index[2] # 获取位置 2 对应的标签
df_no_row_2_iloc = df.drop(row_to_drop_index, axis=0)
print(“\n使用 .iloc 删除位置 2 对应的行后:”)
print(df_no_row_2_iloc)
“`

8. 处理缺失数据

真实世界的数据经常包含缺失值(NaN,Not a Number)。Pandas 提供了方便的方法来检测和处理它们。

“`python

创建一个包含缺失值的 DataFrame

data_with_nan = {
‘A’: [1, 2, np.nan, 4],
‘B’: [5, np.nan, np.nan, 8],
‘C’: [9, 10, 11, 12]
}
df_nan = pd.DataFrame(data_with_nan)
print(“\n包含缺失值的 DataFrame:”)
print(df_nan)

检测缺失值 (返回布尔型 DataFrame)

print(“\n检测缺失值 (.isnull()):”)
print(df_nan.isnull())

print(“\n检测非缺失值 (.notnull()):”)
print(df_nan.notnull())

统计每列的缺失值数量

print(“\n每列缺失值数量:”)
print(df_nan.isnull().sum())

删除包含缺失值的行

how=’any’ (默认): 只要包含任何一个缺失值就删除该行

how=’all’: 只在整行都是缺失值时才删除该行

df_dropped_rows = df_nan.dropna(how=’any’)
print(“\n删除包含缺失值的行后:”)
print(df_dropped_rows)

删除包含缺失值的列 (axis=1)

df_dropped_cols = df_nan.dropna(axis=1, how=’any’)
print(“\n删除包含缺失值的列后:”)
print(df_dropped_cols)

填充缺失值

value: 用于填充的值

method: ‘ffill’ (前向填充), ‘bfill’ (后向填充)

df_filled = df_nan.fillna(0) # 用 0 填充所有缺失值
print(“\n用 0 填充缺失值后:”)
print(df_filled)

df_filled_mean = df_nan.fillna(df_nan[‘A’].mean()) # 用列 A 的均值填充
print(“\n用列 A 均值填充缺失值后:”)
print(df_filled_mean)

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

df_filled_ffill = df_nan.fillna(method=’ffill’)
print(“\n前向填充缺失值后:”)
print(df_filled_ffill)

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

df_filled_bfill = df_nan.fillna(method=’bfill’)
print(“\n后向填充缺失值后:”)
print(df_filled_bfill)
“`
处理缺失值是数据清洗的重要环节,选择哪种方法取决于你的数据和分析需求。

9. 基本数据分析操作

Pandas 提供了许多快速进行数据分析的方法。

“`python

创建一个用于分析的 DataFrame

data_sales = {
‘Product’: [‘A’, ‘B’, ‘A’, ‘C’, ‘B’, ‘A’, ‘C’, ‘B’],
‘City’: [‘Beijing’, ‘Shanghai’, ‘Beijing’, ‘Guangzhou’, ‘Shanghai’, ‘Shanghai’, ‘Guangzhou’, ‘Beijing’],
‘Sales’: [100, 150, 120, 200, 180, 130, 220, 160]
}
df_sales = pd.DataFrame(data_sales)
print(“\n销售数据 DataFrame:”)
print(df_sales)

计算总销售额 (某列的总和)

total_sales = df_sales[‘Sales’].sum()
print(“\n总销售额:”, total_sales)

计算平均销售额

average_sales = df_sales[‘Sales’].mean()
print(“\n平均销售额:”, average_sales)

查找最大销售额

max_sales = df_sales[‘Sales’].max()
print(“\n最大销售额:”, max_sales)

查找最小销售额

min_sales = df_sales[‘Sales’].min()
print(“\n最小销售额:”, min_sales)

计算标准差、中位数、众数等

std_sales = df_sales[‘Sales’].std()
median_sales = df_sales[‘Sales’].median()
mode_product = df_sales[‘Product’].mode() # 众数可能不止一个
print(“\n销售额标准差:”, std_sales)
print(“销售额中位数:”, median_sales)
print(“产品众数:\n”, mode_product)

计算值的出现次数

product_counts = df_sales[‘Product’].value_counts()
print(“\n各产品销售次数:”)
print(product_counts)

city_counts = df_sales[‘City’].value_counts()
print(“\n各城市销售次数:”)
print(city_counts)

排序数据

按销售额升序排序

df_sorted_sales_asc = df_sales.sort_values(by=’Sales’, ascending=True)
print(“\n按销售额升序排序:”)
print(df_sorted_sales_asc)

按城市降序排序,再按销售额升序排序

df_sorted_multi = df_sales.sort_values(by=[‘City’, ‘Sales’], ascending=[False, True])
print(“\n按城市降序,销售额升序排序:”)
print(df_sorted_multi)
``
这些方法让你能够快速对数据进行描述性统计和初步探索。更复杂的分组分析通常使用
groupby()` 方法,这是 Pandas 的一个强大功能,适合在掌握基础后深入学习。

10. 读取和写入数据

Pandas 支持多种文件格式的读取和写入。最常用的是 CSV 文件。

“`python

假设你有一个名为 ‘my_data.csv’ 的文件

写入 CSV 文件

index=False 表示不将 DataFrame 的索引写入文件

df_sales.to_csv(‘sales_data.csv’, index=False)
print(“\nDataFrame 已写入 ‘sales_data.csv'”)

从 CSV 文件读取数据

try:
df_from_csv = pd.read_csv(‘sales_data.csv’)
print(“\n从 ‘sales_data.csv’ 读取的数据:”)
print(df_from_csv)
except FileNotFoundError:
print(“\n’sales_data.csv’ 文件未找到,请确保文件存在。”)

其他常用的读取函数:

pd.read_excel(‘my_data.xlsx’)

pd.read_sql(‘SELECT * FROM my_table’, connection)

pd.read_json(‘my_data.json’)

其他常用的写入函数:

df.to_excel(‘output.xlsx’, index=False)

df.to_sql(‘output_table’, connection, if_exists=’replace’)

df.to_json(‘output.json’)

“`
掌握读取和写入数据的能力,你就可以将 Pandas 应用于实际数据集了。

11. 总结与下一步

恭喜你!你已经学习了 Pandas 的基础知识,包括:

  • Pandas 的核心数据结构:Series 和 DataFrame。
  • 如何创建 Series 和 DataFrame。
  • 如何查看 DataFrame 的基本信息。
  • 如何使用列名、.loc.iloc 选择数据。
  • 如何使用布尔索引过滤数据。
  • 如何添加、修改和删除列/行。
  • 如何处理缺失数据。
  • 如何进行基本的描述性统计和排序。
  • 如何读取和写入 CSV 文件。

这只是 Pandas 的冰山一角。接下来,你可以继续学习更高级的主题,例如:

  • GroupBy 操作: 按类别进行分组聚合计算。
  • 数据合并与连接: 将多个 DataFrame 合并起来。
  • 数据重塑: 使用 pivot, melt, stack, unstack 等方法改变数据结构。
  • 时间序列分析: Pandas 对时间序列数据有特殊支持。
  • 可视化: Pandas 内置了基于 Matplotlib 的简单绘图功能。

最重要的建议是: 动手实践!找一些真实的数据集(比如 Kaggle 上面的公开数据),运用你学到的 Pandas 技能进行探索和分析。遇到问题时,查阅 Pandas 官方文档或 Stack Overflow 是非常有效的学习方法。

希望这篇教程对你的 Pandas 学习之旅有所帮助!祝你在数据分析的道路上越走越远!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部