注:该学习笔记是根据曾志贤老师编写的《Python数据分析实战:从Excel轻松入门Pandas》所学习整理的笔记。
第3章 NumPy数据处理基石
这里写目录标题
一、NumPy的定义
1、定义
- DataFrame表格可以由Series数据构成,Series数据的本质是带标签的一维数组。
- 数组是指NumPy库中的数组,因为Python本身并没有数组这种数据类型。
- NumPy是一个运行速度非常快的数学库。支持大量维度数组与矩阵运算,而Pandas是基于NumPy的一种数据分析工具,因此要学好Pandas,就必须对NumPy有所了解。为了让NumPy表达起来更方便,将NumPy简写为np。
2、主要问题
- 整个NumPy数组中的元素都必须是同一数据类型。如果一组数组中既有文本也有数字,则不能进行各类算术运算。只要数组中涉及文本,整个数组的数据类型就会变成object,这个类型并不支持算术运算。
- 用NumPy数据进行数据分析很难知道哪一列(或者行)代表什么意思,因为通常都是按位置来选择列,比如arr[ : , 1]。
二、NumPy数组的创建与转换
1、普通数组
创建普通数组可以使用np.array( )函数,该函数的参数可以是任何序列类型对象。
数组中的元素数据类型必须保持一致。
import numpy as np
arr1 = np.array([1, 2, 3])
print(arr1)
arr2 = np.array([[1, 2, 3], ['a', 'b', 'c']])
print(arr2)
2、序列数组
创建一个指定数字范围内的等差序列数组,可以使用np.arange( )函数。
它创建数组的方式非常灵活,参数可以是1个、2个或者3个。
- 1个参数时,起始默认值为0.参数值为终止值,步长值默认为1。
- 2个参数时,第1个参数为起始值,第2个参数为终止值,步长值默认为1。
- 3个参数时,第1个参数为起始值,第2个参数为终止值,第3个参数为步长值。
import numpy as np
# 设置1个参数
arr1 = np.arange(4)
print(arr1)
# 返回 [0 1 2 3]
# 设置2个参数
arr2 = np.arange(7, 12)
print(arr2)
# 返回 [ 7 8 9 10 11]
# 设置3个参数
arr3 = np.arange(100, 110, 2)
print(arr3)
# 返回 [100 102 104 106 108]
3、随机数组
使用np.rendom.rand( )函数生成随机小数。
import numpy as np
# 创建单个随机小数
print(np.random.rand())
# 创建一维随机小数
print(np.random.rand(2))
# 创建二维随机小数
print(np.random.rand(2, 3))
# 创建三维随机小数
print(np.random.rand(2, 3, 4))
使用np.rendom.rendint( )函数生成随机整数。
import numpy as np
# 创建单个随机整数
print(np.random.randint(10, 99))
# 创建一维随机整数
print(np.random.randint(10, 99, size=3))
# 创建二维随机整数
print(np.random.randint(10, 99, size=(3, 2)))
# 创建三维随机整数
print(np.random.randint(10, 99, size=(3, 2, 4)))
4、转换数组
1)、DataFrame表格转换为数组
使用np.array( )函数、df.to_numpy( )函数、df.values属性将df表转换为数组。
import numpy as np
import pandas as pd
df = pd.read_excel('3-4.xlsx')
# 方式1
print(np.array(df))
# 方式2
print(df.to_numpy())
# 方式3
print(df.values)
2)、Series数据转换为数组
使用np.array( )函数、df.to_numpy( )函数、df.values属性将Series数据转换为数组。
import numpy as np
import pandas as pd
df = pd.read_excel('3-4.xlsx')
for t, s in df.items():
# 方式1
print(np.array(s))
# 方式2
print(s.to_numpy())
# 方式3
print(s.values)
三、NumPy数组的预处理
1、类型转换
使用astype( )函数进行数组的数据类型转换。
NumPy默认时间开始时间为1970-1-1,可使用pd.to_datetime( )函数自定义起始日期。
注意:Pandas和NumPy中的很多哈数都有dtype参数,表示可以在参数中设置数据类型。
注意:Excel的默认起始日期为:1900-1-1,设置NumPy自定义起始时间与Excel同步时,应修改为:1899-12-30。
类型名称 | 简写 | 注释 |
---|---|---|
bool | ?,b1 | 布尔型数据类型(True或者False) |
int8 | b,i1 | 字节(-128~127) |
int16 | h,i2 | 整数(-32768~32767) |
int32 | i,i4 | 整数(-2147483648~2147483647),可表示为int |
int64 | q,i8 | 整数(-9223372036854775808~9223372036854775807) |
unint8 | B,u1 | 无符号整数(0~255) |
uint16 | H,u2 | 无符号整数(0~65535) |
uint32 | I,u4 | 无符号整数(0~4294967295) |
uint64 | Q,u8 | 无符号整数(0~18446744073709551615) |
float16 | e,f2 | 半精度浮点数,包括1个符号位,5个指数位,10个尾数位 |
float32 | f,f4 | 单精度浮点数,包括1个符号位,8个指数位,23个尾数位 |
float64 | d,f8 | 双精度浮点数,包括1个符号位,11个指数位,52个尾数位,可表示为float |
str | a,S | 字符串,只能包含ASCII码字符,S或a后带数字表示字符串长度,超出部分将被截断,例如S20,a10 |
unicode | U | Unicode字符串,U后带数字表示字符串长度,超出部分将被截断,例如U20 |
datetime64 | M8 | 年(‘Y’)、月(‘M’)、周(‘W’)、天(‘D’)、小时(‘h’)、分钟(‘m’)、秒(‘s’)、毫秒(‘ms’)、微秒(‘μs’)等 |
timedelta64 | 表示时间差,年(‘Y’)、月(‘M’)、周(‘W’)、天(‘D’)、小时(‘h’)、分钟(‘m’)、秒(‘s’)、毫秒(‘ms’)、微秒(‘μs’) |
import numpy as np
import pandas as pd
# 在创建数组时,直接写明数组的数据类型
arr = np.array([100, '123', 99], dtype='int')
print(arr)
# 在创建数组时,未写明数据类型
arr1 = np.array([100, '123', 99])
# 将数组转换为整型
print(arr1.astype('int'))
# 将数组转换为浮点型
print(arr1.astype('float'))
# 将数组转换为字符串型
print(arr1.astype('str'))
# 将数组转换为日期,指定为天截止。
arr2 = np.array([0, 12525, 145], dtype='datetime64[D]')
print(arr2)
# 修改默认起始日期
print(pd.to_datetime([0, 12525, 145], unit='D', origin='2000-1-1'))
案例1:将数字转换为日期
将该表中的数字转换为日期
import numpy as np
import pandas as pd
df = pd.read_excel('3-6.xlsx')
df['出生日期'] = pd.to_datetime(df['出生日期'], unit='D', origin='1899-12-30')
df.to_excel('3-6-1.xlsx')
2、缺失值处理
- 缺失值是指没有任何值的空元素。
- 导入Excel文件后,如果某个单元格没有任何值,则会显示为NaN或者NaT(缺失时间)。
- 在NumPy中也可以通过np.nan来生成缺失值。
- 要判断数组中是否有缺失值,可使用np.isnan( )函数,将返回由布尔值组成的数组,还可以给缺失值填充指定的值。
import numpy as np
# 创建带有缺失值的数组
arr = np.array([2, 3, np.nan, 36, np.nan, 99])
# 筛选缺失值并且赋值
arr[np.isnan(arr)] = 1000
# 打印数组,并将数组数据类型转换为整数型
print(arr.astype('int'))
案例1:将带缺失值的列数据转换为日期
import numpy as np
import pandas as pd
df = pd.read_excel('3-7.xlsx', 0)
# 获取指定列放入数组
arr = np.array(df['出生日期'])
# 筛选数组中的缺失值,并重新赋值为1
arr[np.isnan(arr)] = 1
# 将指定列的数组进行类型转换
df['出生日期'] = pd.to_datetime(arr, unit='D', origin='1899-12-30')
df.to_excel('3-7-1.xlsx')
3、重复值处理
在做数据预处理时,去重复处理是处理比较常见的处理方式。在NumPy中,可以使用np.unique( )函数。
如果对多维数组做去重复处理,最后返回的是具有唯一值的一维数组。
参数axis=None为默认值,返回一维数组;axis=0表示以行为轴,axis=1表示以列为轴。
注意:通过np.unique( )处理重复后,始终返回的是数组结构数据。
import numpy as np
# 对一维数组去重
arr1 = np.array([9, 1, 2, 2, 1, 5, 9])
print(np.unique(arr1))
# 对多维数组去重
arr2 = np.array([[2, 1, 1], [2, 1, 1], [3, 1, 7], [3, 1, 7]])
# 返回一维数组
print(np.unique(arr2))
print(np.unique(arr2, axis=None))
# 返回多维数组
print(np.unique(arr2, axis=0))
4、存取元素
对一维数组的元素选取:arr[selection]
对二维数组的元素选取:arr[row_selection, column_selecyion]
import numpy as np
arr1 = np.array([10, 100, 1000.])
arr2 = np.array([[1., 2., 3.], [4., 5., 6.]])
# 返回标量,在一维数组中,只切片元素的位置
print(arr1[2])
# 返回 1000.0
# 返回标量,在二维数组中,指定行、列号
print(arr2[0, 0])
# 返回 1.0
# 返回二维数组,在二维数组中,指定所有行、指定列号以后的所有元素
print(arr2[:, 1:])
# 返回 [[2. 3.]# [5. 6.]]
# 返回一维数组,在二维数组中,指定所有行和指定的列号
print(arr2[:, 1])
# 返回 [2. 5.]
# 返回一维数组,在二维数组中,指定行号和指定列号之前的所有元素
print(arr2[1, :2])
# 返回 [4. 5.]
# 如果列存在标题,也可以通过arr['列标题']的方式获取到整个列元素
四、NumPy数组维度转换
1、数组维度转换
注意:数组之间的转换要遵循的原则是:转换后的元素个数必须与转换前的元素个数相同,否则转换不成功。
1)、一维数组转换为多维数组
数组的维度转换使用reshape( )函数
import numpy as np
arr1 = np.arange(1, 13)
# 转换为二维数组,2代表两组,6代表每组中的元素个数。且2X6的元素个数之和必须与转换前的元素个数相同。
print(arr1.reshape(2, 6))
# 转换为三维数组
print(arr1.reshape(3, 2, 2))
2)、多维数组转换为多维数组
使用reshape( )函数也可以将多维数组转换为多维数组
import numpy as np
arr2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
# 转换为另一种表现形式的二维数组
print(arr2.reshape(2, 6))
# 转换为三维数组
print(arr2.reshape(2, 2, 3))
3)、多维数组转换为一维数组
将多维数组转换为一维数组,除了使用reshape( )函数以外,也可以使用flatten( )函数,并且这种转换方式更为直接。
import numpy as np
arr3 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# .size属性是表示统计数组中的元素个数
print(arr3.reshape(arr3.size))
# 使用NumPy内置函数转换为一维数组
print(arr3.flatten())
2、数组合并
数组合并就是对两个及以上的数组做拼接
1)、一维数组合并
如果要将多个一维数组合并成一个一维数组,首先要将多个一维数组组织在列表中,然后使用np.concatenate( )函数对列表中的一维数组合并。
import numpy as np
# 一维数组合并
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr3 = np.array([7, 8, 9])
lst = [arr1, arr2, arr3]
arr4 = np.concatenate(lst)
2)、多维数组合并
合并多个多维数组与合并多个一维数组方法基本相同,但由于多维数组合并需要用户确认是横向合并还是纵向合并,所以要在np.concatenate( )函数中对axis参数指明合并方向,axis=1表示横向合并,axis=0表示纵向合并。
import numpy as np
# 多维数组合并
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[7, 8, 9], [10, 11, 12]])
lst = [arr1, arr2]
# 不指定方向合并,默认为纵向。
print(np.concatenate(lst))
# 指定纵向合并
print(np.concatenate(lst, axis=0))
# 指定横向合并
print(np.concatenate(lst, axis=1))
五、Series数据的创建
Series可以视为DataFrame表格的列,创建Series数据可使用pd.Series( )函数。
- 语法结构:
- pd.Series(data=None, index=None, dtype=None, name=None, copy=False)
- 参数说明:
- data:提供创建Series的数据,可以是列表、数组合字典等可迭代对象。
- index:提供Series的索引数据,允许有重复值,默认为RangeIndex(0,1,2…n)。
- dtype:设置Series数据的类型,如未指定则自动判断。
- name:设置Series数据的名称。
- copy:是否复制输入数据。
1、创建Series数据
import pandas as pd
s = pd.Series(['张三', '李四', '王五'], name='姓名')
2、用字典创建Series数据
import pandas as pd
s1 = pd.Series({'张三': 18, '李四': 19, '王五': 20})
3、创建Series数据时设置索引
注意:索引并非唯一值
import pandas as pd
s = pd.Series(['张三', '李四', '王五'], name='姓名', index=['A', 'B', 'C'])
# 索引自适应长度
lst = [4, 5, 6, 22, 66]
print(pd.Series(lst, index=range(100, 100 + len(lst))))
# 字典创建Series时,key默认为索引
dic = {'张三': 18, '李四': 19, '王五': 20}
print(pd.Series(dic))
4、创建Series数据时设置类型
import pandas as pd
s = pd.Series(['张三', '李四', '王五'], name='姓名', index=['A', 'B', 'C'], dtype='str')
六、DataFrame表格的创建
创建DataFrame表格使用pd.DataFrame( )函数。
- 语法结构:
- pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
- 参数说明:
- DataFrame:提供创建DataFrame表格的数据,可以为数组、列表和字典。
- index:提供DataFrame表格的行索引数据,默认为RangeIndex(0,1,2…n)。
- columns:提供DataFrame表格的列索引数据,默认为RangeIndex(0,1,2…n)。
- dtype:数据类型,只允许设置单个数据类型,,如果没有设置则自动判断。
- copy:是否从输入复制数据。仅影响DataFrame/二维数组输入。
1、使用NumPy数组创建DataFrame表格
import pandas as pd
import numpy as np
arr = np.array([['张三', '男', 28], ['李四', '女', 25], ['王五', '女', 19]])
print(pd.DataFrame(arr, index=[1, 2, 3], columns=['姓名', '性别', '年龄']))
2、使用Python列表创建DataFrame表格
import pandas as pd
lst = [['张三', '男', 28], ['李四', '女', 25], ['王五', '女', 19]]
print(pd.DataFrame(lst, index=[1, 2, 3], columns=['姓名', '性别', '年龄']))
3、使用Seize数据创建DataFrame表格
import pandas as pd
s1 = pd.Series(
['张三', '女', 28],
name='1',
index=['姓名', '性别', '年龄']
)
s2 = pd.Series(
['李四', '男', 25],
name='2',
index=['姓名', '性别', '年龄']
)
s3 = pd.Series(
['王五', '女', 19],
name='3',
index=['姓名', '性别', '年龄']
)
lst = [s1, s2, s3]
print(pd.DataFrame(lst))
# 返回的结果
姓名 性别 年龄
1 张三 女 28
2 李四 男 25
3 王五 女 19
4、使用Python字典创建DataFrame表格
1)、字典值为列表
import pandas as pd
dic = {
'姓名': ['张三', '李四', '王五'],
'性别': ['男', '女', '男'],
'年龄': [18, 25, 19]
}
print(pd.DataFrame(dic, index=['001', '002', '003']))
2)、字典值为数组
import pandas as pd
import numpy as np
dic1 = {
'姓名': np.array(['张三', '李四', '王五']),
'性别': np.array(['男', '女', '男']),
'年龄': np.array([18, 25, 19])
}
print(pd.DataFrame(dic1, index=['001', '002', '003']))
3)、字典值为Series
import pandas as pd
dic2 = {
'姓名': pd.Series(['张三', '李四', '王五'], index=['001', '002', '003']),
'性别': pd.Series(['男', '女', '男'], index=['001', '002', '003']),
'年龄': pd.Series([18, 25, 19], index=['001', '002', '003'])
}
print(pd.DataFrame(dic2))