引言

Python的pandas库是数据科学领域最常用的工具之一,它提供了强大的数据结构和数据分析功能。在处理数据时,经常需要从数据框(DataFrame)中选择特定的行或列,这是数据分析的基础操作。pandas提供了多种方法来实现这一目的,其中最常用的是loc和iloc方法。本文将详细介绍这些方法的使用原理、语法规则,并通过丰富的实例展示如何在实际数据分析中灵活运用这些方法来提取所需数据。

pandas数据框基础

在深入了解数据选择方法之前,我们先简要回顾一下pandas的DataFrame结构。DataFrame是pandas中最常用的数据结构,类似于电子表格或SQL表,它由行和列组成,可以存储不同类型的数据。

import pandas as pd import numpy as np # 创建一个简单的DataFrame data = { '姓名': ['张三', '李四', '王五', '赵六', '钱七'], '年龄': [25, 30, 35, 40, 45], '性别': ['男', '女', '男', '女', '男'], '城市': ['北京', '上海', '广州', '深圳', '杭州'], '薪资': [8000, 12000, 15000, 18000, 20000] } df = pd.DataFrame(data) print(df) 

输出结果:

 姓名 年龄 性别 城市 薪资 0 张三 25 男 北京 8000 1 李四 30 女 上海 12000 2 王五 35 男 广州 15000 3 赵六 40 女 深圳 18000 4 钱七 45 男 杭州 20000 

这个DataFrame有5行(索引为0到4)和5列。现在,让我们详细介绍如何使用各种方法从这个DataFrame中选择特定的行数据。

loc方法详解

基本概念

loc是”location”的缩写,是基于标签(label)的数据选择方法。它允许我们通过行标签和列标签来选择数据。loc的主要特点包括:

  1. 使用标签(行名和列名)进行索引
  2. 支持布尔索引
  3. 可以接受切片对象
  4. 包含起始和结束索引(即切片是包含两端的)

基本语法

loc的基本语法是:

df.loc[row_indexer, column_indexer] 

其中:

  • row_indexer:行索引器,可以是单个标签、标签列表、标签切片或布尔数组
  • column_indexer:列索引器,可以是单个标签、标签列表、标签切片或布尔数组(可选)

使用示例

1. 选择单行数据

# 选择索引为2的行 row_2 = df.loc[2] print(row_2) 

输出:

姓名 王五 年龄 35 性别 男 城市 广州 薪资 15000 Name: 2, dtype: object 

2. 选择多行数据

# 选择索引为1和3的行 rows_1_3 = df.loc[[1, 3]] print(rows_1_3) 

输出:

 姓名 年龄 性别 城市 薪资 1 李四 30 女 上海 12000 3 赵六 40 女 深圳 18000 

3. 使用切片选择连续行

# 选择索引从1到3(包含3)的行 rows_1_to_3 = df.loc[1:3] print(rows_1_to_3) 

输出:

 姓名 年龄 性别 城市 薪资 1 李四 30 女 上海 12000 2 王五 35 男 广州 15000 3 赵六 40 女 深圳 18000 

4. 选择特定行和列

# 选择索引为1和3的行,以及'姓名'和'薪资'列 specific_rows_cols = df.loc[[1, 3], ['姓名', '薪资']] print(specific_rows_cols) 

输出:

 姓名 薪资 1 李四 12000 3 赵六 18000 

5. 使用布尔索引

# 选择年龄大于35的行 age_over_35 = df.loc[df['年龄'] > 35] print(age_over_35) 

输出:

 姓名 年龄 性别 城市 薪资 3 赵六 40 女 深圳 18000 4 钱七 45 男 杭州 20000 

6. 复杂条件选择

# 选择年龄大于30且薪资大于15000的行 complex_condition = df.loc[(df['年龄'] > 30) & (df['薪资'] > 15000)] print(complex_condition) 

输出:

 姓名 年龄 性别 城市 薪资 3 赵六 40 女 深圳 18000 4 钱七 45 男 杭州 20000 

自定义索引的示例

让我们创建一个具有自定义索引的DataFrame,看看loc如何处理:

# 创建自定义索引的DataFrame df_custom = df.set_index('姓名') print(df_custom) 

输出:

 年龄 性别 城市 薪资 姓名 张三 25 男 北京 8000 李四 30 女 上海 12000 王五 35 男 广州 15000 赵六 40 女 深圳 18000 钱七 45 男 杭州 20000 

现在,我们可以使用姓名作为行标签:

# 选择姓名为'王五'的行 row_wangwu = df_custom.loc['王五'] print(row_wangwu) 

输出:

年龄 35 性别 男 城市 广州 薪资 15000 Name: 王五, dtype: object 
# 选择姓名为'李四'和'赵六'的行 rows_lizhao = df_custom.loc[['李四', '赵六']] print(rows_lizhao) 

输出:

 年龄 性别 城市 薪资 姓名 李四 30 女 上海 12000 赵六 40 女 深圳 18000 

iloc方法详解

基本概念

iloc是”integer location”的缩写,是基于整数位置的数据选择方法。它允许我们通过行号和列号的整数位置来选择数据,类似于Python中的列表切片。iloc的主要特点包括:

  1. 使用整数位置进行索引(从0开始)
  2. 支持整数列表、切片和布尔数组
  3. 切片不包含结束索引(即切片是左闭右开的)

基本语法

iloc的基本语法是:

df.iloc[row_indexer, column_indexer] 

其中:

  • row_indexer:行索引器,可以是整数、整数列表、切片或布尔数组
  • column_indexer:列索引器,可以是整数、整数列表、切片或布尔数组(可选)

使用示例

1. 选择单行数据

# 选择第2行(索引为1,因为从0开始) row_1 = df.iloc[1] print(row_1) 

输出:

姓名 李四 年龄 30 性别 女 城市 上海 薪资 12000 Name: 1, dtype: object 

2. 选择多行数据

# 选择第1行和第3行(索引为0和2) rows_0_2 = df.iloc[[0, 2]] print(rows_0_2) 

输出:

 姓名 年龄 性别 城市 薪资 0 张三 25 男 北京 8000 2 王五 35 男 广州 15000 

3. 使用切片选择连续行

# 选择第2行到第4行(索引为1到3,不包含4) rows_1_to_3 = df.iloc[1:4] print(rows_1_to_3) 

输出:

 姓名 年龄 性别 城市 薪资 1 李四 30 女 上海 12000 2 王五 35 男 广州 15000 3 赵六 40 女 深圳 18000 

注意:与loc不同,iloc的切片不包含结束索引。

4. 选择特定行和列

# 选择第2行到第4行,以及第1列和第4列(索引为1到3,列索引为0和3) specific_rows_cols = df.iloc[1:4, [0, 3]] print(specific_rows_cols) 

输出:

 姓名 城市 1 李四 上海 2 王五 广州 3 赵六 深圳 

5. 使用步长选择行

# 选择所有奇数行(索引为1, 3) odd_rows = df.iloc[1::2] print(odd_rows) 

输出:

 姓名 年龄 性别 城市 薪资 1 李四 30 女 上海 12000 3 赵六 40 女 深圳 18000 

6. 使用布尔数组

# 创建一个布尔数组,选择第1、3、4行 bool_array = [True, False, True, True, False] bool_selection = df.iloc[bool_array] print(bool_selection) 

输出:

 姓名 年龄 性别 城市 薪资 0 张三 25 男 北京 8000 2 王五 35 男 广州 15000 3 赵六 40 女 深圳 18000 

其他数据选择方法

除了lociloc,pandas还提供了其他一些数据选择方法,如atiatix(已弃用)。

at方法

at方法用于快速获取单个值,它是loc的优化版本,专门用于访问单个值。

# 获取索引为2的行的'姓名'列的值 name_at_2 = df.at[2, '姓名'] print(name_at_2) # 输出: 王五 

iat方法

iat方法用于通过整数位置快速获取单个值,它是iloc的优化版本,专门用于访问单个值。

# 获取第3行(索引为2)第1列(索引为0)的值 value_iat = df.iat[2, 0] print(value_iat) # 输出: 王五 

ix方法(已弃用)

ix方法曾经是pandas中最常用的数据选择方法,它结合了lociloc的功能,可以根据标签或整数位置进行选择。然而,由于它的行为有时令人困惑,从pandas 0.20.0版本开始已被弃用,并在后续版本中被移除。现在推荐明确使用lociloc

实际应用案例

让我们通过一个更实际的例子来展示这些方法的应用。假设我们有一个包含销售数据的DataFrame:

# 创建销售数据DataFrame sales_data = { '日期': pd.date_range(start='2023-01-01', periods=10), '产品': ['A', 'B', 'A', 'C', 'B', 'A', 'C', 'B', 'A', 'C'], '地区': ['东', '南', '西', '北', '东', '南', '西', '北', '东', '南'], '销售额': [1200, 1500, 800, 2000, 1300, 900, 1700, 1100, 1400, 1600], '销售员': ['张三', '李四', '王五', '赵六', '张三', '李四', '王五', '赵六', '张三', '李四'] } sales_df = pd.DataFrame(sales_data) print(sales_df) 

输出:

 日期 产品 地区 销售额 销售员 0 2023-01-01 A 东 1200 张三 1 2023-01-02 B 南 1500 李四 2 2023-01-03 A 西 800 王五 3 2023-01-04 C 北 2000 赵六 4 2023-01-05 B 东 1300 张三 5 2023-01-06 A 南 900 李四 6 2023-01-07 C 西 1700 王五 7 2023-01-08 B 北 1100 赵六 8 2023-01-09 A 东 1400 张三 9 2023-01-10 C 南 1600 李四 

案例1:筛选特定产品的销售记录

# 使用loc筛选产品A的销售记录 product_a = sales_df.loc[sales_df['产品'] == 'A'] print(product_a) 

输出:

 日期 产品 地区 销售额 销售员 0 2023-01-01 A 东 1200 张三 2 2023-01-03 A 西 800 王五 5 2023-01-06 A 南 900 李四 8 2023-01-09 A 东 1400 张三 

案例2:筛选销售额在特定范围内的记录

# 使用loc筛选销售额大于等于1500的记录 high_sales = sales_df.loc[sales_df['销售额'] >= 1500] print(high_sales) 

输出:

 日期 产品 地区 销售额 销售员 1 2023-01-02 B 南 1500 李四 3 2023-01-04 C 北 2000 赵六 6 2023-01-07 C 西 1700 王五 9 2023-01-10 C 南 1600 李四 

案例3:筛选特定销售员在特定地区的销售记录

# 使用loc筛选张三在东区的销售记录 zhangsan_east = sales_df.loc[(sales_df['销售员'] == '张三') & (sales_df['地区'] == '东')] print(zhangsan_east) 

输出:

 日期 产品 地区 销售额 销售员 0 2023-01-01 A 东 1200 张三 4 2023-01-05 B 东 1300 张三 8 2023-01-09 A 东 1400 张三 

案例4:选择特定日期范围内的记录

# 将日期列设为索引 sales_df_date = sales_df.set_index('日期') # 使用loc选择2023-01-03到2023-01-07的记录 date_range = sales_df_date.loc['2023-01-03':'2023-01-07'] print(date_range) 

输出:

 产品 地区 销售额 销售员 日期 2023-01-03 A 西 800 王五 2023-01-04 C 北 2000 赵六 2023-01-05 B 东 1300 张三 2023-01-06 A 南 900 李四 2023-01-07 C 西 1700 王五 

案例5:使用iloc选择特定位置的记录

# 使用iloc选择第3到第7行(索引为2到6),以及第1、3、4列 specific_data = sales_df.iloc[2:7, [0, 2, 3]] print(specific_data) 

输出:

 日期 地区 销售额 2 2023-01-03 西 800 3 2023-01-04 北 2000 4 2023-01-05 东 1300 5 2023-01-06 南 900 6 2023-01-07 西 1700 

案例6:使用query方法进行复杂查询

除了lociloc,pandas还提供了query方法,它允许我们使用字符串表达式进行查询:

# 使用query方法筛选产品为A或C,且销售额大于1000的记录 complex_query = sales_df.query("(产品 == 'A' or 产品 == 'C') and 销售额 > 1000") print(complex_query) 

输出:

 日期 产品 地区 销售额 销售员 0 2023-01-01 A 东 1200 张三 3 2023-01-04 C 北 2000 赵六 6 2023-01-07 C 西 1700 王五 8 2023-01-09 A 东 1400 张三 9 2023-01-10 C 南 1600 李四 

性能比较和最佳实践

性能比较

在选择数据时,不同的方法可能有不同的性能表现。一般来说:

  1. atiat是访问单个值的最快方法
  2. lociloc在访问多个值时性能良好
  3. 布尔索引在大数据集上可能比列表索引更高效

让我们进行一个简单的性能比较:

import timeit # 创建一个较大的DataFrame large_df = pd.DataFrame(np.random.rand(10000, 5), columns=['A', 'B', 'C', 'D', 'E']) # 定义测试函数 def test_loc(): return large_df.loc[0:9999, 'A'] def test_iloc(): return large_df.iloc[0:10000, 0] def test_at(): result = [] for i in range(10000): result.append(large_df.at[i, 'A']) return result def test_iat(): result = [] for i in range(10000): result.append(large_df.iat[i, 0]) return result # 测试性能 loc_time = timeit.timeit(test_loc, number=100) iloc_time = timeit.timeit(test_iloc, number=100) at_time = timeit.timeit(test_at, number=10) # 减少次数因为at方法较慢 iat_time = timeit.timeit(test_iat, number=10) # 减少次数因为iat方法较慢 print(f"loc方法时间: {loc_time:.5f}秒") print(f"iloc方法时间: {iloc_time:.5f}秒") print(f"at方法时间: {at_time:.5f}秒 (执行次数为10)") print(f"iat方法时间: {iat_time:.5f}秒 (执行次数为10)") 

输出结果可能因运行环境而异,但通常情况下,iloc会比loc稍快,而atiat在访问单个值时更快,但在循环中多次使用时可能比批量操作慢。

最佳实践

  1. 明确使用场景

    • 当需要基于标签选择数据时,使用loc
    • 当需要基于整数位置选择数据时,使用iloc
    • 当只需要访问单个值时,使用atiat
  2. 避免链式索引: 链式索引(如df['A'][0])可能导致不可预测的结果和性能问题。推荐使用lociloc: “`python

    不推荐

    value = df[‘A’][0]

# 推荐 value = df.loc[0, ‘A’] value = df.iloc[0, 0]

 3. **使用布尔索引进行复杂筛选**: ```python # 不推荐 result = df.loc[(df['A'] > 0.5).values & (df['B'] < 0.5).values] # 推荐 result = df.loc[(df['A'] > 0.5) & (df['B'] < 0.5)] 
  1. 考虑使用query方法进行复杂查询: “`python

    使用loc

    result = df.loc[(df[‘A’] > 0.5) & (df[‘B’] < 0.5) & (df[‘C’] == ‘value’)]

# 使用query可能更清晰 result = df.query(“A > 0.5 and B < 0.5 and C == ‘value’”) “`

  1. 大数据集上的性能考虑
    • 对于大数据集,避免在循环中使用atiat,而是使用向量化操作
    • 如果需要多次访问相同的数据,考虑将其存储在变量中

总结

在Python pandas数据分析库中,lociloc是两个非常重要的数据选择方法,它们各有特点:

  • loc基于标签进行选择,使用行名和列名,切片包含两端
  • iloc基于整数位置进行选择,使用行号和列号,切片不包含结束索引

除了这两个主要方法,pandas还提供了atiat用于快速访问单个值,以及query方法用于使用字符串表达式进行复杂查询。

在实际应用中,选择合适的方法取决于具体的需求和数据结构。通过理解这些方法的工作原理和使用场景,我们可以更高效地从DataFrame中提取所需数据,为后续的数据分析和处理奠定基础。

掌握这些数据选择方法是pandas数据分析的基础,它们能够帮助我们更灵活、更高效地处理各种数据操作需求。希望本文的详细解释和丰富实例能够帮助读者更好地理解和应用这些方法。