Python库学习(七):科学计算库Numpy[续篇一]:结构数组

2023年 9月 26日 52.3k 0

1.介绍

结构数组是NumPy中的一种高级数据结构,它允许用户在单个数组中存储多种数据类型的元素。与普通的NumPy数组不同,结构数组的每个元素可以具有不同的数据类型,并且可以使用字段名来引用这些元素。这使得结构数组非常适合处理表格数据、数据库查询结果以及其他复杂数据结构。

2. 创建数组

2.1 字符串式声明

import numpy as np

if __name__ == '__main__':
    # 定义类型
    dt = "U10,i4,f"
    # 创建数组
    arr = np.array([
        [("Go", 2, 8.5)],
        [("Java", 3, 8.0)],
        [("Python", 1, 9.0)],
    ], dtype=dt)
    print(arr)

"""
[[('Go', 2, 8.5)]
 [('Java', 3, 8. )]
 [('Python', 1, 9. )]]
"""    

@注:字符串式声明比较简单,只要使用逗号隔开即可,如上述示例:i1,i4,f

2.2 元组列表式声明

a. 声明类型:

 dt = np.dtype([("字段名", "数据类型"),...,("字段名n", "数据类型n")])  

b. 使用示例:

import numpy as np

if __name__ == '__main__':
    # 定义类型
    dt = np.dtype([("name", "U10"), ("age", int), ("address", "U20"), ("weight", float)])
    # 创建数组
    arr = np.array([
        [("张三", 20, "北京昌平区", 74.5)],
        [("小花", 18, "上海徐汇区", 48.5)]
    ], dtype=dt)
    print("创建数组:\n", arr)
    print("访问arr[0]:\n", arr[0])
    print("访问arr['name']:\n", arr['name'])
    print("访问arr['age']:\n", arr['age'])
    
"""
创建数组:
 [[('张三', 20, '北京昌平区', 74.5)]
 [('小花', 18, '上海徐汇区', 48.5)]]
访问arr[0]:
 [('张三', 20, '北京昌平区', 74.5)]
访问arr['name']:
 [['张三']
 ['小花']]
访问arr['age']:
 [[20]
 [18]]
"""   

2.3 字段标题

元组列表除了上面的使用示例,还可以给字段加上标题,使用方式和语法如下:

a. 声明类型:

dt = np.dtype([(("标题", "字段名"), "数据类型"), ... ,(("标题n", "字段名n"), "数据类型")])  

b. 使用示例:

import numpy as np

if __name__ == '__main__':
    # 定义类型
    dt = np.dtype([(("姓名", "name"), "U10"), (("年龄", "age"), int), (("体重", "weight"), float)])
    # 创建数组
    arr = np.array([
        [("张三", 28, 80.23)],
        [("小明", 16, 66.55)],
    ], dtype=dt)
    print("创建数组:\n", arr)
    print("访问 字段标题-> \n", arr["姓名"])
    print("访问 字段名-> \n", arr["name"])
    
"""
创建数组:
 [[('张三', 28, 80.23)]
 [('小明', 16, 66.55)]]
访问 字段标题-> 
 [['张三']
 ['小明']]
访问 字段名-> 
 [['张三']
 ['小明']]
"""    

2.4 字典式声明

a. 声明类型:

 dt = {'names':('字段1',...'字段2'), 'formats':('类型1',...,'类型n')}

b. 使用示例:

import numpy as np

if __name__ == '__main__':
    # 定义类型
    dt = {"names": ("name", "age", "address", "weight"), "formats": ("U10", "i", "U20", "f")}
    # 创建数组
    arr = np.array([
        [("张三", 20, "北京昌平区", 74.5)],
        [("小花", 18, "上海徐汇区", 48.5)]
    ], dtype=dt)
    print("创建数组:\n", arr)
    print("访问arr[0]:\n", arr[0])
    print("访问arr['name']:\n", arr['name'])
    print("访问arr['age']:\n", arr['age'])

"""
创建数组:
 [[('张三', 20, '北京昌平区', 74.5)]
 [('小花', 18, '上海徐汇区', 48.5)]]
访问arr[0]:
 [('张三', 20, '北京昌平区', 74.5)]
访问arr['name']:
 [['张三']
 ['小花']]
访问arr['age']:
 [[20]
 [18]]
"""    

3. 类型说明

3.1 类型汇总

以下是NumPy结构数组的常见数据类型的列表,包括类型、字符代码和说明。

类型 字符代码 说明
int 'i' 整数数据类型
int8 'i1' 8位有符号整数类型
int16 'i2' 16位有符号整数类型
int32 'i4' 32位有符号整数类型
int64 'i8' 64位有符号整数类型
uint8 'u1' 8位无符号整数类型
uint16 'u2' 16位无符号整数类型
uint32 'u4' 32位无符号整数类型
uint64 'u8' 64位无符号整数类型
float 'f' 浮点数数据类型
float16 'f2' 16位浮点数类型
float32 'f4' 32位浮点数类型
float64 'f8' 64位浮点数类型
complex 'c' 复数数据类型
complex64 'c8' 64位复数类型
complex128 'c16' 128位复数类型
bool 'b' 布尔值数据类型
object 'O' 通用对象数据类型
string 'S' 字符串数据类型
unicode 'U' Unicode字符串数据类型
void 'V' 通用无类型数据类型
datetime 'M' 日期和时间数据类型
timedelta 'm' 时间间隔数据类型

数据类型的字符代码,用在NumPy中,表示对应的数据类型。

3.2 时间类型使用

import numpy as np

if __name__ == '__main__':
    # 定义类型
    dt = [
        ('day', 'datetime64[D]'),  # 表示日期,精确到天
        ('minutes', 'datetime64[m]'),  # 表示时间,精确到分钟
        ('second', 'datetime64[s]')  # 表示时间,精确到秒
    ]
    arr = np.array([
        ('2023-09-25', '2023-09-25T14:30', '2023-09-25T14:30:00'),
        ('2023-09-25', '2023-09-25T17:30', '2023-09-25T14:30:45')
    ], dtype=dt)
    print("arr: ", arr)
    print("计算时间差:", arr['minutes'][1] - arr['minutes'][0])
    print("计算时间差:", arr['second'][1] - arr['second'][0])
    
"""
arr:  [('2023-09-25', '2023-09-25T14:30', '2023-09-25T14:30:00')
 ('2023-09-25', '2023-09-25T17:30', '2023-09-25T14:30:45')]
计算时间差: 180 minutes
计算时间差: 45 seconds
"""    

'datetime64[D]:'精确到天,而'datetime64[m]:',精确到分钟,datetime64[s]: 精确到秒

4. 字符串

Numpy使用字符串类型时,常见会是这种格式S10、U20等,其中的10,20指的就是字符的长度,单位是字节。

4.1 对比示例

NumPy结构数组中,使用字符串类型时一定要指定长度,因为字符串类型,需要在内存中预先分配内存,换句话说如果你不指定长度,那么值是存不进去的,如下示例:

import numpy as np

if __name__ == '__main__':
    # 定义字符串--不指定长度
    arr = np.array([
        [("张三", 80.5)],
        [("李四", 67.5)],
    ], dtype="U,f")
    print("定义字符串--不指定长度: \n", arr)
    # 定义字符串--指定长度
    arr2 = np.array([
        [("李白", 90)],
        [("苏轼", 88)],
    ], dtype="U10,f")
    print("定义字符串--指定长度: \n", arr2)
    
"""
定义字符串--不指定长度: 
 [[('', 80.5)]
 [('', 67.5)]]
定义字符串--指定长度: 
 [[('张三', 80.5)]
 [('李四', 67.5)]]
"""    

4.2 原因汇总

使用字符串指定长度的原因,除了上面说的内存预分配的原因,还有其他原因,下面进行了汇总:

  • 内存分配:字符串类型的长度决定了每个字符串在内存中占用的空间大小。如果不指定长度,NumPy无法确定要为每个字符串分配多少内存,这会导致内存分配错误或不确定性,可能会破坏数据的完整性。
  • 数据存储:在结构数组中,每个元素都有固定的字节大小,这包括字符串字段。指定字符串长度允许NumPy为每个元素的字符串字段分配相应大小的内存块,确保数据存储的正确性。
  • 数据对齐:结构数组中的字段通常需要按照字节边界对齐,以提高内存访问效率。指定字符串长度有助于确保每个字符串字段与其他字段正确对齐,以防止不必要的内存开销和性能下降。
  • 数据操作:指定字符串长度还有助于NumPy正确执行数据操作,如拷贝、切片和比较。没有指定长度的字符串可能会导致不明确的行为或错误。
  • 4.3 S、U的区别

    NumPy中,字符串类型有两种常见的类型,分别是S(string)(字节字符串)和U(Unicode)(字符串)。这两种类型在处理字符串数据时具有不同的特性和用途,以下是它们的对比:

  • S 字符串(字节字符串):
    • 字符编码:S字符串使用字节编码,通常用于处理ASCII字符集。这意味着它不支持多语言字符或特殊字符,只能表示ASCII字符。
    • 存储效率:S字符串在内存中以字节为单位存储,因此在存储方面比U字符串更加紧凑,但只能表示有限的字符集。
    • 示例:'S10' 表示包含最多10个ASCII字符的S字符串,例如 'Hello'
    • 适用场景:当你知道字符串只包含ASCII字符或需要节省内存时,可以选择使用S字符串。常见用途包括文件名、用户名、产品代码等。
  • U 字符串(Unicode字符串):
    • 字符编码:U字符串使用Unicode编码,支持多语言字符、特殊字符和表情符号等。它更加通用,适用于处理各种语言的文本。
    • 存储效率:U字符串在内存中以Unicode字符的形式存储,因此通常会占用更多的内存。但它具有更广泛的字符支持。
    • 示例:'U20' 表示包含最多20个Unicode字符的U字符串,例如 '你好,世界'
    • 适用场景:当你需要处理多语言字符、特殊字符、国际化文本或包含Unicode字符的数据时,通常应选择使用U字符串。它适用于Web应用、国际化应用程序、文本处理等场景。
  • @注:当你需要存储中文字符时, 使用Unicode

    5. 字节顺序

    5.1 概念说明

    大端字节顺序(Big-Endian)和小端字节顺序(Little-Endian)是两种用于存储多字节数据(如整数、浮点数)的不同方式。它们决定了在内存中多字节数据的字节存储顺序。

    5.2 大端字节顺序

    在大端字节顺序中,数据的高位字节(Most Significant Byte,MSB)存储在内存的低地址处,而低位字节(Least Significant Byte,LSB)存储在内存的高地址处。这就好像你阅读英文文本,从左到右逐个字母阅读一样。

    示例: 假设我们要存储整数值0x1234(十进制为4660),在大端字节顺序下,在内存中的存储方式是:

    高地址 --> 0x12 | 0x34  0x34 | 0x12 :指定大端字节顺序。
    

  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论