Pandas函数详解:案例解析(第25天)

news2025/1/11 21:47:14

系列文章目录


  1. Pandas函数详解
  2. 排序函数
  3. 聚合函数
  4. 缺失值处理
  5. 日期函数

文章目录

  • 系列文章目录
  • 前言
    • 1 索引和列名操作
      • 1.1 查看索引和列名
      • 1.2 修改索引和列名
    • 2 常用计算函数
      • 2.1 排序函数
      • 2.2 聚合函数
      • 2.3 练习
    • 3 缺失值处理
      • 3.1 缺失值概念
      • 3.2 加载包含缺失值数据
      • 3.3 查看缺失值
      • 3.4 缺失值处理
        • 3.4.1 删除缺失值
        • 3.4.2 填充缺失值
    • 4 pandas数据类型
      • 4.1 类型转换
      • 4.2 category类型
      • 4.3 日期时间类型
      • 4.4 时间差类型


前言

本文主要通过案例解析的方式详解了Pandas工作中常用函数。


提示:以下是本篇文章正文内容,下面案例可供参考

1 索引和列名操作

1.1 查看索引和列名

# 导入模块
import pandas as pd
# 加载数据集
df = pd.read_csv('data/LJdata.csv')
# 获取区域列为天通苑租房的信息
df2 = df[df['区域']=='天通苑租房']
df2
# 获取df2中价格列
df2_price = df2['价格']
df2_price
# 获取行索引值
# s/df.index
df2_price.index
type(df2_price.index)
df2.index
# 获取行索引值列表中的具体值  通过下标取值
df2.index[0]
# 获取s对象的行索引值
df2_price.keys()
# 获取df的列名
df2.keys()
df2.columns
# 通过列表下标值获取数据值
df2.columns[-1]

1.2 修改索引和列名

  • set_index()方法

    # 通过set_index(keys=[列名])方法设置索引值
    df2.set_index(keys=['区域'])
    # 多列索引为复合索引 -> 了解  
    df2.set_index(keys=['区域','地址'])
    # 读取数据是通过参数指定索引列
    # index_col
    
  • index_col属性

    # 读取数据时通过index_col参数指定索引
    df4 =pd.read_csv('data/LJdata.csv', index_col=['区域'])
    df4
    pd.read_csv('data/LJdata.csv', index_col=['区域', '地址'])
    
  • reset_index()方法

    # 重置行索引 
    # reset_index(drop=)  
    # drop: 是否删除原行索引, 默认不删除(原索引作为df中的一列)
    df4.reset_index()
    # 删除原索引
    df4.reset_index(drop=True)
    # s对象重置索引 返回df对象
    df2_price.reset_index()
    # s对象重置索引 返回s对象
    df2_price.reset_index(drop=True)
    
  • 赋值修改

    必须要获取所有索引和列名, 修改的列表中的数据要和行数/列数相同

    df5 = df2_price.reset_index().head()
    df5
    # 先获取索引和列名
    df5.index
    df5.columns
    # 如何修改列表中的数据  赋值修改
    list1 = [1,2,3,4]
    list1[0]='a'
    list1
    # 赋值修改索引  df索引值数和列表的数据个数相等
    df5.index = [0, 'b', 'c', 'd', 'e']
    df5
    # 赋值修改列名
    df5.columns = ['列名1', '列名2']
    df5
    
  • rename()方法修改

    灵活修改, 可以修改指定的索引或列名

    # df.rename(index={原索引:新索引,...}, columns={原列名:新列名,...}, inplace=)
    # 修改行索引
    df5.rename(index={'b': 1, 'e': 'E'})
    # 修改列名
    df5.rename(columns={'列名1':'id', '列名2':'price'})
    # 同时修改索引和列名
    df5.rename(index={'b':1,'c':2,'d':3,'e':4},columns={'列名1':'id','列名2':'price'},inplace=True)
    df5
    

2 常用计算函数

2.1 排序函数

  • nlargest()

    # 导入模块
    import pandas as pd
    # 加载数据集
    df = pd.read_csv('data/LJdata.csv')
    df2 = df.head(10)
    df2
    # df.nlargest(n, columns=[列名1, 列名2,...])
    # 根据指定的列进行降序操作, 获取前n个数据
    # 获取看房人数列排名前5数据 -> 看房人数值相同时, 再通过价格值比较
    df2.nlargest(n=5, columns=['看房人数', '价格'])
    df2.nlargest(3, '价格')
    
  • nsmallest()

    # df.nsmallest(n=, columns=[列名1, 列名2, ...])
    # 根据指定的列值进行升序操作, 获取前n个数据
    # 获取面积最小的前3条数据
    df2.nsmallest(n=3, columns=['面积'])
    
  • sort_values()

    # df.sort_values(by=[列名1, 列名2, ...], ascending=[True, False, ...])
    # ascending: 排序方式, 默认True 升序, False 降序
    # 对一列数据进行排序 默认升序  order by 面积 asc
    df2.sort_values(by=['面积'])
    # 降序 order by 面积 desc
    df2.sort_values(by=['面积'], ascending=False)
    # 对多列进行排序操作 
    # 第一列中数据值相等时, 以第二列进行排序, ...  order by 看房人数,价格 asc
    df2.sort_values(by=['看房人数','价格'], ascending=True)
    df2.sort_values(by=['看房人数','价格'], ascending=False)
    # 对多列对应不同排序方式的排序操作 order by 看房人数 asc, 价格 desc
    df2.sort_values(by=['看房人数', '价格'], ascending=[True, False])
    
  • sort_index()

    # 对索引进行排序操作
    df2.sort_index(ascending=False)
    

2.2 聚合函数

# 聚合函数一般是和分组结合使用
# 聚合函数单独使用, 是对一列数据进行聚合, 返回一个结果值
# min 最小值, 默认是按列计算 axis=0
df2.min()
# 按行计算 axis=1
df2.min(axis=1)
df2['价格'].min()
# max 最大值
df2.max()
# mean 平均值
df2.mean()
# std 标准差  机器学习
df2.std()
# median 中位数
df2.median()
# sum 求和
# 数值列求和, 非数值列字符串拼接
df2.sum()
# cumsum 累计求和  1 1+2  1+2+3
df2.cumsum()
# count 统计非空值个数
df2.count()
# 统计每行个数
df2.count(axis=1)
# value_counts() 统计不同值出现的次数 分组计算
df2['朝向'].value_counts()
# corr 相关性计算 了解  给机器学习处理数据时, 获取相关性不是很强的列作为特征列进行模型训练
# 计算数值列之间的相关性 -1~1 负数就是负相关, 正数就是正相关
df2.corr()
# quantile 分位数 默认二分位 -> 中位数
# 二八原则 获取1/5分位值, 根据分位值获取20%数据
df2.quantile() 
# 通过q参数自定义分位
df2.quantile(q=[0, 0.25, 0.5, 0.75, 1])
df2['价格'].quantile(q=[0,1/3, 2/3, 1])
# 根据价格获取前75%的数据
df2[df2['价格']<7725] 

2.3 练习

# 找到租金最低和最高的房子的全部信息
# 找到最近新上的10套房源
# 每套房子的平均租房价格-元/平米  所有房子平均价格
# 统计不同户型的房源数量

3 缺失值处理

3.1 缺失值概念

数据中都会存在缺失值

pandas中的缺失值用numpy中的NaN,NAN,nan值表示

sql中的缺失值用NULL,null表示

python中的缺失值用None表示

也可以用一些特定的值表示缺失值 missing,0,空字符串

缺失值是不参与统计计算的

from numpy import NAN, NaN, nan
# 缺失值不等于0,'',bool值
print(NAN == 0)
print(nan == '')
print(nan == True)
print(nan == False)
# 缺失值之间也是不相等
print(NAN==NAN)
print(NAN==NaN)
# 缺失值如何产生的?
# 数据采集过程中, 是没有采集到数据
# 计算过程中, 产生缺失值 -> sql关联, 关联不上的用缺失值填充

3.2 加载包含缺失值数据

import pandas as pd
# 加载城市天气数据集
df = pd.read_csv('data/city_day.csv')
df
# 缺失值不参与统计
df.count()
# 加载数据集时, 不转换空值
# keep_default_na:默认True, 将空值用NaN值表示
new_df = pd.read_csv('data/city_day.csv', keep_default_na=False)
new_df
new_df.count()
# 指定数据值用NaN值替换
# missing、空字符串、0等值可以表示的是NaN值
# city列用Ahmedabad表示的是NaN值
# na_values:指定某些数据值在加载时用NaN替换
pd.read_csv('data/city_day.csv', keep_default_na=False, na_values=['Ahmedabad', '2015-01-01'])
# 可以通过replace函数实现替换
df.replace(to_replace='Ahmedabad', value=NaN)

3.3 查看缺失值

# 通过info方法进行查看
df.info()
# isnull/isna判断数值是否是缺失值 返回True False
# notnull/notna判断数值是否不是缺失值 返回True False
df.head().isnull()
df.isna()
# 如果值不是缺失值, 返回True
df['PM2.5'].head().notnull()
df.head().notna()
# 统计每列缺失值数量
# 布尔值进行数值计算时,True转换成1,False转换成0
df.isnull().sum()
# 统计每行缺失值数量
df.isna().sum(axis=1)
# 统计每列非缺失值数量
df.count()
# 通过missingno模块 可视化展示缺失值 -> 了解
# 在jupyter中安装模块, 前边加一个 !
!pip install missingno -i https://pypi.tuna.tsinghua.edu.cn/simple/
import missingno as msno
import matplotlib.pyplot as plt
# 绘制缺失值柱状图
msno.bar(df)
plt.show()
# 绘制缺失值位置图形
msno.matrix(df)
# 随机获取100条数据
df.sample(100)
msno.matrix(df.sample(100))
# 绘制缺失值相关性图形
msno.heatmap(df)

3.4 缺失值处理

3.4.1 删除缺失值
# 一般情况下不建议删除行或列, 除非是缺失值占比很高 80%以上 
# 删除行列 drop()
# df.dropna()
# 随机获取10条数据
# random_state:随机数种子, 了解
df2 = df.sample(n=10, random_state=5)
df2
# 按行删除包含缺失值的行数据
df2.dropna(how='any')
# 统计每行缺失值的数量
df2.isnull().sum(axis=1)
# 删除每行的数据都为缺失值的行数据
df2.dropna(how='all')
# 按列删除缺失值的列
df2.dropna(axis=1)
# 统计每列中缺失值的数量
df2.isnull().sum()
# 删除指定列中包含缺失值的行数据
# subset
df2.dropna(subset=['PM10', 'NH3'])
# 删除缺失值行数据之后, 非空值个数大于等于指定的阈值时, 会保留当前行
df2.dropna(thresh=12)
df.isnull().sum()
# 通过drop方法删除缺失值占比很高的列
df.drop(labels=['Xylene'],axis=1)
3.4.2 填充缺失值
  • 固定值填充

    # df.fillna(value=)
    # 使用常数值或统计值填充缺失值
    df2 = df.copy()
    df2
    # 用常数填充
    # 例如: 性别列 男,女  缺失值可以用未知进行填充(问业务方)
    df2['PM2.5'].fillna(value='未知')
    df2.fillna(value='未知')
    df2['PM2.5'].mean()
    # 使用统计值填充缺失值 平均值,最大最小值,众数
    df2['PM2.5'] = df2['PM2.5'].fillna(value=df2['PM2.5'].mean())
    df2
    
  • 前后值填充

    # 使用缺失值的前后非缺失值填充 -> 对时间序列数据
    temp_s = df['Xylene'][54:64]
    temp_s
    # 使用缺失值的上一个非缺失值填充
    # method: ffill:前一个非缺失值  bfill:后一个非缺失值
    temp_s.fillna(method='ffill')
    temp_s.fillna(method='bfill')
    
  • 线性填充

    # 线性填充法
    # 认为值之间存在一个线性关系, 自动用线性值填充
    temp_s.interpolate()
    

4 pandas数据类型

4.1 类型转换

import pandas as pd
df = pd.read_csv('data/city_day.csv')
df.info()
# 类似于sql中的cast操作
# s.astype(内置类型名)
# 查看列类型
df['PM2.5'].dtype
# 转换成字符串类型
df['PM2.5'] = df['PM2.5'].astype('str')
df.info()
# 转换成浮点类型
df['PM2.5'].astype('float')
# 构造包含 missing字符的数据
df2 = df.head().copy()
df2
# 将1,3,5行的NO列值替换成missing
df2.loc[::2, 'NO'] = 'missing'
df2
# 发生报错, missing不能转换成float类型
df2['NO'].astype('float')
# pd.to_numeric()
# raise: 如果不能转换会抛出异常
pd.to_numeric(df2['NO'], errors='raise')
# coerce: 强制转换, 非浮点值用NaN值替换
pd.to_numeric(df2['NO'], errors='coerce')
# ignore: 不发生转换,也不发生报错
pd.to_numeric(df2['NO'], errors='ignore')

4.2 category类型

# 创建category类型
# data接受的是一个分类对象 pd.Categorical(values=, categorires=)
s1 = pd.Series(data=pd.Categorical(values=['a', 'b', 'c', 'd'], categories=['a', 'b', 'c']))
s1
s2 = pd.Series(data=['a', 'b', 'c', 'd', 'a', 'b'],dtype='category')
s2
# 转换df中列的类型为category类型
df.info()
df['City'] = df['City'].astype('category')
df.info()

4.3 日期时间类型

  • python日期时间

    # python中通过datetime/time模块获取日期时间
    import datetime
    t1 = datetime.datetime.now()
    t1
    type(t1)
    someday = datetime.datetime(2024,2,24)
    someday
    import time
    time.time()
    from datetime import datetime
    # format -> 将日期时间类型转换成字符串日期
    a = datetime.strftime(t1, '%Y-%m-%d')  
    print(a)
    type(a)
    datetime.strptime(a, '%Y-%m-%d')  # parse -> 将字符串日期转换成日期时间类型
    
  • 日期类型转换

    # 读取数据时将列解析成日期时间类型
    # parse_dates: 指定列名或列下标
    new_df = pd.read_csv('data/city_day.csv', parse_dates=['Date'])
    new_df.info()
    # 通过pd.to_datetime(列名)方法转换成日期时间类型
    df = pd.read_csv('data/city_day.csv')
    df['Date'] = pd.to_datetime(df['Date'])
    df.info()
    
    df = pd.read_csv('data/city_day.csv')
    df.info()
    # 通过astype方法转换成日期时间类型
    df['Date'].astype('datetime64[ns]')
    
  • 提取日期时间列中部分数据

    # 提取日期时间类型中部分数据
    # .dt -> 获取一列中的部分数据
    new_df['year'] = new_df['Date'].dt.year
    new_df
    new_df['Date'].dt.month
    
    t2 = datetime(2024,2,24)
    t2
    # 获取一个值中的部分数据
    t2.year
    t2.month
    t2.day
    
  • 日期时间运算

    # 获取Date列中最小日期
    new_df['Date'].min()
    # 日期时间作差, 得到天数差值 timedelta64[ns] 时间差类型
    new_df['Date'] - new_df['Date'].min()
    
  • 日期时间索引

    # 设置日期时间列为索引
    df = pd.read_csv('data/city_day.csv',index_col=['Date'], parse_dates=True)
    df.index
    # 使用日期时间获取部分数据之前,需要对索引列进行排序
    df = df.sort_index()
    # 获取2018年的数据
    df['2018']
    # 获取2018-08的数据
    df['2018-08']
    # 获取时间范围内的数据
    df.loc['2018-08-01 22':'2019-01-01 23:11:12']
    

4.4 时间差类型

  • python中timedelta类型

    from datetime import datetime
    now = datetime.now()
    print(now)
    t1 = datetime(2024,2,22)
    print(t1)
    diff = now-t1
    print(diff)
    print(type(diff))
    
  • 时间差类型转换

    df = pd.read_csv('./data/city_day.csv', parse_dates=[1])
    df.info()
    # 日期时间作差得到时间差类型
    ref_date = df['Date'] - df['Date'].min()
    ref_date
    # 转换成时间差类型
    s1 = ref_date.astype('object')
    s1
    pd.to_timedelta(s1)
    s1.astype('timedelta64[ns]')
    
  • 时间差索引

    # 时间差类型设置成索引
    df = pd.read_csv('./data/city_day.csv', parse_dates=[1])
    # 将时间差列设置为索引
    df.index = df['Date'] - df['Date'].min()
    df = df.sort_index()
    # 需要先对索引排序, 然后根据范围获取部分数据
    df['0 days':'4 days']
    

    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1891849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无人机集群协同搜索研究综述

源自&#xff1a;指挥控制与仿真 作者&#xff1a;刘圣洋, 宋婷, 冯浩龙, 孙玥, 韩飞 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 摘要 无人机集群协同区域搜索能够有效地获取任务区域地面信息,降低环境不确定度。基…

【操作系统】操作系统运行环境——处理器的运行模式

处理器的运行模式 导读一、内核程序和应用程序二、特权指令与非特权指令三、用户态与核心态四、内核4.1 时钟管理4.2 中断机制4.3 原语4.4 系统控制的数据结构及处理 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我…

高校教师教学质量评估系统-计算机毕业设计源码03344

摘要 在高等教育中&#xff0c;教学质量是培养优秀人才的关键。为了提高教学质量&#xff0c;高校需要建立一套科学、有效的教师教学质量评估系统。本研究采用 SSM技术框架&#xff0c;旨在开发一款高校教师教学质量评估系统。 SSM框架作为一种成熟的Java开发框架&#xff0c;具…

echarts--Tree的label上添加图片

使用echarts的rich富文本&#xff0c;配合lable的formatter去实现 主要代码&#xff1a;label里 rich: {img1: {backgroundColor: {image: Cloudy,},height: 40}},formatter: function (param) {var res "";res {img1|} param.name;return res;}, 如果想要哪一节…

基于贝叶斯优化的卷积神经网络-循环神经网络混合模型的的模拟股票时间序列预测(MATLAB R2021B)

将机器学习和深度学习方法运用到股市分析中, 不仅具有一定的理论价值, 也具有一定的实践价值。从理论价值上讲, 中国的量化投资技术&#xff08;投资观念、方法与决策等&#xff09;还不够成熟, 尚处在起步阶段, 能够将量化投资技术运用到投资决策中的公司寥寥无几。目前, 国内…

程序员学CFA——经济学(五)

经济学&#xff08;五&#xff09; 货币政策与财政政策基本术语货币政策货币货币的功能货币的定义货币的创造过程货币的供给和需求费雪效应 中央银行中央银行的职能中央银行的目标与通货膨胀的成本中央银行的有效性 货币政策工具货币传导机制货币政策的目标与形式货币政策的目标…

AIGC时代算法工程师的面试秘籍(2024.6.10-6.23第十六式) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试方法&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

还以网站建设为主营?赶紧转!除非你的网站做比他们还漂亮

案例一&#xff1a;某上市公司2019年找A公司做了一个官网&#xff0c;网站做了三年多&#xff0c;到现在没有上线&#xff0c;该公司业务没受任何影响&#xff0c;一直蒸蒸高日上。案例二&#xff1a;我公司也有自己官网&#xff0c;这么多年页面啥流量&#xff0c;一样不影响我…

001:开源交易系统开发实战开篇

本专栏采用融入【主力思维】的方法学&#xff0c;包含数据抓取、特征模型开发、历史验证回归测试、每日动态风险评估管理等技术&#xff0c;较大的增强股票投资胜率&#xff0c;让IT开发者拥有一套实用的属于自己思路的专用交易软件。 先简要介绍下系统运行的成果和项目架构&a…

这玩意终于有免费的了———Navicat Premium Lite

免费啦&#xff01;&#xff01;&#xff01;X&#xff01;&#xff01;&#xff01; 免费啦&#xff01;&#xff01;&#xff01;X&#xff01;&#xff01;&#xff01; 免费啦&#xff01;&#xff01;&#xff01;X&#xff01;&#xff01;&#xff01; 去下载吧&…

uniapp应用如何实现传感器数据采集和分析

UniApp是一种跨平台的应用开发框架&#xff0c;它支持在同一份代码中同时开发iOS、Android、H5等多个平台的应用。在UniApp中实现传感器数据采集和分析的过程可以分为以下几个步骤&#xff1a; 引入相关插件或库 UniApp通过插件或库的形式扩展功能。对于传感器数据采集和分析&…

无人机对地面运动目标定位---获取目标的移动方向和速度

目录 一、引子 我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位&#xff0c;当前&#xff0c;我们已经获得了每张相片上该目标的三维坐标&#xff0c;并且知道该无人机在飞行过程中拍照的时间间隔&#xff0c;那么我们就可以通过一定的计算&#xff0c;得…

Docker学习笔记(一)概念理解

一、什么是docker容器 Docker容器是一种轻量级、可移植的软件封装技术&#xff0c;它允许开发者将应用程序及其依赖、配置文件、运行环境等打包到一个独立的、自包含的执行单元中。容器与虚拟机相似&#xff0c;都提供了隔离的运行环境&#xff0c;但容器更加轻量级&#xff0c…

职业本科扩容:教育改革的新篇章与挑战

高考结束后&#xff0c;李文莉同学并没有如释重负的感觉&#xff0c;因为她正在为选学校、选专业而纠结。幸运的是&#xff0c;今年我国职业本科院校又增加了十多所&#xff0c;这对学习成绩稍差、但动手能力较强的她来说&#xff0c;无疑是个好消息。这几天&#xff0c;她已将…

《数字图像处理与机器视觉》案例四 基于分水岭算法的粘连物体的分割与计数

一、引言 分水岭算法&#xff08;Watershed Algorithm&#xff09;&#xff0c;是一种基于拓扑理论的数学形态学的分割方法&#xff0c;其基本思想是把图像看作是测地学上的拓扑地貌&#xff0c;图像中每一点像素的灰度值表示该点的海拔高度&#xff0c;每一个局部极小值及其影…

【Python123题库】#判断闰年 #判断奇偶数 #分段函数A

禁止转载&#xff0c;原文&#xff1a;https://blog.csdn.net/qq_45801887/article/details/140079827 参考教程&#xff1a;B站视频讲解——https://space.bilibili.com/3546616042621301 有帮助麻烦点个赞 ~ ~ Python123题库 判断闰年判断奇偶数分段函数A 判断闰年 类型&am…

静态方法与实例方法的区别

静态方法与实例方法的区别 1、静态方法&#xff08;Static Methods&#xff09;1.1 调用方式1.2 访问权限 2、实例方法&#xff08;Instance Methods&#xff09;2.1 调用方式2.2 访问权限 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1…

DDR3(一)

目录 1 SDRAM1.1 同步动态随机存储器1.2 位宽1.3 SDRAM结构1.4 SDRAM引脚图 2 SDRAM操作指令2.1 读写指令2.2 刷新和预充电2.3 配置模式寄存器2.4 读/写突发2.5 数据屏蔽 SDRAM是DDR3的基础&#xff0c;在学习DDR3之前&#xff0c;我们先来学习一下SDRAM的相关知识。 1 SDRAM …

Spring容器生命周期中如前置运行程序和后置运行程序

在Spring容器加入一个实现了BeanPostProcessor接口bean实例&#xff0c;重写postProcessBeforeInitialization、postProcessAfterInitialization方法&#xff0c;在方法里面写具体的实现&#xff0c;从而达到Spring容器在初如化前或销毁时执行预定的程序&#xff0c;方法如下&a…

浅谈 Linux 中的 core dump 分析方法

文章目录 一、什么是 core dump二、发生 core dump 的原因1. 空指针或非法指针引起 core dump2. 数组越界或指针越界引起的 core dump3. 数据竞争导致 core dump4. 代码不规范 三、core dump 分析方法1. 启用 core dump2. 触发 core dump2-1. 因空指针解引用而崩溃2-2. 通过 SI…