news 2026/4/3 4:48:56

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

作者头像

张小明

前端开发工程师

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

Hands-on data analysis— 动手学数据分析


写在最前面

这门课程得主要目的是通过真实的数据,以实战的方式了解数据分析的流程和熟悉数据分析python的基本操作。知道了课程的目的之后,我们接下来我们要正式的开始数据分析的实战教学,完成kaggle上泰坦尼克的任务,实战数据分析全流程。
这里有两份资料需要大家准备:图书《Python for Data Analysis》第六章和 baidu.com &google.com(善用搜索引擎)

来自Github开源项目Github项目地址

作者仅对于学习中遇到的问题进行标注整理 供大家学习讨论

本实验数据集和资料可以私信作者, 鼓励有条件的同学自行到Github上查阅下载

一、这篇笔记你将学到什么?

这篇笔记是基于 Kaggle 泰坦尼克项目的数据,从 0 带你走一遍数据分析最开始的几步:数据加载 → 初步观察 → 简单保存与导出,同时熟悉numpypandas的常用操作。


1. 数据加载:把数据“请进来”

  • 如何导入numpypandas并在报错时自己安装库。
  • 使用相对路径和绝对路径加载本地 CSV 文件,搞清楚“当前工作目录”的概念。
  • 理解pd.read_csv()pd.read_table()的区别(默认分隔符不同),以及.csv.tsv.xlsx这几种常见数据格式应该如何读取。
  • 学会用chunksize按块读取大文件,明白为什么要“逐块读取”来节省内存。
  • 学会把英文表头替换为中文列名,并把“乘客ID”设置为索引,同时理解inplace=True是“原地修改”。

2. 初步观察:快速给数据做个“体检”

  • 使用df.info()了解数据的整体结构:行数、列数、每列缺失值情况、数据类型和内存占用。
  • 使用head()/tail()查看前几行、后几行,快速感受数据长什么样。
  • 使用isnull()判断缺失值,理解哪些东西会被视为“空”(比如 NaN、None、NaT),哪些不会(比如 0、空字符串)。
  • 延伸出更多观察维度的思路:描述性统计(describe)、类别分布(value_counts)、极端值和相关性等,为后续真正的数据分析打基础。

3. 保存数据:把修改结果“带走”

  • 学会把修改过列名、索引后的 DataFrame 导出为新的 CSV 文件。
  • 知道文件默认保存位置是当前工作目录,也能指定保存路径。
  • 知道如何通过设置编码解决中文乱码问题(如utf-8gbk等)。

1 第一章:数据加载

1.1 载入数据

数据集下载 https://www.kaggle.com/c/titanic/overview

1.1.1 任务一:导入numpy和pandas
importnumpyasnpimportpandasaspd

【提示】如果加载失败,学会如何在你的python环境下安装numpy和pandas这两个库

1.1.2 任务二:载入数据

(1) 使用相对路径载入数据
(2) 使用绝对路径载入数据

df=pd.read_csv('train.csv')df.head(3)
# "E:\pycharm\Python3_9\hands-on-data-analysis\第一单元项目集合\train.csv"# 注意:Windows系统的路径中反斜杠\需要用双反斜杠\\或者斜杠/来表示,否则会报错df=pd.read_table('E:\\pycharm\\Python3_9\\hands-on-data-analysis\\第一单元项目集合\\train.csv',sep=',')df.head(3)

【提示】相对路径载入报错时,尝试使用os.getcwd()查看当前工作目录。

  • cwd 是 Current Working Directory 的缩写
importos# 打印当前工作目录print("当前工作目录:",os.getcwd())

【思考1.】知道数据加载的方法后,试试pd.read_csv()和pd.read_table()的不同,如果想让他们效果一样,需要怎么做?了解一下’.tsv’和’.csv’的不同,如何加载这两个数据集?

【总结】加载的数据是所有工作的第一步,我们的工作会接触到不同的数据格式(eg:.csv;.tsv;.xlsx),但是加载的方法和思路都是一样的,在以后工作和做项目的过程中,遇到之前没有碰到的问题,要多多查资料吗,使用google,了解业务逻辑,明白输入和输出是什么。

  • 【思考1.】pd.read_csv()pd.read_table()的区别,以及如何处理.csv.tsv文件。

1.pd.read_csv()pd.read_table()的主要区别

这两个函数在 Pandas 中都用于从文本文件加载数据到 DataFrame 中,但它们被设计用来处理不同默认分隔符的文件。

特性pd.read_csv()pd.read_table()
默认分隔符(sep参数)逗号(,)制表符(\t)
使用场景主要用于.csv文件(Comma Separated Values)。主要用于.tsv文件(Tab Separated Values)或通用文本文件
默认索引列index_col=Noneindex_col=None

在功能上,pd.read_csv()是更常用的和推荐的。实际上,pd.read_table()只是pd.read_csv()的一个包装器(Wrapper),它在内部调用pd.read_csv()并自动将分隔符设置为制表符。


如何让它们效果一样?

要让pd.read_csv()pd.read_table()读取同一个文件并产生相同的效果,你需要手动设置它们的分隔符 (sep) 参数,使其保持一致:

场景 A:读取逗号分隔的文件(.csv
函数代码说明
pd.read_csv()pd.read_csv('data.csv')使用默认值:逗号
pd.read_table()pd.read_table('data.csv', sep=',')手动指定分隔符为逗号
sep 是 Separator(分隔符)的缩写
场景 B:读取制表符分隔的文件(.tsv
函数代码说明
pd.read_csv()pd.read_csv('data.tsv', sep='\t')手动指定分隔符为制表符
pd.read_table()pd.read_table('data.tsv')使用默认值:制表符

2..tsv.csv的区别及加载方法

.csv.tsv都是常用的纯文本数据存储格式,它们的主要区别在于字段(列)之间是如何被分隔开的。

什么是分隔符?

分隔符(Delimiter)是一种特殊的字符,用于将数据行中的不同字段分开。

文件后缀全称含义分隔符
.csvCommaSeparatedValues逗号分隔值逗号(,)
.tsvTabSeparatedValues制表符分隔值制表符(\t)

要读取.xlsx文件(Microsoft Excel 文件),需要使用Pandas配合一个专门处理 Excel 格式的引擎

用于读取.xlsx文件的 Pandas 函数是pd.read_excel()



读取.xlsx文件的步骤

1. 安装必要的库

Pandas 自己无法直接处理.xlsx这种复杂格式的 Excel 文件,它需要一个后端库作为“引擎”来解析文件。最常用的库是openpyxl

如果你还没有安装,需要在命令行或终端运行以下命令:

pipinstallpandas openpyxl

2. 使用pd.read_excel()

安装完openpyxl后,你就可以在 Python 中使用pd.read_excel()函数来读取.xlsx文件了。

importpandasaspd# 假设你的文件名为 'my_data.xlsx'file_path='my_data.xlsx'# 使用 pd.read_excel() 读取文件df=pd.read_excel(file_path)print(df.head())

1.1.3 任务三:每1000行为一个数据模块,逐块读取
chunker=pd.read_csv('train.csv',chunksize=100)# chunksize=1000 关键参数: 指定每次读取文件时,要读取的行数。这里设置为 100行。print(f"chunker 的类型是:{type(chunker)}")# 2. 遍历 chunkerchunk_count=0forchunkinchunker:chunk_count+=1print("-"*30)print(f"这是第{chunk_count}个数据块 (chunk)")print(f"数据块的类型是:{type(chunk)}")print(f"数据块的行数是:{len(chunk)}")print("\n数据块 (chunk) 的具体内容:")# 打印每个数据块的前几行,以展示它是 DataFrameprint(chunk.head(3))# 'chunker' 每次迭代都会返回一个包含 1000 行数据的 DataFrameforchunkinchunker:# 这里的 'chunk' 就是一个标准的 Pandas DataFrame,但它只有 1000 行。# 可以在这里对这 1000 行数据进行计算、筛选或聚合等操作print(f"当前数据块的行数:{len(chunk)}")# 示例:计算每块数据的平均值average=chunk['Age'].mean()print(f"平均值:{average}")# 如果需要,可以将每块处理结果保存到外部列表或文件中# results.append(average)

输出结果如下:

chunker 的类型是:<class'pandas.io.parsers.readers.TextFileReader'>------------------------------ 这是第1个数据块(chunk)数据块的类型是:<class'pandas.core.frame.DataFrame'>数据块的行数是:100数据块(chunk)的具体内容:......

【思考1.】什么是逐块读取?为什么要逐块读取呢?

【提示】大家可以chunker(数据块)是什么类型?用for循环打印出来出处具体的样子是什么?


  • chunker(数据块)是什么类型?用for循环打印出来出处具体的样子是什么?

chunker 的类型是: <class ‘pandas.io.parsers.readers.TextFileReader’>

上方程序有chunker迭代出的内容

  • 什么是逐块读取?为什么要逐块读取呢?

Chunks是一个使用Pandas库来读取大型 CSV 文件时非常高效的技巧。

核心作用是:“不要一次性把整个大文件加载到内存中,而是把它分成一个个小的‘数据块’(Chunks),可以逐块处理。”


chunker = pd.read_csv('train.csv', chunksize=100)

代码逐段解释

代码段含义
pd.read_csv(...)告知 Pandas 库,我们要读取一个 CSV 文件。
'train.csv'指定要读取的文件名(假设这是一个很大的训练数据集文件)。
chunksize=1000关键参数:指定每次读取文件时,要读取的行数。这里设置为1000 行
chunker = ...将读取的结果赋值给一个名为chunker的变量。

chunksize参数的作用和原理

当一个文件非常大(比如有几百万行,甚至几 GB)时,你的计算机内存可能不足以一次性存储整个文件,或者一次性加载会导致程序运行缓慢甚至崩溃。

设置了chunksize后,pd.read_csv()就不会返回一个完整的DataFrame,而是返回一个特殊的迭代器 (Iterator)对象,我们在这里命名为chunker

1.chunker是什么?

chunker不是一个完整的 DataFrame,它是一个可以被循环的对象。

你可以把它想象成一个**“文件搬运工”**。你告诉搬运工:“每次只给我搬 1000 行数据。”

2. 如何使用chunker

你需要使用for循环来从chunker中逐块地取出数据,进行处理

3. 为什么使用分块读取?
  • 节省内存 (Memory Efficiency):你的程序永远只在内存中处理 1000 行数据,而不是整个文件。
  • 处理超大文件 (Big Data):即使文件大小超过了你电脑的可用内存,也可以完整地处理它。
  • 进度跟踪 (Progress Tracking):可以清晰地知道处理数据的进度。

总而言之,chunker = pd.read_csv('train.csv', chunksize=1000)的作用就是开启了分批加载大文件的模式,以提高内存使用效率和处理速度

1.1.4 任务四:将表头改成中文,索引改为乘客ID [对于某些英文资料,我们可以通过翻译来更直观的熟悉我们的数据]

PassengerId => 乘客ID
Survived => 是否幸存
Pclass => 乘客等级(1/2/3等舱位)
Name => 乘客姓名
Sex => 性别
Age => 年龄
SibSp => 堂兄弟/妹个数
Parch => 父母与小孩个数
Ticket => 船票信息
Fare => 票价
Cabin => 客舱
Embarked => 登船港口

df=pd.read_csv('train.csv',names=['乘客ID','是否幸存','仓位等级','姓名','性别','年龄','兄弟姐妹个数','父母子女个数','船票信息','票价','客舱','登船港口'],index_col='乘客ID',header=0)df.head()# 查看数据前5行输出(默认),如果想要多查看几行可以对head()传参

【思考】所谓将表头改为中文其中一个思路是:将英文列名表头替换成中文。还有其他的方法吗?

将表头改成中文并将索引改为乘客ID,可以通过以下几种方式实现:

方法 1:在读取数据时直接指定列名和索引

使用pd.read_csv()names参数指定中文列名,同时通过index_col参数设置索引为乘客ID。

df=pd.read_csv('train.csv',names=['乘客ID','是否幸存','乘客等级','乘客姓名','性别','年龄','堂兄弟/妹个数','父母与小孩个数','船票信息','票价','客舱','登船港口'],index_col='乘客ID',header=0# 跳过原始表头)df.head()

方法 2:读取后修改列名和索引

先读取数据,再通过columns属性和set_index()方法修改列名和索引。

df=pd.read_csv('train.csv')# 修改列名df.columns=['乘客ID','是否幸存','乘客等级','乘客姓名','性别','年龄','堂兄弟/妹个数','父母与小孩个数','船票信息','票价','客舱','登船港口']# 设置索引df=df.set_index('乘客ID')df.head()

方法 3:使用字典映射替换列名

通过字典映射替换列名,适合列名较多且需要动态修改的情况。

df=pd.read_csv('train.csv')# 创建英文到中文的映射字典column_mapping={'PassengerId':'乘客ID','Survived':'是否幸存','Pclass':'乘客等级','Name':'乘客姓名','Sex':'性别','Age':'年龄','SibSp':'堂兄弟/妹个数','Parch':'父母与小孩个数','Ticket':'船票信息','Fare':'票价','Cabin':'客舱','Embarked':'登船港口'}# 替换列名df.rename(columns=column_mapping,inplace=True)# 设置索引df.set_index('乘客ID',inplace=True)df.head()

方法 4:逐列修改列名

如果只需要修改部分列名,可以通过rename()方法逐列修改。

df=pd.read_csv('train.csv')# 修改部分列名df.rename(columns={'PassengerId':'乘客ID','Survived':'是否幸存'},inplace=True)# 设置索引df.set_index('乘客ID',inplace=True)df.head()
  • 在上面的方法三、四中inplace=Trues实现了什么功能

在 Pandas 中,inplace=True是一个非常常见的参数,它的含义是:直接在原对象上进行修改,而不是返回一个新的对象。

简单来说,就是**“原地修改”**。

详细对比

1. 默认情况 (inplace=False)

如果你不写这个参数,或者设置为False(这是默认值),Pandas 不会改变原本的df变量,而是把修改后的结果作为一个新的 DataFrame返回给你。你需要用变量去接收它。

# ❌ 原来的 df 不会变df.rename(columns=column_mapping)# ✅ 需要赋值给变量才能保存修改df_new=df.rename(columns=column_mapping)# 或者覆盖原变量df=df.rename(columns=column_mapping)
2. 使用inplace=True

如果你设置为True,Pandas 会直接修改内存中的df对象。这个操作没有返回值(返回None),但df本身变了。

# ✅ 原来的 df 直接被修改了df.rename(columns=column_mapping,inplace=True)# ❌ 千万不要这样写,因为 inplace=True 返回的是 None# df = df.rename(columns=column_mapping, inplace=True) <-- 这样 df 会变成 None

总结

  • inplace=False(默认)“给我一份改好的复印件,原件不要动。”(安全,适合链式调用)
  • inplace=True“直接在原件上改。”(省去赋值步骤,代码看起来简洁一些)

1.2 初步观察

导入数据后,你可能要对数据的整体结构和样例进行概览,比如说,数据大小、有多少列,各列都是什么格式的,是否包含null等

1.2.1 任务一:查看数据的基本信息
df.info()
<class 'pandas.core.frame.DataFrame'> Index: 891 entries, 1 to 891 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 是否幸存 891 non-null int64 1 仓位等级 891 non-null int64 2 姓名 891 non-null object 3 性别 891 non-null object 4 年龄 714 non-null float64 5 兄弟姐妹个数 891 non-null int64 6 父母子女个数 891 non-null int64 7 船票信息 891 non-null object 8 票价 891 non-null float64 9 客舱 204 non-null object 10 登船港口 889 non-null object dtypes: float64(2), int64(4), object(5) memory usage: 83.5+ KB
  • 输出结果解释

Pandas DataFrame 的.info()方法的运行结果,它提供了关于这个数据集(DataFrame)的简洁、概要的信息

我们可以将这些信息分为几个关键部分来理解:

1. 整体结构信息

  • <class 'pandas.core.frame.DataFrame'>
    • 含义:确认这个对象是一个Pandas DataFrame类型,这是 Pandas 中最常用的二维(表格型)数据结构。
  • Int64Index: 891 entries, 1 to 891
    • 含义:描述数据的行信息
      • 总行数 (Entries):共有891条记录(或行)。
      • 索引 (Index):索引类型是 64 位整数 (Int64Index),范围是从1 到 891。这表明数据的索引是从 1 开始的,而不是默认的 0 开始。
  • Data columns (total 11 columns)
    • 含义:描述数据的列信息
      • 总列数:共有11列。

2. 列详细信息(数据质量检查的核心)

这部分是.info()输出最重要的部分,它详细列出了每一列的数据情况。

序号列名 (Column)非空值计数 (Non-Null Count)数据类型 (Dtype)缺失值情况
0是否幸存891 non-nullint64无缺失值(891/891)
1仓位等级891 non-nullint64无缺失值(891/891)
2姓名891 non-nullobject无缺失值
3性别891 non-nullobject无缺失值
4年龄714 non-nullfloat64有缺失值(177 个)
5兄弟姐妹个数891 non-nullint64无缺失值
9客舱204 non-nullobject严重缺失(687 个)
10登船港口889 non-nullobject有缺失值(2 个)

关键数据类型解释:

  • int64(Integer 64-bit):64 位整数。通常用于存储整数数据(如计数、ID、等级)。
  • float64(Float 64-bit):64 位浮点数。用于存储小数数据(如年龄、票价)。
  • object字符串(文本)类型。用于存储文本数据(如姓名、客舱号)。

缺失值分析:

通过比较总行数 (891) 和 Non-Null Count,我们可以迅速发现数据集中的缺失数据 (Missing Values)

  • 年龄:只有 714 个非空值,意味着有891 − 714 = 177 891 - 714 = \mathbf{177}891714=177个缺失值。
  • 客舱:只有 204 个非空值,意味着有891 − 204 = 687 891 - 204 = \mathbf{687}891204=687个缺失值(缺失率非常高)。
  • 登船港口:只有 889 个非空值,意味着有2 \mathbf{2}2个缺失值。

这些缺失值需要在后续的数据清洗和预处理阶段进行处理(比如填充或删除)。


3. 资源使用信息

  • dtypes: float64(2), int64(4), object(5)
    • 含义:总结了数据类型在整个 DataFrame 中的分布。
      • 有 2 列是float64类型。
      • 有 4 列是int64类型。
      • 有 5 列是object(字符串)类型。
  • memory usage: 83.5+ KB
    • 含义:估算这个 DataFrame 在内存中所占用的空间大约是83.5 千字节 (KB)。这个数值可以帮助你评估处理更大文件时的内存需求。

总而言之,.info()是进行初步数据探索数据质量检查时最重要的一步,它让你快速了解数据的规模、类型和完整性。

  • df.info 和 df.info()有什么区别

这是一个非常经典的 Python 初学者问题,触及了**方法调用(Call)对象引用(Reference)**的核心区别。

简单来说:带括号是“做动作”,不带括号是“看说明书”。

以下是详细对比分析:

1.df.info()—— 执行方法(做动作)

  • 含义:这是在调用(Call)这个函数。你告诉 Python:“现在立刻运行info这个功能。”
  • 结果:Python 会执行info内部的代码,计算并打印出 DataFrame 的详细摘要(行数、列数、非空值、内存占用等)。
  • 你在数据分析中需要的:正是这个。

代码示例:

df.info()

输出结果(示例):

<class 'pandas.core.frame.DataFrame'> Int64Index: 891 entries, 1 to 891 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 是否幸存 891 non-null int64 ... (省略中间内容) ... dtypes: float64(2), int64(5), object(5) memory usage: 90.5+ KB

2.df.info—— 查看对象(看说明书)

  • 含义:这是在引用这个属性。你告诉 Python:“我想看看df对象里名为info的那个东西是什么。”
  • 结果:Python 不会运行代码,而是告诉你:“这是一个绑定在 DataFrame 上的方法对象。”
  • 你在数据分析中需要的:通常不需要,除非你在做高级编程(比如把这个函数赋值给另一个变量)。

代码示例:

df.info

输出结果(示例):

<bound method DataFrame.info of 是否幸存 仓位等级 姓名 性别 年龄 ... 父母子女个数 船票信息 票价 客舱 登船港口 乘客ID ... 1 0 3 Braund... male 22.0 ... 0 A/5 21171 7.25 NaN S 2 1 1 Cuming... female 38.0 ... 0 PC 17599 71.28 C85 C ... [891 rows x 11 columns]>

(注意:它只是打印出了这个方法的描述信息,并没有统计数据的非空值或类型)


总结对比表

特性df.info()(带括号)df.info(不带括号)
本质函数调用 (Function Call)对象引用 (Object Reference)
比喻按下遥控器上的“播放”键手指着遥控器上的“播放”键
作用执行代码,计算并显示数据摘要查看这个方法本身在内存中的样子
是否有返回值有(通常打印到控制台或返回 None)有(返回方法对象本身)
常用场景99.9% 的情况(查看数据信息)极少(调试或高阶函数式编程)

结论

在做数据分析查看数据概况时,请务必加上括号()

1.2.2 任务二:观察表格前10行的数据和后15行的数据
df.head(10)
df.tail(15)

记住相关语法就可以,这里就不展示结果了。

1.2.3任务三:判断数据是否为空,为空的地方返回True,其余地方返回False
df.isnull().head()# 展示前 5 行数据的缺失值分布情况(True 表示缺失)

.isnull()方法是查看空缺值 ,这里结合.head()方法一起使用。避免一次性输出过多

【总结】上面的操作都是数据分析中对于数据本身的观察

【思考】对于一个数据,还可以从哪些方面来观察?找找答案,这个将对下面的数据分析有很大的帮助


  • 对于一个数据,还可以从哪些方面来观察?

除了上述的的查看头尾行 (head/tail)、基本信息 (info) 和缺失值 (isnull) 之外,数据观察(Exploratory Data Analysis, EDA)通常还需要从以下几个核心维度进行深入:

1. 描述性统计分析 (Descriptive Statistics)

这是最直接了解数据数值分布的方法。

  • 方法df.describe()
  • 观察点
    • 均值 (mean)vs中位数 (50%):如果两者相差很大,说明数据存在偏斜(Skewness)或异常值。
    • 标准差 (std):数据波动大不大?
    • 最小值 (min) / 最大值 (max):数据范围是否合理?(例如:年龄不应为负数,票价不应无穷大)。
# 查看数值型列的统计摘要df.describe()

2. 唯一值与计数 (Unique Values & Counts)

对于分类数据(如性别、登船港口、客舱等级),我们需要知道有哪些类别以及每个类别的数量。

  • 方法
    • df['列名'].unique():查看有哪些唯一值。
    • df['列名'].value_counts():查看每个类别有多少条数据。
  • 观察点
    • 是否存在拼写错误的类别(如 “male” 和 “Male”)?
    • 样本是否均衡?(例如:幸存者和遇难者比例是否悬殊?)
# 查看“性别”列有哪些值,以及各有多少人df['性别'].value_counts()

3. 数据类型与格式检查 (Data Types & Format)

虽然info()给了大概的类型,但有时需要更细致的检查。

  • 观察点
    • 数值是否被存成了字符串?(例如票价列里混入了 “$” 符号导致变成 object 类型)。
    • 时间格式是否正确?(例如日期是 “2021-01-01” 字符串还是 datetime 对象)。

4. 异常值检测 (Outlier Detection)

寻找那些“格格不入”的数据。

  • 方法
    • 排序df.sort_values(by='列名'),看看最大和最小的几个值是否离谱。
    • 可视化(箱线图):虽然还没讲到绘图,但这是观察异常值最直观的方法。
  • 观察点
    • 比如泰坦尼克号数据中,是否有年龄超过 100 岁或票价高达 5000 的记录?

5. 相关性分析 (Correlation)

观察特征之间,或者特征与目标变量(是否幸存)之间的关系。

  • 方法df.corr()
  • 观察点
    • 票价越高,幸存率越高吗?
    • 年龄和兄弟姐妹数量有关联吗?

总结代码示例

你可以尝试运行以下代码来扩展你的观察视角:

# 1. 统计摘要(快速看数值分布)print("--- 统计摘要 ---")print(df.describe())# 2. 查看分类数据的分布(例如:查看男女比例)print("\n--- 性别分布 ---")print(df['性别'].value_counts())# 3. 排序观察(例如:看看票价最高的前 5 个人)print("\n--- 票价最高的 5 人 ---")print(df.sort_values(by='票价',ascending=False).head(5))
  • .isnull()判断为空的机制是什么? 空值可能是没有填充 Nan None…

理解 Pandas 如何定义“空值”对于数据清洗至关重要。

1.df.isnull().head()语句解释

这行代码是两个方法的链式调用,我们可以把它拆解来看:

  1. df.isnull()
    • 作用:它会遍历整个 DataFrame,判断每一个单元格是否为“空”。
    • 返回结果:返回一个与原 DataFrame 形状完全一样的新 DataFrame,但里面的内容变成了布尔值(Boolean):
      • 如果原位置是空值,显示True
      • 如果原位置有数据,显示False
  2. .head()
    • 作用:取前 5 行。
    • 目的:因为整个表可能很大,打印出来看不清,我们只看前 5 行的布尔值结果,快速检查一下哪些列可能存在缺失数据。

总结:这行代码的作用是**“展示前 5 行数据的缺失值分布情况(True 表示缺失)”**。


2. Pandas 判断“空值”的机制

Pandas 在判断是否为null时,主要依据底层NumPy的标准以及 Python 的对象标准。

被判定为True(是空值) 的情况:

Pandas 的isnull()(以及它的别名isna()) 会将以下情况视为缺失值:

  1. NaN(Not a Number)
    • 这是标准的浮点数缺失值(IEEE 754 标准)。
    • 这是 Pandas 中最常见的缺失值形式(数值列通常都用这个)。
  2. None(Python 的 None 对象)
    • Python 自带的“无”对象。
    • 在 Pandas 的object类型(字符串/混合类型)列中,None会被保留并视为缺失值。
    • 在数值列中,Pandas 通常会自动把None转换为NaN
  3. NaT(Not a Time)
    • 专门用于时间序列(Datetime)类型的缺失值。
被判定为False(不是空值) 的情况(易错点):

很多初学者容易混淆以下情况,Pandas不认为它们是空值:

  1. 空字符串""" "
    • 注意:这是最容易踩坑的地方!在 Pandas 看来,空字符串是一个长度为 0 的有效字符串对象,不是 Null
  2. 字符串"NaN""null"
    • 如果你读取 CSV 时没有正确解析,这些只是普通的文本字符,不是真正的缺失值。
  3. 数字0
    • 0 是一个有效的数字,不是空。
  4. False
    • 布尔值的 False 是有效值。
  5. inf(无穷大)
    • 默认情况下,无穷大被视为有效值(可以通过配置修改)。

代码演示

importpandasaspdimportnumpyasnp data={'数值':[1,np.nan,0],# np.nan 是空,0 不是'对象':['abc',None,''],# None 是空,空字符串 '' 不是'时间':[pd.Timestamp('20210101'),pd.NaT,pd.Timestamp('20210102')]# NaT 是空}df_test=pd.DataFrame(data)print("原始数据:")print(df_test)print("-"*20)print("isnull() 判断结果:")print(df_test.isnull())

输出结果预演:

  • np.nan-> True
  • None-> True
  • pd.NaT-> True
  • 0->False
  • ''(空字符串) ->False

1.3 保存数据

1.3.1 任务一:将你加载并做出改变的数据,在工作目录下保存为一个新文件train_chinese.csv
# 注意:不同的操作系统保存下来可能会有乱码。大家可以加入`encoding='GBK' 或者 ’encoding = ’utf-8‘‘`df.to_csv('train_chinese.csv')

默认会将文件保存在当前的“工作目录”(Current Working Directory)下。

也可以指定绝对路径保存注意反斜杠的问题

【总结】数据的加载以及入门,接下来就要接触数据本身的运算,我们将主要掌握numpy和pandas在工作和项目场景的运用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/2 11:26:34

Go 安装插件更换国内镜像

在后台执行&#xff1a; go install golang.org/x/tools/goplslatest但 Go 默认一定会访问&#xff1a; https://proxy.golang.org,direct而当前网络 没有被 Go 识别 → 请求超时 → 所有工具安装失败。✅ 方案一&#xff08;推荐&#xff09;&#xff1a;正确配置 Go 国内镜像…

作者头像 李华
网站建设 2026/4/3 1:39:27

LobeChat能否接入Reddit API?社区热点内容聚合分析

LobeChat 能否接入 Reddit API&#xff1f;社区热点内容聚合分析的实现路径 在信息爆炸的时代&#xff0c;每天有成千上万的讨论在 Reddit 的各个子版块中悄然生成。从 r/ArtificialIntelligence 到 r/Futurology&#xff0c;再到加密货币、开源项目和消费电子等垂直社区&…

作者头像 李华
网站建设 2026/3/30 12:29:21

基于SpringBoot的居民小区物业管理系统的设计与实现毕业设计项目源码

项目简介在城市化进程加快、小区居民对物业服务精细化需求提升&#xff0c;而传统物业管理存在 “工单处理低效、缴费流程繁琐、信息沟通不畅、设施管理散乱” 的行业痛点背景下&#xff0c;基于 SpringBoot 的居民小区物业管理系统构建具有重要的民生与管理价值&#xff1a;从…

作者头像 李华
网站建设 2026/4/1 15:02:26

第四章 智能体经典范式构建

一个现代的智能体&#xff0c;其核心能力在于能将大语言模型的推理能力与外部世界联通。它能够自主地理解用户意图、拆解复杂任务&#xff0c;并通过调用代码解释器、搜索引擎、API等一系列“工具”&#xff0c;来获取信息、执行操作&#xff0c;最终达成目标。 然而&#xff0…

作者头像 李华
网站建设 2026/4/2 17:10:50

基于SpringBoot的课堂考勤系统设计与实现毕业设计项目源码

项目简介在教育信息化推进过程中&#xff0c;传统课堂考勤存在 “人工点名效率低、考勤数据统计繁琐、代签到难管控、缺勤预警不及时” 的痛点&#xff0c;难以满足高校及中小学精细化教学管理的需求。基于 SpringBoot 的课堂考勤系统构建具有重要的教育管理与实用价值&#xf…

作者头像 李华
网站建设 2026/4/3 3:41:15

Dify 权限控制的终极方案:融合RBAC与ABAC应对复杂混合检索场景

第一章&#xff1a;混合检索的 Dify 权限控制在构建基于 Dify 的智能应用时&#xff0c;混合检索机制与权限控制系统共同决定了系统的安全性与数据访问效率。Dify 支持通过角色和策略实现细粒度的权限管理&#xff0c;确保用户仅能访问其被授权的数据资源&#xff0c;即使在启用…

作者头像 李华