数据选择与索引
目录
- 基础索引操作
- [loc 和 iloc](#loc 和 iloc)
- 布尔索引
- 条件筛选
- [使用 query 方法](#使用 query 方法)
- [at 和 iat](#at 和 iat)
- 多级索引
- 索引操作技巧
- 实际应用示例
基础索引操作
选择列
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'城市': ['北京', '上海', '广州', '深圳'],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# 选择单列(返回 Series)
col = df['姓名']
print(col)
# 输出:
# 0 张三
# 1 李四
# 2 王五
# 3 赵六
# Name: 姓名, dtype: object
# 选择单列(返回 DataFrame)
col_df = df[['姓名']]
print(col_df)
# 选择多列
cols = df[['姓名', '工资']]
print(cols)
# 使用点号访问(列名必须是有效的 Python 标识符,且不包含空格)
df2 = pd.DataFrame({'name': ['A', 'B'], 'age': [25, 30]})
name_col = df2.name
print(name_col)
# 注意:如果列名与 DataFrame 方法重名,不能使用点号访问
# 例如,如果列名是 'count',应使用 df['count'] 而不是 df.count
选择行
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# 使用切片选择行(返回 DataFrame)
rows = df[0:2] # 选择前两行
print(rows)
# 选择最后一行
last_row = df[-1:]
print(last_row)
# 选择特定行(通过布尔索引,见下文)
loc 和 iloc
loc 和 iloc 是 Pandas 中最常用的索引方法。
loc - 基于标签的索引
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
# 选择单行
row = df.loc['a']
print(row)
# 输出:
# 姓名 张三
# 年龄 25
# 工资 8000
# Name: a, dtype: object
# 选择多行
rows = df.loc[['a', 'c']]
print(rows)
# 行切片(包含结束位置)
rows_range = df.loc['a':'c']
print(rows_range)
# 选择特定的行和列
value = df.loc['a', '姓名'] # 单个值
print(value) # 张三
subset = df.loc['a':'b', ['姓名', '工资']] # 行和列的子集
print(subset)
# 选择所有行的特定列
cols = df.loc[:, ['姓名', '工资']]
print(cols)
# 条件选择
filtered = df.loc[df['年龄'] > 30]
print(filtered)
iloc - 基于位置的索引
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# 选择单行
row = df.iloc[0]
print(row)
# 选择多行
rows = df.iloc[[0, 2]]
print(rows)
# 行切片(不包含结束位置,类似 Python 列表)
rows_range = df.iloc[0:2]
print(rows_range)
# 选择特定的行和列
value = df.iloc[0, 1] # 第 0 行,第 1 列
print(value) # 25
subset = df.iloc[0:2, [0, 2]] # 行和列的子集
print(subset)
# 选择所有行的特定列
cols = df.iloc[:, [0, 2]]
print(cols)
# 使用负数索引
last_row = df.iloc[-1]
first_two_rows = df.iloc[:-2] # 除了最后两行的所有行
loc vs iloc 对比
python
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [10, 20, 30, 40]
}, index=['x', 'y', 'z', 'w'])
# loc: 标签索引,切片包含结束位置
print(df.loc['x':'z']) # 包含 'z'
# iloc: 位置索引,切片不包含结束位置
print(df.iloc[0:2]) # 不包含位置 2
# 注意事项
# - loc 使用标签,即使标签是数字,也按标签匹配
# - iloc 使用位置,总是从 0 开始
布尔索引
布尔索引是 Pandas 中非常强大的功能,允许根据条件选择数据。
基本布尔索引
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# 创建布尔 Series
mask = df['年龄'] > 30
print(mask)
# 输出:
# 0 False
# 1 False
# 2 True
# 3 False
# Name: 年龄, dtype: bool
# 使用布尔索引选择行
filtered = df[mask]
print(filtered)
# 输出:
# 姓名 年龄 工资
# 2 王五 35 10000
# 直接使用条件
filtered = df[df['年龄'] > 30]
print(filtered)
多条件筛选
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# AND 条件(使用 &)
filtered = df[(df['年龄'] > 25) & (df['工资'] > 10000)]
print(filtered)
# OR 条件(使用 |)
filtered = df[(df['年龄'] > 30) | (df['工资'] < 9000)]
print(filtered)
# NOT 条件(使用 ~)
filtered = df[~(df['年龄'] > 30)]
print(filtered)
# 复杂条件
filtered = df[((df['年龄'] > 25) & (df['年龄'] < 35)) | (df['工资'] > 11000)]
print(filtered)
# 注意:多个条件必须用括号括起来
# 错误:df[df['年龄'] > 25 & df['工资'] > 10000] # 会报错
# 正确:df[(df['年龄'] > 25) & (df['工资'] > 10000)]
使用 isin 方法
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'城市': ['北京', '上海', '广州', '深圳'],
'工资': [8000, 12000, 10000, 11000]
}
df = pd.DataFrame(data)
# 选择特定值
filtered = df[df['城市'].isin(['北京', '上海'])]
print(filtered)
# 否定条件
filtered = df[~df['城市'].isin(['北京', '上海'])]
print(filtered)
# 多个列使用 isin
filtered = df[df[['城市', '姓名']].isin(['北京', '张三']).any(axis=1)]
print(filtered)
条件筛选
字符串条件筛选
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'城市': ['北京', '上海', '广州', '深圳']
}
df = pd.DataFrame(data)
# 包含特定字符串
filtered = df[df['姓名'].str.contains('三')]
print(filtered)
# 以特定字符串开头
filtered = df[df['城市'].str.startswith('北')]
print(filtered)
# 以特定字符串结尾
filtered = df[df['城市'].str.endswith('海')]
print(filtered)
# 匹配正则表达式
filtered = df[df['姓名'].str.match('^张')]
print(filtered)
# 忽略大小写
df_en = pd.DataFrame({'name': ['Alice', 'Bob', 'alice']})
filtered = df_en[df_en['name'].str.contains('alice', case=False)]
print(filtered)
数值条件筛选
python
import pandas as pd
import numpy as np
data = {
'姓名': ['张三', '李四', '王五', '赵六', '孙七'],
'年龄': [25, 30, 35, 28, 32],
'工资': [8000, 12000, 10000, 11000, 9500]
}
df = pd.DataFrame(data)
# 范围筛选
filtered = df[(df['年龄'] >= 28) & (df['年龄'] <= 32)]
print(filtered)
# 使用 between
filtered = df[df['年龄'].between(28, 32, inclusive='both')]
print(filtered)
# 查找最值
max_age_row = df[df['年龄'] == df['年龄'].max()]
print(max_age_row)
min_age_row = df[df['年龄'] == df['年龄'].min()]
print(min_age_row)
# 查找前 N 个最大/最小值
top3 = df.nlargest(3, '工资')
print(top3)
bottom2 = df.nsmallest(2, '年龄')
print(bottom2)
# 排除异常值
Q1 = df['工资'].quantile(0.25)
Q3 = df['工资'].quantile(0.75)
IQR = Q3 - Q1
filtered = df[(df['工资'] >= Q1 - 1.5*IQR) & (df['工资'] <= Q3 + 1.5*IQR)]
print(filtered)
使用 query 方法
query 方法提供了类似 SQL 的查询语法,使条件筛选更加直观。
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'工资': [8000, 12000, 10000, 11000],
'城市': ['北京', '上海', '广州', '深圳']
}
df = pd.DataFrame(data)
# 简单条件
result = df.query('年龄 > 30')
print(result)
# AND 条件
result = df.query('年龄 > 25 and 工资 > 10000')
print(result)
# OR 条件
result = df.query('年龄 > 30 or 工资 < 9000')
print(result)
# 字符串条件
result = df.query("城市 == '北京'")
print(result)
# 使用变量
age_threshold = 30
result = df.query('年龄 > @age_threshold') # 使用 @ 引用外部变量
print(result)
# 复杂条件
result = df.query('(年龄 > 25 and 年龄 < 35) or 工资 > 11000')
print(result)
# 多列条件
result = df.query('年龄 > 年龄.mean()') # 使用列的方法
print(result)
at 和 iat
at 和 iat 用于快速访问单个值,比 loc 和 iloc 更快。
at - 基于标签的快速访问
python
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [10, 20, 30]
}, index=['x', 'y', 'z'])
# 获取单个值
value = df.at['x', 'A']
print(value) # 1
# 设置单个值
df.at['x', 'A'] = 100
print(df)
iat - 基于位置的快速访问
python
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [10, 20, 30]
})
# 获取单个值
value = df.iat[0, 1]
print(value) # 10
# 设置单个值
df.iat[0, 1] = 100
print(df)
性能对比
python
import pandas as pd
import time
df = pd.DataFrame(range(1000000)).T
# 使用 loc(较慢)
start = time.time()
for i in range(1000):
value = df.loc[0, i]
print(f"loc: {time.time() - start:.4f} 秒")
# 使用 at(较快)
start = time.time()
for i in range(1000):
value = df.at[0, i]
print(f"at: {time.time() - start:.4f} 秒")
多级索引
创建多级索引
python
import pandas as pd
import numpy as np
# 创建多级索引
arrays = [['A', 'A', 'B', 'B'], [1, 2, 1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=['字母', '数字'])
df = pd.DataFrame(np.random.randn(4, 3), index=index, columns=['X', 'Y', 'Z'])
print(df)
# 使用 loc 选择多级索引
result = df.loc['A']
print(result)
result = df.loc[('A', 1)]
print(result)
result = df.loc[('A', 1):('B', 1)]
print(result)
# 使用 xs 方法
result = df.xs('A', level='字母')
print(result)
result = df.xs(1, level='数字')
print(result)
索引操作技巧
1. 重置索引
python
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [10, 20, 30]
}, index=['x', 'y', 'z'])
# 重置为默认整数索引
df_reset = df.reset_index()
print(df_reset)
# 不保留原索引
df_reset = df.reset_index(drop=True)
print(df_reset)
# 重置索引并添加到列
df = df.reset_index()
print(df)
2. 设置索引
python
import pandas as pd
df = pd.DataFrame({
'ID': [1, 2, 3],
'姓名': ['张三', '李四', '王五'],
'年龄': [25, 30, 35]
})
# 设置索引
df_indexed = df.set_index('ID')
print(df_indexed)
# 设置多级索引
df_multi = df.set_index(['ID', '姓名'])
print(df_multi)
3. 重命名索引和列
python
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [10, 20, 30]
}, index=['x', 'y', 'z'])
# 重命名索引
df_renamed = df.rename(index={'x': 'X', 'y': 'Y'})
print(df_renamed)
# 重命名列
df_renamed = df.rename(columns={'A': 'Column_A'})
print(df_renamed)
# 同时重命名
df_renamed = df.rename(index={'x': 'X'}, columns={'A': 'Column_A'})
print(df_renamed)
实际应用示例
示例 1:股票数据筛选
python
import pandas as pd
import numpy as np
# 创建股票数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=100, freq='D')
stocks = pd.DataFrame({
'日期': dates,
'股票代码': np.random.choice(['000001', '000002', '600000'], 100),
'收盘价': np.random.uniform(10, 100, 100),
'成交量': np.random.randint(1000000, 10000000, 100)
})
# 筛选特定股票
stock_000001 = stocks[stocks['股票代码'] == '000001']
print(stock_000001.head())
# 筛选价格高于均价的记录
mean_price = stocks['收盘价'].mean()
high_price = stocks[stocks['收盘价'] > mean_price]
print(f"价格高于均价的记录数: {len(high_price)}")
# 筛选成交量最大的前 10 条
top10_volume = stocks.nlargest(10, '成交量')
print(top10_volume)
# 筛选特定日期范围
start_date = '2024-01-15'
end_date = '2024-01-30'
date_range = stocks[(stocks['日期'] >= start_date) & (stocks['日期'] <= end_date)]
print(date_range)
示例 2:员工数据分析
python
import pandas as pd
employees = pd.DataFrame({
'员工ID': ['E001', 'E002', 'E003', 'E004', 'E005'],
'姓名': ['张三', '李四', '王五', '赵六', '孙七'],
'部门': ['销售', '技术', '销售', '技术', '销售'],
'年龄': [25, 30, 35, 28, 32],
'工资': [8000, 12000, 10000, 11000, 9500],
'绩效': [85, 92, 88, 90, 87]
})
# 筛选高绩效员工
high_performance = employees[employees['绩效'] >= 90]
print("高绩效员工:")
print(high_performance[['姓名', '部门', '绩效']])
# 筛选各部门工资最高的员工
dept_max_salary = employees.loc[employees.groupby('部门')['工资'].idxmax()]
print("\n各部门工资最高员工:")
print(dept_max_salary)
# 筛选特定条件的员工组合
target_employees = employees[
(employees['部门'] == '销售') &
(employees['年龄'] < 30) &
(employees['工资'] < 10000)
]
print("\n符合条件的员工:")
print(target_employees)
# 使用 query 方法
target = employees.query('部门 == "技术" and 绩效 > 85')
print("\n技术部门高绩效员工:")
print(target)
总结
数据选择与索引是 Pandas 的核心功能:
- 基础索引 :使用
[]选择列和行 - loc 和 iloc:标签索引和位置索引
- 布尔索引:基于条件筛选数据
- query 方法:类似 SQL 的查询语法
- at 和 iat:快速访问单个值
- 多级索引:处理复杂的数据结构