news 2026/2/6 20:20:17

动手学数据分析:实战系列(第二天)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动手学数据分析:实战系列(第二天)

复习:数据分析的第一步,加载数据我们已经学习完毕了。当数据展现在我们面前的时候,我们所要做的第一步就是认识他,今天我们要学习的就是了解字段含义以及初步观察数据

本文引用数据信息,及文章内容来源请先阅读动手学数据分析一

1 第一章:pandas基础

1.4 知道你的数据叫什么——Series 和 DataFrame 初认识

在这一部分,你会学到:

  • pandas的两个核心数据结构:Series(一维)DataFrame(二维表格),理解它们分别长什么样、适合装什么数据。
  • 能自己写出简单示例:
    • 用字典创建Series(如州名 → 数值映射)。
    • 用字典创建DataFrame(如 state/year/pop 这样的表格数据)。
  • 重新加载train.csv或上一节保存好的train_chinese.csv,并通过df.columns查看每一列的列名。
  • 学会两种访问列的方式,并理解它们的区别:
    • 字典访问法:df['Cabin']
    • 属性访问法:df.Cabin
      知道什么时候必须用中括号索引(列名有空格、特殊字符、想用变量名等)。
  • 学会对比两个 DataFrame(如traintest_1)的列差异:
    • 用集合运算找出“测试集中多出的列”。
    • 用多种方式删除多余列:deldrop(columns=...)pop()或“只保留需要的列”的思路。
    • 理解Unnamed: 0这类列名出现的原因:通常是保存时把索引写进 CSV、读取时又没指定index_col导致的。
  • df.drop([...], axis=1)实现“临时隐藏几列只看其他列”,并理解:
    • 不加inplace=True时,只是返回一个“修改后的视图/新对象”,原df不会被真正改动。
    • 何时适合用inplace=True做“原地修改”。
1.5 筛选的逻辑——用条件把数据“挑”出来

在这一部分,你会学到:

  • 利用布尔条件对 DataFrame 做行筛选:
    • 例如:df[df["Age"] < 10]获取 10 岁以下乘客。
  • 构造多条件筛选,并用逻辑运算符组合条件:
    • 使用&表示“同时满足”(交集),|表示“满足其一”(并集),~表示取反。
    • 理解为什么每个条件外面都必须加一层括号。
    • 完成“10 < Age < 50”的区间筛选,并将结果命名为midage
  • 使用reset_index()重置筛选后 DataFrame 的索引:
    • 理解原索引可能是不连续、不是 0 开始的。
    • 明白reset_index()reset_index(drop=True)的区别:一个保留旧索引为列,一个直接丢弃。
    • 知道何时需要先重置索引,再按“行号感觉”的方式去定位行。
  • 使用loc按“标签”选取数据:
    • 例如选出midage中第 100 行指定列("Pclass""Sex")的数据。
    • 以及多行多列组合选择:loc[[100, 105, 108], ['Pclass', 'Name', 'Sex']]
  • 使用iloc按“位置”选取数据:
    • 例如用iloc[[100,105,108],[2,3,4]]通过“行号 + 列号”的方式选择相同的数据。
  • 通过对比lociloc,理解它们的关键区别:
    • loc:按标签(行索引名、列名)选取。
    • iloc:按位置(整数下标)选取。
    • 切片区间在loc中是闭区间,在iloc中是左闭右开

1.4 知道你的数据叫什么

我们学习pandas的基础操作,那么上一节通过pandas加载之后的数据,其数据类型是什么呢?

1.4.1 任务一:pandas中有两个数据类型DataFrame和Series,通过查找简单了解他们。然后自己写一个关于这两个数据类型的小例子🌰[开放题]
importnumpyasnpimportpandasaspd
sdata={'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}example_1=pd.Series(sdata)example_1
data={'state':['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],'year':[2000,2001,2002,2001,2002,2003],'pop':[1.5,1.7,3.6,2.4,2.9,3.2]}example_2=pd.DataFrame(data)example_2
  • Pandas 主要有两个核心数据结构DataFrame和Series 的介绍

Pandas 主要有两个核心数据结构,以及存储在这些结构中的底层数据类型(dtypes)

1. 核心数据结构 (Data Structures)

这是 Pandas 中最常用的两个对象:

  • Series (序列)

    • 定义:一维数组对象。
    • 理解:可以把它看作是 Excel 表格中的一列,或者是一个带标签(索引)的 Python 列表。
    • 组成:由一组数据(Values)和一组与之相关的数据标签(Index)组成。
    • 代码示例(参考你的example_1):
    # 创建 Seriess=pd.Series([1,3,5,np.nan,6,8])
  • DataFrame (数据框)

  • 定义:二维表格型数据结构。

  • 理解:可以把它看作是整个Excel 表格或 SQL 表。

  • 组成:它既有行索引(Index),也有列索引(Columns)。你可以把它看作是由多个 Series 组成的字典(共用同一个行索引)。

  • 代码示例(参考你的example_2):

# 创建 DataFramedf=pd.DataFrame({'A':1.,'B':pd.Timestamp('20130102'),'C':pd.Series(1,index=list(range(4)),dtype='float32')})
2. 底层数据类型 (Dtypes)

这是指存储在 Series 或 DataFrame 单元格中的具体数值类型。你可以通过df.dtypes查看。常见的包括:

  • object:通常代表字符串(String),或者是混合类型的数据。
  • int64:整数(Integer)。
  • float64:浮点数(Float),即带小数点的数字。
  • bool:布尔值(True/False)。
  • datetime64:日期时间类型。
1.4.2 任务二:根据上节课的方法载入"train.csv"文件
df=pd.read_csv('./train.csv')df.head(3)

也可以加载上一节课保存的"train_chinese.csv"文件。

1.4.3 任务三:查看DataFrame数据的每列的名称
df.columns
1.4.4任务四:查看"Cabin"这列的所有值 [有多种方法]
# 字典访问法df['Cabin'].head(3)
# 属性访问法 / 点号法df.Cabin.head(3)
  • df['Cabin'].head(3)、 df.Cabin.head(3)这两种方法的区别

这两种方法在当前这个例子中(访问名为 “Cabin” 的列)效果是完全一样的,都返回该列的数据。

但是,它们在适用场景灵活性上有很大的区别。以下是详细对比:

1.df['Cabin'](方括号法 / 字典访问法)

这是最通用、最推荐的方法。

  • 优点

    • 支持任意列名:如果列名包含空格(如"First Name")、特殊符号(如"Price($)")或数字开头,必须用这种方法。

    • 支持变量:可以使用变量来动态访问列。

      col_name='Cabin'df[col_name]# 可行
    • 创建新列:必须用这种方法来添加新列。

      df['New_Column']=1# 创建成功
    • 避免冲突:如果列名和 Pandas 的内置方法名重名(比如列名叫count,sum,class),这种方法依然能准确获取列数据。

2.df.Cabin(属性访问法 / 点号法)

这是一种语法糖(Syntactic Sugar),主要是为了写起来方便。

  • 优点

    • 书写快捷:少打两个引号和两个括号。
    • 代码补全:在 Jupyter Notebook 或 IDE 中,输入df.后按 Tab 键通常能自动补全列名。
  • 缺点(局限性)

    • 不支持特殊列名:如果列名有空格(df.First Name❌)或特殊字符,会报错。
    • 不能创建新列df.New_Column = 1只会给df对象添加一个普通的 Python 属性,而不会在 DataFrame 数据结构中真正添加一列数据。
    • 容易冲突:如果你的列名叫做shapeindexT或者count,使用df.shape访问的是 DataFrame 的形状属性,而不是名为 “shape” 的那一列数据。
总结建议
  • 日常快速查看数据且列名规范(无空格、非关键字)时,可以用df.ColumnName
  • 编写正式脚本处理复杂列名创建新列时,请务必使用df['ColumnName']
1.4.5 任务五:加载文件"test_1.csv",然后对比"train.csv",看看有哪些多出的列,然后将多出的列删除

手动打印表头(df.columns)进行肉眼对比

经过我们的观察发现一个测试集test_1.csv有一列是多余的,我们需要将这个多余的列删去

test_1=pd.read_csv('test_1.csv')test_1.head(3)
# 删除多余的列deltest_1['a']test_1.head(3)

【思考】还有其他的删除多余的列的方式吗?

以下是三种删除多余列的方法
为避免和上文方法冲突,这里对三种方法进行了注释,想要测试先注释掉其他删除方法,再重新运行程序。

  1. 使用 drop() 函数(最推荐)这是最标准的方法,因为它不会像 del 那样直接修改原数据(除非你指定 inplace=True),这在数据处理管道中更安全。
''' #思考回答 # 方法 A:返回一个新的 DataFrame(不改变原数据) test_1_clean = test_1.drop(['a'], axis=1) # 方法 B:直接在原数据上修改(加上 inplace=True) test_1.drop(['a'], axis=1, inplace=True) # 方法 C:使用 columns 参数(更直观,不需要写 axis=1) test_1.drop(columns=['a'], inplace=True) # axis 参数用于指定操作的方向(行还是列)。 # axis=0 (默认):代表 行 (Rows/Index)。也就是纵向 ↓。 # axis=1:代表 列 (Columns)。也就是横向 →。 '''
  1. 使用 pop() 方法
    这个方法会删除列,同时把被删除的列作为返回值弹出来。如果你需要把删掉的数据存起来备用,这个方法很有用。
# 删除 'a' 列,并把它的数据赋值给 deleted_col# deleted_col = test_1.pop('a')
  1. 列表切片/筛选(保留法)与其说是“删除”,不如说是“只保留想要的”。当你需要删除的列很多,而保留的列很少时,这种方法最快。
# 只保留 'PassengerId' 和 'Survived',其他的都不要了# test_1 = test_1[['PassengerId', 'Survived']]
总结对比
方法特点适用场景
del df['col']Python 原生语法,直接修改原数据,无返回值。快速删除单列,确定不再需要原数据。
df.drop()Pandas 专用,功能强大,支持多列,默认不修改原数据。最通用,特别是需要删除多列或在链式调用中。
df.pop()删除并返回该列数据。删除的同时还需要用到这列数据。
df[['col1']]筛选保留。需要删除的列比保留的列多得多时。
补充:在Pandas 中如何高效、编程化地对比两个 DataFrame 的列差异?

使用 Python 的集合(Set)操作来快速找出不同之处。

方法:使用集合操作 (Set Operations)

集合操作可以让你瞬间找出:

  1. A 有但 B 没有的列(差集)
  2. B 有但 A 没有的列(差集)
  3. 两者共有的列(交集)
  4. 两者所有的列(并集)

假设你有两个 DataFrame:traintest_1

# 获取列名集合train_cols=set(df.columns)test_cols=set(test_1.columns)# 1. 找出 test_1 中多出的列 (test_1 有但 train 没有)diff=test_cols-train_colsprint(f"test_1 多出的列:{diff}")# 2. 找出 train 中多出的列 (train 有但 test_1 没有)# diff_2 = train_cols - test_cols# print(f"train 多出的列: {diff_2}")
为什么这种方法更高效?
  • 自动化:不需要人工逐个单词去核对,避免眼花看错。
  • 直接可用:结果是一个集合或列表,你可以直接把这个结果传给drop()函数来删除多余的列。

这里不显示多余的列是因为 如果按顺序执行该程序 那么不同的列在上方已经被删除了.你需要注释或者删除上方程序后重新运行。

# 找出 test_1 中多余的列extra_columns=set(test_1.columns)-set(df.columns)print(f"多余的列是:{extra_columns}")# 如果想直接删除这些多余的列# test_1.drop(columns=extra_columns, inplace=True)
  • 输出解释'Unnamed: 0'
  • 这是 Pandas 读取 CSV 文件时非常常见的一个现象。

现在去观察一下你输入的两个.csv文件,train.csv的第一列是PassengerId,然而train_1.csv的第一列是一个无列名的序号列

所以读取时就会看到一个叫Unnamed: 0的列。
你可以在 CSV 里给这一列补上列名(比如“序号”),再重新读取一次,对比一下输出,就会更直观地理解这个现象。

它的含义是:
这通常是 CSV 文件中原本就存在的索引列(Index Column),但在保存时没有给它起名字,或者读取时没有指定它为索引。

详细解释
  1. 来源
    当你使用df.to_csv('filename.csv')保存文件时,默认情况下 Pandas 会把 DataFrame 的行索引(0, 1, 2, …)也保存进 CSV 文件,作为第一列。
    因为行索引通常没有名字,所以 CSV 文件的第一行(表头)的第一个位置是空的。

  2. 读取时的表现
    当你再次用pd.read_csv('filename.csv')读取这个文件时,Pandas 发现第一列有数据但表头是空的,它就会自动给这一列起一个名字,叫做Unnamed: 0(意思是:第 0 个没有名字的列)。

如何解决/避免?

你有以下几种方法处理它:

方法一:读取时指定索引(推荐)
告诉 Pandas 第一列就是索引,不要把它当成普通数据列读取。

# index_col=0 表示把第0列作为行索引test_1=pd.read_csv('test_1.csv',index_col=0)

方法二:保存时不保存索引
如果你不需要保存行索引(通常 0,1,2… 这种默认索引是不需要保存的),在保存时加上index=False

# 保存时丢弃索引df.to_csv('filename.csv',index=False)

方法三:读取后删除(你现在的做法)
既然已经读进来了,就把它删掉。

# 把它加入到要删除的列表中deltest_1['Unnamed: 0']# 或者test_1.drop(columns=['Unnamed: 0'],inplace=True)
1.4.6 任务六: 将[‘PassengerId’,‘Name’,‘Age’,‘Ticket’]这几个列元素隐藏,只观察其他几个列元素
df.drop(['PassengerId','Name','Age','Ticket'],axis=1).head(3)

【思考】对比任务五和任务六,是不是使用了不一样的方法(函数),如果使用一样的函数如何完成上面的不同的要求呢?

【思考回答】

如果你希望在原 DataFrame 上永久删除这些列,可以在drop()中使用inplace=True

本小节只是想“暂时隐藏这几列看一眼效果”,所以不加inplace,让原数据保持不变。

# 思考回答df.head(3)

1.5 筛选的逻辑

对于表格数据,最重要的能力之一就是筛选:把自己需要的信息挑出来,把当前分析不关心的先丢在一边。

下面还是用实战的方式,一边写代码一边体会 pandas 的筛选能力。

1.5.1 任务一: 我们以"Age"为筛选条件,显示年龄在10岁以下的乘客信息。
df[df["Age"]<10].head(3)
1.5.2 任务二: 以"Age"为条件,将年龄在10岁以上和50岁以下的乘客信息显示出来,并将这个数据命名为midage
midage=df[(df["Age"]>10)&(df["Age"]<50)]midage.head(3)

【提示】了解pandas的条件筛选方式以及如何使用交集和并集操作

在 Pandas 中进行条件筛选(Boolean Indexing)时,逻辑运算与 Python 原生的and/or有所不同。

以下是核心规则和操作方式:

1. 核心逻辑符号

Pandas 使用位运算符来处理向量化的逻辑操作:

  • 交集 (AND):使用符号&
    • 含义:同时满足所有条件。
  • 并集 (OR):使用符号|(竖线)
    • 含义:只要满足其中一个条件即可。
  • 取反 (NOT):使用符号~(波浪号)
    • 含义:排除满足该条件的数据。

2. !!!极其重要的语法规则:括号()

这是新手最容易报错的地方:每个独立的条件必须用括号括起来

  • 错误写法

    df[df['Age']>10&df['Age']<50]# 报错原因:Python 中 & 的优先级比 > 高,# 它会先尝试计算 10 & df['Age'],导致逻辑混乱。
  • 正确写法

df[(df['Age']>10)&(df['Age']<50)]

3. 实战示例

假设我们要处理泰坦尼克号的数据:

A. 交集 (AND) - 你的任务二

筛选年龄在 10 岁到 50 岁之间的人(大于10小于50):

# 两个条件都必须为 Truemidage=df[(df["Age"]>10)&(df["Age"]<50)]

B. 并集 (OR)

筛选“小孩”或者“老人”(小于 10 岁或者大于 50 岁):

# 只要满足其中一个条件就保留extreme_age=df[(df["Age"]<10)|(df["Age"]>50)]

C. 列表筛选 (isin)

如果你要筛选某个字段等于多个特定值(比如筛选 1 等舱和 3 等舱),用isin()更简洁,它本质上也是一种并集:

# 等同于 (df["Pclass"] == 1) | (df["Pclass"] == 3)df[df["Pclass"].isin([1,3])]
1.5.3 任务三:将midage的数据中第100行的"Pclass"和"Sex"的数据显示出来
midage=midage.reset_index(drop=True)midage.head(3)

reset_index(drop=True) 的作用是将 midage 的索引重置为默认的整数索引(0, 1, 2, …),并且不保留原有的索引列(因为 drop=True)。

这样做可以让 midage 的索引变得连续、规范,方便后续按位置(或标签)访问或数据处理,避免因索引混乱导致的错误。

如果不加 drop=True(即写成 midage = midage.reset_index()),原有的索引会被还原为一列,变成 DataFrame 的普通数据列,而不是被直接丢弃。

具体表现为:

  • 新的 DataFrame 会多出一列名为 “index”(或原索引名),内容是原来的索引值。
  • 索引会被重置为默认的 0, 1, 2, …。

这样做的结果是,原索引信息不会丢失,而是以新的一列保留在数据中。如果你不需要原索引,建议加 drop=True,否则会多出一列。

简要总结:
这行代码让 midage 的索引变为默认的连续数字索引,并且丢弃原来的索引,不再作为新的一列保留。

【思考】这个reset_index()函数的作用是什么?如果不用这个函数,下面的任务会出现什么情况?

reset_index() 函数是 Pandas DataFrame 的一个方法,主要作用是将索引(index)还原为普通列,并生成新的默认整数索引。常见用法有:

  • df.reset_index():将当前索引变为普通列,索引重置为默认的 0, 1, 2, …
  • df.reset_index(drop=True):将索引重置为默认整数索引,但不保留原索引为列。

如果不用 reset_index(),在某些操作(如 groupby、set_index、过滤等)后,DataFrame 的索引可能不是默认的整数索引,而是某些列的值或多级索引。这样会导致:

  • 数据显示时索引不是连续数字,可能影响可读性。
  • 后续按位置(如 iloc)或合并、可视化等操作时,索引不规范可能导致报错或结果异常。
  • 某些情况下,索引列不会参与普通的列运算或输出,容易遗漏。

举例说明:

假设 groupby 后:

df2=df.groupby('A').sum()print(df2)

此时 ‘A’ 变成了索引。如果你想让 ‘A’ 重新变成普通列,可以用:

df2=df2.reset_index()

如果不 reset_index,后续用 df2[‘A’] 会报错,因为 ‘A’ 只是索引,不是普通列。

总结:reset_index() 让索引变回普通列,保证数据结构统一,便于后续处理。如果不用,可能导致数据操作和结果出现问题。

# 将midage的数据中第100行的"Pclass"和"Sex"的数据显示出来midage.loc[[100],['Pclass','Sex']]
1.5.4 任务四:使用loc方法将midage的数据中第100,105,108行的"Pclass","Name"和"Sex"的数据显示出来
midage.loc[[100,105,108],['Pclass','Name','Sex']]
1.5.5 任务五:使用iloc方法将midage的数据中第100,105,108行的"Pclass","Name"和"Sex"的数据显示出来
midage.iloc[[100,105,108],[2,3,4]]

【思考】对比ilocloc的异同

ilocloc都是 Pandas 中用于选取 DataFrame 或 Series 数据的索引器

相同点:

  • 都可以用于行、列的选取和切片。
  • 都支持单个、多个、切片、布尔数组等多种索引方式。

不同点:

iloc(integer location)loc(label location)
索引方式只能用整数位置(0, 1, 2, …)用标签(行/列名)
包含性切片时,结尾不包含(左闭右开)切片时,结尾包含(左闭右闭)
典型用法df.iloc[0:3, 1:3]df.loc[‘a’:‘c’, ‘col1’:‘col3’]
错误类型超出范围时报 IndexError标签不存在时报 KeyError

举例:

# iloc 按位置df.iloc[0:2,1:3]# 选第0、1行,第1、2列# loc 按标签df.loc['row1':'row3','A':'C']# 选标签从row1到row3,列A到C(都包含结尾)

总结:

  • iloc 用于“按位置”取数据,适合数字索引。
  • loc 用于“按标签”取数据,适合行名、列名索引。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/3 4:01:58

红外热像仪光学性能综合测试系统在多领域中的作用

随着红外技术的快速发展&#xff0c;红外热像仪已成为工业检测、医疗诊断、安防监控、航空航天等领域的核心设备。其核心价值在于将不可见的红外辐射转化为清晰的热图像&#xff0c;而噪声、分辨率、视场范围等性能参数直接影响图像质量与数据有效性&#xff0c;其性能精度直接…

作者头像 李华
网站建设 2026/2/3 5:23:17

Kotaemon能否用于舆情监控?我们尝试了新闻摘要生成

Kotaemon能否用于舆情监控&#xff1f;我们尝试了新闻摘要生成 在信息爆炸的时代&#xff0c;每天产生的新闻和社交媒体内容堪称海量。对于企业公关、政府机构或媒体监测团队而言&#xff0c;如何从这股信息洪流中快速识别关键事件、掌握舆论风向&#xff0c;已成为一项迫在眉睫…

作者头像 李华
网站建设 2026/2/6 0:22:41

4、Windows 7 系统窗口与文件管理全攻略

Windows 7 系统窗口与文件管理全攻略 1. 所需设备与技能 要使用 Windows 7 系统进行操作,你需要以下设备: - 一台计算机(笔记本或台式机) - Windows 7 家庭高级版操作系统 - 显示器屏幕 - 键盘和鼠标或触控板 同时,你需要掌握键盘和鼠标的基本使用技能。 2. 窗口的…

作者头像 李华
网站建设 2026/2/4 5:56:24

16、中老年Windows 7用户的数码摄影入门与照片处理指南

中老年Windows 7用户的数码摄影入门与照片处理指南 1. 订单提交与照片处理准备 在进行购物时,若对订单满意,点击“立即购买”提交订单,在此之前你无需承担任何责任。若有疑虑,关闭网页即可,不会产生任何费用,且在这个过程中你会获得不少信心。 接下来进入照片处理环节…

作者头像 李华
网站建设 2026/2/3 20:47:21

18、老年人Windows 7电脑使用技巧与高级邮件处理指南

老年人Windows 7电脑使用技巧与高级邮件处理指南 1. 高级文字处理实用技巧 在处理长文档时,有几个实用技巧能提升工作效率。首先,可以在文档左侧启用文档地图,它能展示文档内容的简洁目录,让导航更轻松。操作方法是在视图功能区找到文档地图选项并开启。 另外,给文档中…

作者头像 李华