欢迎光临白事网
详情描述

lociloc 是 Pandas 中两个最常用的索引器,它们的主要区别在于索引方式不同:

核心区别

特性 loc iloc
索引方式 标签索引 位置索引
语法 [行标签, 列标签] [行位置, 列位置]
包含范围 包含结束位置 不包含结束位置
切片 'A':'C'(包含C) 0:3(包含0,1,2,不包含3)
索引类型 索引名、布尔数组 整数位置、布尔数组

代码示例

1. 基本使用

import pandas as pd
import numpy as np

# 创建示例数据
df = pd.DataFrame({
    'A': [1, 2, 3, 4, 5],
    'B': [10, 20, 30, 40, 50],
    'C': [100, 200, 300, 400, 500]
}, index=['a', 'b', 'c', 'd', 'e'])

print("原始数据:")
print(df)

2. 单行/单列选择

# loc - 使用标签
print("\n=== loc 示例 ===")
print("df.loc['c']:")  # 选择行'c'
print(df.loc['c'])

print("\ndf.loc[:, 'B']:")  # 选择列'B'
print(df.loc[:, 'B'])

# iloc - 使用位置
print("\n=== iloc 示例 ===")
print("df.iloc[2]:")  # 选择第2行(0-based)
print(df.iloc[2])

print("\ndf.iloc[:, 1]:")  # 选择第1列
print(df.iloc[:, 1])

3. 切片操作

print("\n=== 切片比较 ===")
# loc 切片(包含结束位置)
print("df.loc['b':'d']:")  # 包含'd'
print(df.loc['b':'d'])

# iloc 切片(不包含结束位置)
print("\ndf.iloc[1:4]:")  # 位置1,2,3(不包含4)
print(df.iloc[1:4])

# 行列组合切片
print("\ndf.loc['b':'d', 'A':'B']:")
print(df.loc['b':'d', 'A':'B'])

print("\ndf.iloc[1:4, 0:2]:")
print(df.iloc[1:4, 0:2])

4. 布尔索引

print("\n=== 布尔索引 ===")
# 两者都支持布尔数组
mask = df['A'] > 2
print("df.loc[mask]:")
print(df.loc[mask])

print("\ndf.iloc[mask.values]:")
print(df.iloc[mask.values])

5. 混合选择

print("\n=== 混合选择 ===")
# 选择特定行和列
print("df.loc[['a', 'c', 'e'], ['A', 'C']]:")
print(df.loc[['a', 'c', 'e'], ['A', 'C']])

print("\ndf.iloc[[0, 2, 4], [0, 2]]:")
print(df.iloc[[0, 2, 4], [0, 2]])

6. 赋值操作

print("\n=== 赋值操作 ===")
# 复制一份数据用于修改
df_copy = df.copy()

# 使用 loc 赋值
df_copy.loc['b':'d', 'A'] = [99, 99, 99]
print("使用 loc 赋值后:")
print(df_copy)

# 使用 iloc 赋值
df_copy.iloc[1:4, 0] = [88, 88, 88]
print("\n使用 iloc 赋值后:")
print(df_copy)

7. 实际应用场景

print("\n=== 实际应用场景 ===")

# 场景1:处理时间序列数据(适合用 loc)
dates = pd.date_range('2023-01-01', periods=5, freq='D')
df_time = pd.DataFrame({
    'price': [100, 102, 101, 105, 103],
    'volume': [1000, 1200, 900, 1500, 1100]
}, index=dates)

print("时间序列数据:")
print(df_time)
print("\n选择特定日期范围:")
print(df_time.loc['2023-01-02':'2023-01-04'])

# 场景2:处理有序整数索引(适合用 iloc)
print("\n=== 有序数据 ===")
print("获取前3行:")
print(df.iloc[:3])

print("\n获取最后2行:")
print(df.iloc[-2:])

8. 常见错误

print("\n=== 常见错误 ===")

# 错误1:使用整数标签时混淆
df_int_index = pd.DataFrame({'A': [1, 2, 3]}, index=[10, 20, 30])

try:
    # 这可能会引起混淆
    print(df_int_index.loc[1])  # 错误!会尝试找标签1,而不是位置1
except KeyError as e:
    print(f"错误: {e}")

# 正确做法
print("\n正确做法:")
print("df_int_index.iloc[1]:")  # 使用位置索引
print(df_int_index.iloc[1])
print("\ndf_int_index.loc[20]:")  # 使用标签索引
print(df_int_index.loc[20])

# 错误2:切片范围理解错误
print("\n=== 切片范围理解 ===")
print("loc['a':'c'] 包含 'a', 'b', 'c'")
print("iloc[0:3] 包含 0, 1, 2(不包含3)")

最佳实践建议

选择依据

  • 当索引有明确的业务含义(如日期、名称)时,使用 loc
  • 当只需要按位置选择时,使用 iloc

性能考虑

  • 对于大数据集,iloc 通常比 loc 稍快
  • 但可读性和意图明确更重要

代码清晰

# 清晰明确的代码
df.loc[df['score'] > 90, ['name', 'grade']]

# 使用 iloc 实现相同的选择(但不推荐,可读性差)
mask = df['score'] > 90
col_indices = [df.columns.get_loc('name'), df.columns.get_loc('grade')]
df.iloc[mask.values, col_indices]

避免混用

# 不推荐:混合使用可能造成混淆
# df.loc[0:5]  # 如果索引是整数,这可能会按标签选择,而不是位置

# 明确区分
df.iloc[0:5]  # 按位置选择
df.loc['2023-01-01':'2023-01-05']  # 按标签选择

总结表格

场景 推荐使用 原因
按行/列名选择 loc 语义明确,可读性好
按位置选择 iloc 简单直接
布尔索引 两者均可 根据具体情况选择
时间序列数据 loc 方便按日期范围选择
连续范围选择 根据索引类型选择 整数索引时注意区分

记住:loc 是基于标签的,iloc 是基于位置的。选择哪个取决于你是想通过"名字"还是"位置"来访问数据。

相关帖子