Pandas--数据选择与索引

数据选择与索引

目录


基础索引操作

选择列

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

lociloc 是 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

atiat 用于快速访问单个值,比 lociloc 更快。

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 的核心功能:

  1. 基础索引 :使用 [] 选择列和行
  2. loc 和 iloc:标签索引和位置索引
  3. 布尔索引:基于条件筛选数据
  4. query 方法:类似 SQL 的查询语法
  5. at 和 iat:快速访问单个值
  6. 多级索引:处理复杂的数据结构

相关推荐
wudl55661 天前
Pandas-DataFrame 数据结构详解
数据结构·pandas
wudl55661 天前
Pandas 简介与安装
pandas
左师佑图2 天前
综合案例:Python 数据处理——从Excel文件到数据分析
开发语言·python·数据分析·excel·pandas
景早5 天前
pandas简介
pandas
懒惰蜗牛8 天前
Day10:Python实现Excel自动汇总
python·numpy·pandas·pip·1024程序员节·python读写excel
CodeCraft Studio9 天前
国产化Excel开发组件Spire.XLS教程:在Python中将Pandas DataFrame导出到Excel的详细教程
python·excel·pandas
sunbyte10 天前
从零掌握 Pandas:数据分析的黄金钥匙|01:认识Pandas
数据挖掘·数据分析·pandas
是梦终空10 天前
计算机毕业设计240—基于python+爬虫+html的微博舆情数据可视化系统(源代码+数据库)
爬虫·python·pandas·课程设计·毕业论文·计算机毕业设计·微博舆情可视化
万粉变现经纪人13 天前
如何解决 pip install -r requirements.txt 私有索引未设为 trusted-host 导致拒绝 问题
开发语言·python·scrapy·flask·beautifulsoup·pandas·pip