数据治理 | 数据分析与清洗工具:Pandas 数据类型转换(赠送本文同款数据!

优采云 发布时间: 2022-05-01 09:11

  数据治理 | 数据分析与清洗工具:Pandas 数据类型转换(赠送本文同款数据!

  Part1前言上期文章中,我们介绍了数据中的各种类型的缺失值以及如何处理这些缺失值;同时也介绍了常见的数据重复问题并奉上了处理重复数据的方法。这些处理方法对大家的数据治理、数据分析工作都有着至关重要的作用。本期文章将会继续学习 Pandas 工具,学习如何转换数据类型。读完本文后,灵活转换数据类型将不再是问题!本文中所有 Python 代码均在集成开发环境 Visual Studio Code (VScode) 中使用交互式开发环境 Jupyter Notebook 编写。Part2为什么需要做数据类型转换数据的含义与数据的类型是息息相关的,正确的数据类型能够支撑数据含义的正确表示。当一些数据的类型出现错乱时,它们的含义也会变得“诡异”。请看下面几个例子:

  错误示范

  正确示范

  原因解析

  今年是 2022.0年

  今年是 2022 年

  2022 作为一个年份时,应该保存为整数型或者字符型,而不是浮点型(小数型)数字 2022.0

  圆周率保留两位小数的结果是3

  圆周率保留两位小数的结果是 3.14

  圆周率保留两位小数应该是浮点数 3.14,如果转为整数型,其结果就会是 3

  1 + 1 = 11

  1 + 1 = 2

  1 + 1 = 11 实际上是字符串拼接,即 '1' + '1' 得到了 '11'

  [0, 1, 2] 的第一个元素是[

  [0, 1, 2] 的第一个元素是 0

  列表 [0, 1, 2] 被保存为字符型,它的真面目是 "[0, 1, 2]",这个字符串的第一个元素是 '[' 而不是 0

  我们早已经知道,Python 中字符串是用英文引号引起来的,就像是 'Python',"Python"。你可能会觉得,既然如此,数字型数据和字符型数据不就不容易搞混了吗?例如,数字 2022 和 字符串 "2022" ,很容易就能区分。然而,实际的情况却是,容易搞混,很容易搞混!这是因为在 Pandas 中,所有字符数据前后的引号都不会显示出来,如果显示出了引号,那么这些引号也是字符串中的字符。所以使用 Pandas 处理数据,为了避免类似的情况出现,学习数据类型转换是非常有必要的。Part3类型转换大多数时候,数据中不同字段的数据类型是不一定全都一样;同一个字段中,数据的类型是一般是一致的。所以进行数据类型转换时不需要一个一个对数据值做类型转换,直接操作一个字段会更加方便。我们使用本期赠送的数据作为介绍 Pandas 的示例数据,使用 Excel 打开数据【5G 产业全国各省市分年度专利申请、专利授权情况(2000-2019.9).xlsx】,如下图所示:

  

  赠送的数据中没有缺失值,其中值为数字的字段在 Excel 中是数字类型;我们使用 Pandas 读取 Excel 或者 csv 数据时,系统会自动地将每个字段读取为合适的数据类型。如果需要自定义一些(或者所有)字段的类型,我们也可以自己指定每个字段的数据类型(数据必须满足指定类型的格式,例如我们不可以将 “省份名” 字段设置为 整数型)。使用 Pandas 读取这个 Excel 数据,代码和输出如下:

  # 数据存储的路径<br />path = './5G 产业全国各省市分年度专利申请、专利授权情况(2000-2019.9).xlsx'<br /># 这里指定字段的数据类型<br />columns_type = {'年份':'str', <br />                '省份名':'str', <br />                '省份行政代码':'int',                                 <br />                '专利申请':'int', <br />                '专利授权':'int', <br />                '专利类型':'str'}<br /># dtype 参数用于指定字段的类型,如果不需要特意指定字段的类型,不使用 dtype 参数即可<br />data = pd.read_excel(path, dtype=columns_type)<br />data<br />

  

  读取数据后我们使用 Pandas 中的相关方法生成一个新的列,这一列中的数据是一个包含专利申请、专利授权和专利类型的列表。操作代码和新生成的数据如下:

  # 根据专利申请、专利授权和专利类型三个字段得到一个新字段<br />data['列表'] = data.apply(lambda X: [X['专利申请'], X['专利授权'], X['专利类型']] ,axis=1)<br />data<br />

  

  将新生成的数据保存为 csv 文件后再读取,读取时我们故意将部分字段读取为错误的类型,随后使用错误的数据来给大家演示如何进行数据类型的转换。

  # 将刚刚新生成的数据保存为 csv 文件<br /># 参数 index=False 的含义是,不讲数据索引写入 csv 文件中<br />data.to_csv('新数据.csv', index=False)<br /><br /># 使用错误的字段类型重新读取数据<br /># 我们将年份读取为浮点型(小数型),将专利申请读取为字符型<br />wrong_type = {'年份':'float',                                   <br />              '专利申请':'str'}<br />DATA = pd.read_csv('新数据.csv', dtype=wrong_type)<br /><br /># 查看专利申请字段类型<br />print(DATA.专利申请.dtype)  # 输出:object,说明该字段含有字符型数据<br />DATA<br />

  

  可以看到,“年份” 字段中所有的年份都变为小数型;通过代码也判断出 “专利申请” 字段不再是整数型,而是字符型,因为 DataFrame 中的字符型数据不会显示两端的引号,所以无法目测其类型。那么这种内容为数字的字符型数据会给我们什么麻烦呢?假设我们需要使用 专利授权/ 专利申请 来计算专利授权率时 ,会发现整数和字符之间无法运算。如果这两个字段中的值的都是字符型,那么两者只能进行加法运算,例如:“45” + “8” == “458”,这恐怕更不是我们想要的结果。接下来我们使用数据类型转换的方法来纠正这些错误的数据。1使用 astype() 转换基本类型Pandas 专门为类型转换提供了一个 astype() 方法,这个方法可以将数据类型转换为希望的类型,既可以操作 Series,又可以操作 DataFrame,使用时只需要传入转换后的类型即可。我们在往期的文章中提到过,Pandas 中绝大多数涉及到数据修改的方法,他们都不会直接修改原始的数据,而是返回一个新的数据。astype()也是一样的,默认返回一个新的数据。场景 1:将数据中的年份字段转换为整数型

  # 将字段类型由浮点型(小数型)转换为整数型 int<br /># 返回一个新数据,调用该方法的是一个 Series,返回值也将是一个 Series<br />DATA['年份'].astype(int)<br />

  

  希望类型转换操作在原始数据中生效可以使用下面的代码。

  # 将新生的数据重新赋值给原始数据即可<br /># 赋值操作不会返回任何值<br />DATA['年份'] = DATA['年份'].astype(int)<br /># 输出查看转换后的数据<br />DATA<br />

  

  场景 2:将数据中所有内容转换为字符型数据,转换后的数据命名为ALL_STR

  # 将类型转换为字符型数据后的新数据命名为 ALL_STR<br />ALL_STR = DATA.astype(str)<br /># 查看新数据的信息<br />ALL_STR.info()<br />

  

  所有的字段类型都变为 object,说明所有字段中都含有字符型数据,操作生效。另外,当字段中存在无法转换的数据值时,可以指定参数 errors='ignore' 来忽略无法转换的数据值。假如我们希望将所有字段都转换为浮点型(小数型),但是字符型数据 “北京” 、“45”、“发明专利” 等字符型数据无法转换为浮点型,我们则可以使用下面的代码来转换可以转换的字段:

  # 指定参数 errors='ignore',忽略无法转换的数据值<br />DATA.astype(float, errors='ignore')<br />

  

  可以看到,除了一些字符型数据之外,其他的数字类型数据都被转换为浮点型(小数型)数据。同样地,如果不进行赋值操作,那么就会返回一个新的数据,而原始数据不会发生变化。2使用 eval() 转换特殊类型astype() 方法多用于浮点型 float、整数型 int 和 字符型 str 的转换操作。当涉及到字符型转化为列表,字典等 Python 的组合数据类型时,则需要使用 Python 自带的方法 eval() 。该函数可以去掉字符串最外侧的引号,并按照 Python 语句方式执行去掉引号后的字符内容。下面我们举例介绍一下 eval() 的用法。

  # 对字符串 '12' 做转换<br />eval('12')     # 得到整数:12<br /><br /># 对字符串 '12.5' 做转换<br />eval('12.5')   # 得到浮点数:12.5<br /><br /># 对字符串 '12+5' 做转换<br />eval('12+5')   # 得到整数:17<br /><br /># 定义变量 a 后对字符串 'a' 做转换<br />a = '20'<br />eval('a')      # 得到 a 的值:20<br /><br /># 对字符串 "[11,12,'列表元素']" 做转换<br />eval("[11,12,'列表元素']") # 得到列表:[11, 12, '列表元素']<br /><br /># 定义变量 m,n 后对字符串 '[m,n,m-50]' 做转换<br />m=100<br />n='某个字符串'<br />eval("[m,n,m-50]")  # 得到列表:[100, '某个字符串', 50]<br />

  根据上面的例子可以看出,eval() 确实可以去掉字符串最外侧的引号,并按照 Python 语句方式执行去掉引号后的字符内容。这个方法不仅可以转换列表形式的字符串,对诸如字典、元组以及集合等 Python 数据类型形式的字符串,该方法依然可用。场景 3:将数据中“列表”字段转换为 Python 列表类型由于 eval() 方法操作的是字符串对象,一次只接受一个需要转化的对象,当需要使用它来对 DataFrame 的一整个字段做转换操作时,需要借助循环或者其他的 Pandas 方法。

  # 输出查看转换之前"列表"字段最后一个值的类型,原始的类型为 str 型<br />print(type(DATA['列表'].values[-1]))<br /># 输出:,确认是字符型<br /><br /># 方法 1:借助 for 循环<br />for i in DATA.index:<br />    # 遍历数据的索引<br />    # 根据索引找到待转换的数据<br />    Target = DATA.loc[i,'列表']<br />    # 将转换后的数据重新赋值给原来位置的数据值<br />    DATA['列表'][i] = eval(Target)<br />    <br /># 输出查看"列表"字段最后一个值的类型,若为列表,说明转换成功<br />print(type(DATA['列表'].values[-1]))<br /># 输出:,转换成功<br /><br /># 方法 2:借助 Pandas 方法 map()。不再输出查看类型<br />DATA['列表'] = DATA['列表'].map(eval)<br /><br /># 方法 3:借助 Pandas 方法 apply()。不再输出查看类型<br />DATA['列表'] = DATA['列表'].apply(eval)<br />

  后面两种方法可以实现 方法 1 同样的效果,且代码量更少。Part4总结本期文章中,我们介绍了数据类型错误带来的影响,同时也介绍了转换字段数据类型的方法。使用类型转换方法可以在基本的数据类型之间进行合理的转换。同时也介绍了转换特殊数据类型的方法。学习这些可以让我们灵活地转换数据的类型,避免类型错乱带来的麻烦。在最后的 场景3中,我们使用了map() 和 apply() 两个方法,使用更少的代码完成了同样的功能。下期文章我们将会继续介绍 Pandas,学习如何使用以上两种方法来根据已有的数据生成新的数据列(数据列衍生)。

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线