查看全课大纲(第 38 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.3D绘图 -- mplot3d
  82. 82.3D曲线可视化
  83. 83.3D散点图可视化
  84. 84.3D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 101.实战:通过移动设备行为数据预测性别和年龄

DataFrame的索引操作

约 11 分钟

📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)

小象实战讲义 · Python数据分析实战

上一节我们详细学习了Series的索引操作,这一节我们来看一下DataFrame的索引操作。DataFrame作为二维表格结构,其索引方式比Series更加丰富,既有列索引也有行索引,还有混合索引。掌握这些索引操作是高效进行数据筛选和提取的基础。

💡 核心导读

  • DataFrame的列索引:使用方括号直接获取单列或多列
  • DataFrame的行索引:必须使用.loc[](标签索引)或.iloc[](位置索引)
  • 混合索引:先行后列与先列后行的多种写法
  • inplace参数的作用:控制操作是否在原数据上直接修改

DataFrame的列索引

DataFrame在设计时更倾向于面向列的操作,因此直接使用方括号进行索引时,默认获取的是列数据。

import pandas as pd
import numpy as np

# 构建DataFrame
country1 = pd.Series({'Name': '中国',
                    'Language': 'Chinese',
                    'Area': '9.597M km2',
                     'Happiness Rank': 79})

country2 = pd.Series({'Name': '美国',
                    'Language': 'English (US)',
                    'Area': '9.834M km2',
                     'Happiness Rank': 14})

country3 = pd.Series({'Name': '澳大利亚',
                    'Language': 'English (AU)',
                    'Area': '7.692M km2',
                     'Happiness Rank': 9})

df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

print("完整DataFrame:")
print(df)
print()
完整DataFrame:
    Name      Language        Area  Happiness Rank
CH    中国       Chinese  9.597M km2              79
US    美国  English (US)  9.834M km2              14
AU  澳大利亚  English (AU)  7.692M km2               9

单列索引

获取单列时,直接在方括号中放入列名,返回的是一个Series对象:

import pandas as pd

# 重新构建DataFrame(每个代码块自包含)
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

# 获取'Area'列
area_series = df['Area']
print("Area列数据:")
print(area_series)
print(f"类型: {type(area_series).__name__}")
Area列数据:
CH    9.597M km2
US    9.834M km2
AU    7.692M km2
Name: Area, dtype: str
类型: Series

多列索引

获取不连续的多列时,需要在方括号中放入列名的列表,返回的是一个DataFrame:

import pandas as pd

# 重新构建DataFrame
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

# 获取'Area'和'Name'两列
area_name_df = df[['Area', 'Name']]
print("Area和Name两列数据:")
print(area_name_df)
print(f"类型: {type(area_name_df).__name__}")
Area和Name两列数据:
          Area  Name
CH  9.597M km2    中国
US  9.834M km2    美国
AU  7.692M km2  澳大利亚
类型: DataFrame

DataFrame的行索引

在DataFrame中进行行索引时,必须使用.loc[](基于标签)或.iloc[](基于位置),不能省略。这是因为DataFrame有两个索引方向(行和列),如果省略.loc/.iloc,Python会将其解释为列索引。

import pandas as pd

# 重新构建DataFrame
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

# 获取行标签为'CH'的行(中国)
row_ch = df.loc['CH']
print("行标签'CH'的数据:")
print(row_ch)
print(f"类型: {type(row_ch).__name__}")
print()

# 获取第一行(位置0,即中国)
row_first = df.iloc[0]
print("位置0(第一行)的数据:")
print(row_first)
print(f"类型: {type(row_first).__name__}")
行标签'CH'的数据:
Name                      中国
Language             Chinese
Area              9.597M km2
Happiness Rank            79
Name: CH, dtype: object
类型: Series

位置0(第一行)的数据:
Name                      中国
Language             Chinese
Area              9.597M km2
Happiness Rank            79
Name: CH, dtype: object
类型: Series

注意:无论是获取一列还是一行,返回的都是Series类型,因为它们都是一维数据。

混合索引

混合索引指的是同时指定行和列来获取特定单元格的数据。有两种方式:先行后列和先列后行。

先行后列

先使用.loc[]或.iloc[]获取行(得到一个Series),再从这个Series中获取列:

import pandas as pd

# 重新构建DataFrame
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

# 方法1: 先行后列
value1 = df.loc['CH']['Area']
print(f"df.loc['CH']['Area'] = {value1}")

# 使用iloc同理
value2 = df.iloc[0]['Area']  # iloc[0]对应第一行'CH'
print(f"df.iloc[0]['Area'] = {value2}")
df.loc['CH']['Area'] = 9.597M km2
df.iloc[0]['Area'] = 9.597M km2

先列后行

先获取列(得到一个Series),再从这个Series中获取行:

import pandas as pd

# 重新构建DataFrame
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

# 方法2: 先列后行
value3 = df['Area']['CH']
print(f"df['Area']['CH'] = {value3}")

# 在得到的Series上,可以加.loc或.iloc,效果一样
value4 = df['Area'].loc['CH']
print(f"df['Area'].loc['CH'] = {value4}")

value5 = df['Area'].iloc[0]
print(f"df['Area'].iloc[0] = {value5}")
df['Area']['CH'] = 9.597M km2
df['Area'].loc['CH'] = 9.597M km2
df['Area'].iloc[0] = 9.597M km2

两种方式的结果相同,选择哪种取决于个人习惯和代码可读性。

inplace参数的作用

Pandas中的很多操作(如drop()、replace()等)都有一个重要的参数inplace,它控制操作是否在原数据上直接修改。

默认行为:inplace=False

当inplace=False(默认值)时,操作会返回一个新的对象,原始数据保持不变:

import pandas as pd

# 创建新的DataFrame用于演示
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df_demo = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

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

# 删除Area列,默认inplace=False
df_new = df_demo.drop('Area', axis=1)
print("删除Area列后的新DataFrame:")
print(df_new)
print()

print("原始数据是否改变?")
print(df_demo)
原始数据:
    Name      Language        Area  Happiness Rank
CH    中国       Chinese  9.597M km2              79
US    美国  English (US)  9.834M km2              14
AU  澳大利亚  English (AU)  7.692M km2               9

删除Area列后的新DataFrame:
    Name      Language  Happiness Rank
CH    中国       Chinese              79
US    美国  English (US)              14
AU  澳大利亚  English (AU)               9

原始数据是否改变?
    Name      Language        Area  Happiness Rank
CH    中国       Chinese  9.597M km2              79
US    美国  English (US)  9.834M km2              14
AU  澳大利亚  English (AU)  7.692M km2               9

直接修改:inplace=True

当inplace=True时,操作会在原数据上直接修改,且没有返回值(返回None):

import pandas as pd

# 创建新的DataFrame用于演示
country1 = pd.Series({'Name': '中国', 'Language': 'Chinese', 'Area': '9.597M km2', 'Happiness Rank': 79})
country2 = pd.Series({'Name': '美国', 'Language': 'English (US)', 'Area': '9.834M km2', 'Happiness Rank': 14})
country3 = pd.Series({'Name': '澳大利亚', 'Language': 'English (AU)', 'Area': '7.692M km2', 'Happiness Rank': 9})
df_inplace = pd.DataFrame([country1, country2, country3], index=['CH', 'US', 'AU'])

print("操作前数据:")
print(df_inplace)
print()

# 删除Area列,inplace=True
result = df_inplace.drop('Area', axis=1, inplace=True)
print(f"drop操作返回值: {result}")
print()

print("操作后数据(已直接修改):")
print(df_inplace)
操作前数据:
    Name      Language        Area  Happiness Rank
CH    中国       Chinese  9.597M km2              79
US    美国  English (US)  9.834M km2              14
AU  澳大利亚  English (AU)  7.692M km2               9

drop操作返回值: None

操作后数据(已直接修改):
    Name      Language  Happiness Rank
CH    中国       Chinese              79
US    美国  English (US)              14
AU  澳大利亚  English (AU)               9

重要提示:

  • inplace=False(默认):安全,原始数据不变,需要用变量接收结果
  • inplace=True:直接修改原始数据,无返回值,使用时需谨慎
  • 如果对inplace=True的操作结果用变量接收,该变量的值会是None

📝 动手练一练

  1. 概念辨析:在DataFrame中,为什么行索引必须使用.loc[]或.iloc[],而列索引可以直接用方括号?
👉 点击查看参考答案

因为DataFrame有两个索引方向(行和列)。当使用方括号时,Pandas默认将其解释为列索引。如果省略.loc/.iloc,像df['CH']这样的写法会被理解为获取名为’CH’的列,而不是行。使用.loc[]和.iloc[]可以明确指定我们要进行的是行索引操作。

相比之下,Series只有一个索引方向(行索引),所以可以直接用方括号而不会产生歧义。

  1. 代码实践:创建一个包含学生成绩的DataFrame,然后:
    • 使用列索引获取”数学”成绩列
    • 使用行索引获取”李四”的所有成绩
    • 使用混合索引获取”王五”的”英语”成绩
    • 使用drop()方法删除”语文”列(用两种方式:创建新对象和直接修改)
👉 点击查看参考答案
import pandas as pd

# 创建学生成绩DataFrame
scores = pd.DataFrame({
    '语文': [85, 92, 78],
    '数学': [90, 88, 95],
    '英语': [88, 85, 92]
}, index=['张三', '李四', '王五'])

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

# 1. 获取"数学"成绩列
math_scores = scores['数学']
print("数学成绩列:")
print(math_scores)
print(f"类型: {type(math_scores).__name__}")
print()

# 2. 获取"李四"的所有成绩
li_si_scores = scores.loc['李四']
print("李四的所有成绩:")
print(li_si_scores)
print(f"类型: {type(li_si_scores).__name__}")
print()

# 3. 获取"王五"的"英语"成绩
wang_wu_english = scores.loc['王五']['英语']  # 或 scores['英语']['王五']
print("王五的英语成绩:", wang_wu_english)
print()

# 4. 删除"语文"列(两种方式)
# 方式1:创建新对象(默认inplace=False)
scores_no_chinese = scores.drop('语文', axis=1)
print("方式1 - 删除语文列后的新DataFrame:")
print(scores_no_chinese)
print("原始数据不变:")
print(scores)
print()

# 方式2:直接修改(inplace=True)
scores_copy = scores.copy()  # 先复制一份,避免修改原始数据
scores_copy.drop('语文', axis=1, inplace=True)
print("方式2 - 直接修改后:")
print(scores_copy)
原始数据:
    语文  数学  英语
张三  85  90  88
李四  92  88  85
王五  78  95  92

数学成绩列:
张三    90
李四    88
王五    95
Name: 数学, dtype: int64
类型: Series

李四的所有成绩:
语文    92
数学    88
英语    85
Name: 李四, dtype: int64
类型: Series

王五的英语成绩: 92

方式1 - 删除语文列后的新DataFrame:
    数学  英语
张三  90  88
李四  88  85
王五  95  92
原始数据不变:
    语文  数学  英语
张三  85  90  88
李四  92  88  85
王五  78  95  92

方式2 - 直接修改后:
    数学  英语
张三  90  88
李四  88  85
王五  95  92

本章小结

本节我们深入学习了DataFrame的索引操作,这是Pandas数据操作的核心技能之一。掌握这些索引方式,能够帮助我们高效地从复杂的数据集中提取所需信息。

📋 行动清单

  • 练习DataFrame的列索引:使用方括号获取单列和多列数据
  • 掌握行索引的两种方式:.loc[]用于标签索引,.iloc[]用于位置索引
  • 尝试混合索引:分别用先行后列和先列后行的方式获取特定单元格数据
  • 理解inplace参数:区分创建新对象和直接修改原数据的场景

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 本节课件:DataFrame的索引操作
    PDF · 264KB
    下载
  • 全套课件打包(第1-5章)
    ZIP · 12.8MB
    下载
  • 全套课件打包(第6-8章)
    ZIP · 15MB
    下载
  • 实战数据集:AppleStore 应用商城分析
    ZIP · 329KB
    下载
  • 实战数据集:女性服装电商分析
    ZIP · 2.8MB
    下载
  • Python 数据分析环境搭建指南
    PDF · 2MB
    下载
  • Scrapy 安装教程
    PDF · 12.7MB
    下载
  • 附加实战项目:AppleStore 应用商城数据分析
    ZIP · 0.3MB · ipynb + CSV 数据
    下载
  • 附加实战项目:银行电话营销数据分析
    ZIP · 0.4MB · ipynb + CSV 数据
    下载
  • 附加实战项目:女性服装电商评论数据分析
    ZIP · 2.7MB · ipynb + CSV 数据
    下载
  • 附加实战项目:美国化学学会杂志数据分析
    ZIP · 34.2MB · ipynb + SQLite 数据库
    下载