当前位置: 首页 > news >正文

[黑马程序员Pandas教程]——DataFrame数据的增删改操作

目录:

  1. 学习目标
  2. DataFrame添加列
    1. 直接赋值添加列数据
  3. 删除与去重
    1. 删除
      1. df.drop删除行数据
      2. df.drop删除列数据
    2. 数据去重
      1. Dataframe去重
      2. Seriers去重
  4. 修改DataFrame中的数据
    1. 直接修改数据
    2. replace函数替换数据
    3. 按条件使用布尔值修改数据
    4. 执行自定义函数修改数据
      1. Series.apply()函数遍历每一个值同时执行自定义函数
      2. df.apply()函数遍历每一列同时执行自定义函数
      3. df.apply()函数遍历每一行同时执行自定义函数
    5. 了解函数向量化
  5. 总结
  6. 项目地址

1.学习目标

  • 知道drop函数删除df的行或列数据

  • 知道drop_duplicates函数对df或series进行数据去重

  • 知道unique函数对series进行数据去重

  • 知道apply函数的使用方法

  • 了解numpy.vectorize(func)函数向量化

2.DataFrame添加列

直接赋值添加列数据
import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()# 拷贝一份df
df3 = df2.copy()# 一列数据都是固定值
df3['new col 1'] = 33# 新增列数据数量必须和行数相等
df3['new col 2'] = [1, 2, 3, 4, 5]
df3['new col 3'] = df3.year * 2# 分别查看增加数据列之后的df和原df
print(df3)
print(df2)

3.删除与去重

删除
df.drop删除行数据
import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()# 拷贝一份df
df3 = df2.copy()print(df3)# 默认删除行,按索引值删除,不会在原df上删除,添加参数inplace=True,此时就在原df上进行删除
df4 = df3.drop([0])
print(df4)
# 在原df上进行删除
df3.drop([0], inplace=True)
print(df3)
# 可以删除多行
df5 = df3.drop([2, 4])
print(df5)
# 对series对象按索引值删除
print(df3.GDP)df6 = df3.GDP.drop([1, 3])
print(df6)
df.drop删除列数据
  • df.drop默认删除指定索引值的行 axis=0axis='index';如果添加参数axis=1axis='columns',则删除指定列名的列

import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()# 拷贝一份df
df3 = df2.copy()# 一列数据都是固定值
df3['new col 1'] = 33# 新增列数据数量必须和行数相等
df3['new col 2'] = [1, 2, 3, 4, 5]
df3['new col 3'] = df3.year * 2print(df3)df4 = df3.drop(['new col 3'], axis=1)
print(df4)
数据去重
Dataframe去重
  • 运行下面的代码获取具有重复数据的df(代码中使用的append函数会在后边《合并与变形》章节中详细介绍)

import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
print(df2)df4 = pd.concat([df2] * 2).reset_index(drop=True)
print(df4)# 去除重复的数据
# 默认对所有列进行去重,可以通过参数 subset=['列名1','列名2'...] 对指定的列进行去重
df5 = df4.drop_duplicates()
print(df5)
Seriers去重
import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
print(df2)df4 = pd.concat([df2] * 2).reset_index(drop=True)
print(df4)# Seriers对象使用drop_duplicates函数进行去重,返回Series对象
print(df4.country)
df5 = df4.country.drop_duplicates()
print(df5)# Seriers对象还可以使用unique函数进行去重,返回的ndarray数组
df6 = df4.country.unique()
print(df6)

4.修改DataFrame中的数据

直接修改数据
import pandas as pddf = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
# 拷贝一份数据
df5 = df.head().copy()
print(df5)df5['GDP'] = [5, 4, 3, 2, 1]
print(df5)
replace函数替换数据
import pandas as pd# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df6 = df.head().copy()
print(df6)# series对象替换数据,返回的还是series对象,不会对原来的df造成修改
df7 = df6.year.replace(1960, 19600)
print(df7)# 如果加上inplace=True参数,则会修改原始df
df6.country.replace('日本', '扶桑', inplace=True)
print(df6)# df也可以直接调用replace函数,用法和s.replace用法一致,只是返回的是df对象
df8 = df6.replace(1960, 19600)
print(df8)
按条件使用布尔值修改数据
  • 我们可以利用[s对象的判断表达式]来选取df中的数据,再进行赋值修改

import pandas as pd# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df7 = df.head().copy()
print(df7)
# 如果country是日本 那就修改GDP为7777
df7['GDP'][df7['country'] == '日本'] = 7777
print(df7)# 上述步骤解析
# df7['country'] == '日本'
# [df7['country'] == '日本']
# df7['GDP'][df7['country'] == '日本']
执行自定义函数修改数据
  • 有时需要我们对df或s对象中的数据做更加精细化的修改动作,并将修改操作封装成为一个自定义的函数;这时我们就可以利用<s / df>.apply()来调用我们自定义的函数
Series.apply()函数遍历每一个值同时执行自定义函数
import pandas as pd# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)# Series对象使用apply调用自定义的函数,返回新的Series对象
# 自定义函数必须接收一个参数
def foo(x):# x此时是s对象中一个数据# 本自定义函数返回的也是一个数据if x == '美国':return '美利坚'return xdf9 = df8['country'].apply(lambda x: foo(x))
print(df9)# Series对象使用apply调用自定义的函数,并向自定义函数中传入参数
# 自定义函数必须接收一个参数
def foo(x, arg1):# x此时是s对象中一个数据# 本自定义函数返回的也是一个数据if x == '美国':return '美利坚'return arg1df10 = df8['country'].apply(lambda x: foo(x, arg1='其他国家'))
print(df10)
 df.apply()函数遍历每一列同时执行自定义函数
import pandas as pd# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)def foo(s, arg1):# 此时s参数就是df中的一列数据,s对象# 函数也必须返回一列数据,s对象try:return s + arg1except:return s# 返回df对象
df9 = df8.apply(lambda x: foo(x, arg1=1))
print(df9)
df.apply()函数遍历每一行同时执行自定义函数
  • 使用参数axis=1,使df.apply()调用的自定义函数按行执行

import pandas as pd# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)def foo(s, arg1):# 此时s参数就是df中的一行数据,s对象# 函数也必须返回一行数据,s对象# print(s)if s['country'] == arg1:s.GDP = 6666return sreturn s# 返回df对象
df9 = df8.apply(lambda x: foo(x, arg1='美国'), axis=1)
print(df9)

 小结:

  • s.apply(自定义函数名, arg1=xx, ...) 对s对象中的每一个值,都执行自定义函数,且该自定义函数除了固定接收每一个值作为第一参数以外,还可以接收其他自定义参数

  • df.apply(自定义函数名, arg1=xx, ...) 对df对象中的每一列,都执行自定义函数,且该自定义函数除了固定接收列对象作为第一参数以外,还可以接收其他自定义参数

  • df.apply(自定义函数名, arg1=xx, ..., axis=1) 对df对象中的每一,都执行自定义函数,且该自定义函数除了固定接收行对象作为第一参数以外,还可以接收其他自定义参数

了解函数向量化
  • 运行下面会报错的代码

import pandas as pd# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)# 运行下面会报错的代码
# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)def bar(s):# 此时s参数就是df中的一列数据,s对象# 函数也必须返回一列数据,s对象if s != 1960:return selse:return s + 1# 报错
df10 = df9.apply(lambda x: bar(x))
print(df10)
# 运行上述代码会报错
  • 上述错误的代码中,if s != 1960:报错,s != 1960 返回一组bool值(向量),这个判断表达式没有问题,但和if连在一起使用就会报错----if只能与返回单一bool值(标量)的判断表达式放在一起;此时我们就需要这个if可以和向量放在一起使用,那么这个时候我们就可以使用函数向量化:让整个函数中原来不能和向量进行操作的代码变为可以和向量进行操作【这段话啥意思不理解也没关系,看下边的代码】

import pandas as pd
import numpy as np# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)def bar(s):# 此时s参数就是df中的一列数据,s对象# 函数也必须返回一列数据,s对象if s != 1960:return selse:return s + 1# 对原来的bar函数执行np.vectorize(),返回新的函数bar2
bar2 = np.vectorize(lambda x: bar(x))# 再使用新的bar2函数
df10 = df9.apply(bar2)
print(df10)

  • 还可以利用装饰器对函数进行向量化

import pandas as pd
import numpy as np# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)# 使用装饰器
@np.vectorize
def bar(s):# 此时s参数就是df中的一列数据,s对象# 函数也必须返回一列数据,s对象if s != 1960:return selse:return s + 1# 再使用被向量化装饰器装饰的bar函数
df10 = df9.apply(bar)
print(df10)

5.总结

  • df['列名'] = 标量或向量 修改或添加列

  • <df / s>.drop([索引值1, 索引值2, ...]) 根据索引删除行数据

  • df.drop([列名1, 列名2, ...], axis=1) 根据列名删除列数据

  • <df / s>.drop_duplicates() df或s对象去除重复的行数据

  • s.unique() s对象去除重复的数据

  • <df / s>.replace('原数据', '新数据', inplace=True) 替换数据

    • df或series对象替换数据,返回的还是原来相同类型的对象,不会对原来的df造成修改

    • 如果加上inplace=True参数,则会修改原始df

  • df['指定列'][df['列名']=='x'] = y 按条件df['列名']=='x'返回True的对应行的指定列的值修改为y

  • apply函数

    • s.apply(自定义函数名, arg1=xx, ...) 对s对象中的每一个值,都执行自定义函数,且该自定义函数除了固定接收每一个值作为第一参数以外,还可以接收其他自定义参数

    • df.apply(自定义函数名, arg1=xx, ...) 对df对象中的每一列,都执行自定义函数,且该自定义函数除了固定接收列对象作为第一参数以外,还可以接收其他自定义参数

    • df.apply(自定义函数名, arg1=xx, ..., axis=1) 对df对象中的每一,都执行自定义函数,且该自定义函数除了固定接收行对象作为第一参数以外,还可以接收其他自定义参数

  • new_func = numpy.vectorize(func) 函数向量化,返回一个新的函数

6.项目地址:

Python: 66666666666666 - Gitee.com

相关文章:

[黑马程序员Pandas教程]——DataFrame数据的增删改操作

目录&#xff1a; 学习目标DataFrame添加列 直接赋值添加列数据删除与去重 删除 df.drop删除行数据df.drop删除列数据数据去重 Dataframe去重Seriers去重修改DataFrame中的数据 直接修改数据replace函数替换数据按条件使用布尔值修改数据执行自定义函数修改数据 Series.apply(…...

【服务器】Java连接redis及使用Java操作redis、使用场景

一、Java连接redis-No-SQL 1、导入依赖 在你的项目里面导入redis的pom依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version> </dependency> 2、连接redis 连接redis …...

Spark 基础知识点

Spark 基础 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 什么是Spark 什么是Spark 1.1 定义&#xff1a;Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎 Spark最早源于一篇论文 Re…...

动作捕捉系统通过SDK与LabVIEW通信

运动分析、VR、机器人等应用中常使用LabVIEW对动作捕捉数据进行实时解算。NOKOV度量动作捕捉系统支持通过SDK与LabVIEW进行通信&#xff0c;将动作数据传入LabVIEW。 一、软件设置 1、形影软件设置 1、将模式切换到后处理模式 2、加载一个刚体数据 3、打开软件设置 4、选择网…...

【PTE-day02 sqlmap操作】

1、sqlmap简介 🍇sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL进行SQL注入。目前支持的数据库有MySql、Oracle、Access、PostageSQL、SQL Server、IBM DB2、SQLite、Firebird、Sybase和SAP MaxDB等. Sqlmap采用了以下5种独特的SQL注入技术 (1)…...

2021年03月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 不超过100个元素的有序数列&#xff0c;使用二分查找能找到指定的元素&#xff0c;可能的查找次数不包括&#xff1f; …...

2023.10.18 信息学日志

1. CF1689D Lena and Matrix 题目描述 n ⋅ m n \cdot m n⋅m 的矩阵&#xff0c;求矩阵上任意一点坐标使得到矩阵上的关键点曼哈顿距离最大值最小。数据范围&#xff1a; ∑ n ⋅ m ≤ 1 0 6 \sum n \cdot m \leq 10^6 ∑n⋅m≤106 题目概况 来源&#xff1a;Codeforces …...

Modbus封装库(Com,tcp,udp一应俱全)

自行封装在用的Modbus通迅库,集成了com,tcp,udp, 做个笔记吧&#xff0c; 以下头文件&#xff0c; #pragma once #include <functional> #include <vector> #include <string> #include <memory> #ifdef LIBMODBUS_EXPORTS #define LIBMODBUS_EXPORT_…...

专访HuggingFace CTO:开源崛起、创业故事和AI民主化丨智源独家

导读 HuggingFace CTO Julien Chaumond认为&#xff0c;在大模型时代&#xff0c;AI民主化至关重要。随着大语言模型和复杂人工智能系统的崛起&#xff0c;持续提升AI技术的可及性有助于确保这些技术的获取和控制不集中在少数强大实体手中。技术民主化促进了机会均等&#xff0…...

C++常用格式化输出转换

在C语言中可以用printf以一定的格式打印字符&#xff0c;C当然也可以。 输入输出及命名空间还不太了解的小伙伴可以看一看C入门讲解第一篇。  在C中&#xff0c;可以用流操作符&#xff08;stream manipulators&#xff09;控制数据的输出格式&#xff0c;这些流操作符定义在2…...

如何使用 Loadgen 来简化 HTTP API 请求的集成测试

引言 在编写 HTTP 服务的过程中&#xff0c;集成测试 1 是保证程序正确性的重要一环&#xff0c;如下图所示&#xff0c;其基本的流程就是不断向服务发起请求然后校验响应的状态和数据等&#xff1a; 为大量的 API 和用例编写测试是一件繁琐的工作&#xff0c;而 Loadgen 2 正…...

软件测试面试大家是不是一问到项目就不会了?

软件测试面试中&#xff0c;介绍做过的项目&#xff0c;可以说是必不可少的一道面试题了&#xff0c;对于面试的同学来说&#xff0c;该自己发挥呢&#xff1f; 把项目的所有功能噼里啪啦说一遍就完事了&#xff1f;当然不是&#xff0c;我们要搞清楚&#xff0c;面试官问这个…...

伐木猪小游戏

欢迎来到程序小院 伐木猪 玩法&#xff1a;控制小猪点击屏幕左右砍树&#xff0c;不能碰到树枝&#xff0c;考验手速与眼力&#xff0c;记录分数&#xff0c;快去挑战伐木吧^^。开始游戏https://www.ormcc.com/play/gameStart/199 html <script type"text/javascript…...

0007Java安卓程序设计-ssm基于Android的校园新闻管理系统

文章目录 **摘** **要**目 录开发环境 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 摘 要 网络的广泛应用给生活带来了十分的便利。所以把校园新闻管理与现在网络相结合&#xff0c;利用java技术建设校园新闻管理系统app&#xff0c;实…...

git增加右键菜单

有次不小心清理系统垃圾&#xff0c;把git右击菜单搞没了&#xff0c;下面是恢复方法 将下面代码存为.reg文件&#xff0c;双击后导出生效&#xff0c;注意&#xff0c;你安装的git必须是默认C盘的&#xff0c;如果换了地方要改下面注册表文件中相关的位置 Windows Registry …...

openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果

文章目录 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果117.1 前提条件117.2 背景信息117.3 操作步骤 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果 117.1 前提条件 审计功能总开关已开启。需要审计的审计项开关已开…...

学习代码20231106

解释代码&#xff1a;os.environ[“OMP_NUM_THREADS“] “1“ 这行代码涉及到 Python 的 os 模块和环境变量。它的作用是设置名为 “OMPNUMTHREADS” 的环境变量的值为 “1”。让我解释一下各部分的含义&#xff1a; 1.os.environ: 这是 Python 中的一个字典&#xff0c;包含…...

turtle绘制分形树-第10届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第5讲。 turtle绘制分形树&…...

【大厂招聘试题】__硬件工程师_2021年“美团”校招

目录 匹配职位&#xff1a;硬件工程师 1.&#xff08;多选题&#xff09;单处理系统中&#xff0c;进程P1,P2,P3处于就绪队列&#xff0c;进程P4&#xff0c;P6处于等待队列&#xff0c;P5正占用处理器运行&#xff0c;以下对接下来的运行合理的分析是&#xff08; &#xff…...

算法通关村第七关|黄金挑战|迭代实现二叉树的前、中、后序遍历

1.迭代实现前序遍历 public List<Integer> preOrderTraversal(TreeNode root) {List<Integer> res new ArrayList<Integer>();if (root null) {return res;}Deque<TreeNode> stack new LinkedList<TreeNode>();TreeNode node root;while (!…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...