
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
简介 统计软件的作用: 统计分析软件是数据分析的主要工具 统计设计完成之后,完整的数据分析过程包括: - 数据的收集 - 数据的整理 - 数据的分析 - 结果的报告 统计学为数据分析过程提供一套完整的科学的方法论,统计软件为数据分析提供了实现手段 spss发展简史 软件名称: - 最早:Statisical Package for Social Science - 现在:IBM SPSS Statistics 软件发展概览: - 60年代:美国斯坦福大学三位学生所制 - 70年代:SPSS总部成立于芝加哥,推出SPSS中小型机版——SPSSX - 80年代:微机版(V1~4) SPSS/PC+ - 90年代:Windows版(V6~10) - 本世纪:11~20版,中文版 SPSS的基本特点 优势: - 功能强大 - 兼容性好 - 易用性强 - 扩展性高(以一种不同的方式) 劣势: - 计算速度相对较慢 - 在统计模型的纳入上速度较慢 界面及基本操作 初始打开软件界面 1-界面.png 初次使用打开软件注意的地方 2初次使用打开软件界面显示的内容.png 说明这个软件已经被授权准备就绪 SPSS主要几种窗口 结果浏览窗口 - 提供类似资源管理器的界面 语法窗口 - 编写SPSS程序时使用 - 功能集中体现在菜单"run"中 脚本窗口 - 高级用户进行SPSS二次平台开发时使用 - Script菜单:提供了基本的开发功能 - Debug菜单:提供程序调试的常用功能 统计分析软件的基本使用方式 人机交互对话方式 批处理(程序)方式 菜单方式和对话框方式 SPSS的四种运行方式 菜单对话框方式 - 最常用,最好记,重用性差,效率最低 程序方式 - 适合于批量数据分析,但需要编程能力 include命令方式 - 适合于较大规模的分析项目 SPSS Production Facility方式 - 适合于分布式环境中在服务器上执行分析 SPSS的四种结果输出 枢轴表 - 增强的多维立体表格,拥有动态展示功能 文本格式 - 标准的RTF文本 标准图与交互图 - 都具有动态展示功能 - 交互图功能更强,但已经被取消 模型 - 具有更强大的分析结果展示功能 SPSS的菜单项 文件 3文件菜单.png 数据与转换 5数据与转换.png 分析 6分析.png 图形 帮助 SPSS对话框基本操作规范 一级对话框元素 - 候选变量列表框 测量尺度+标签+变量名方式 - 选入变量列表框 - 变量移动纽 根据当前框的状态不断变化 二级对话框元素 - 下拉列表框 功能实际上和单选框组相同 - 文本框 往往会和单选框、复选框结合起来使用 - 框组 以上各种元素的集合 集中完成某项功能 SPSS结果窗口操作 结果文件的打开和保存 - 打开和保存都为spv格式, 后缀名都为.spv 结果内容的移动和删除 - 标准的拖放式操作 - 在大纲视图中操作最方便 结果的拷贝、导出操作 - 注意中文兼容性问题,必要时需要对软件进行设置 ** 原创文章,转载告知** 个人博客地址:www.limiao.tech
栈 栈:是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端进行加入数据和输出数据的运算。没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,确定了一种默认的访问顺序。 由于只能在一端操作,因此按照后进先出的原理运作 栈的实现 支持操作: Stack()创建一个新的空栈 push(item)添加一个新的元素item到栈顶 pop()弹出栈顶元素 peek()返回栈顶元素 is_empty()判断栈是否为空 size()返回栈的元素个数 class Stack(object): """栈""" def __init__(self): self.__list = [] def push(self, item): """加入元素""" self.__list.append(item) def pop(self): """弹出元素""" return self __list.pop() def peek(self): """返回栈顶元素""" if self.__list: return self.__list[-1] else: return None def is_empty(self): """判断是否为空""" #return self.__list == [] return not self__list def size(self): """返回栈的大小""" return len(self.__list) if __name__ == "__main__": stack = Stack() stack.push("hello, world") stack.push("hello, python") stack.push("hello, China") print(stack.size()) print(stack.peek()) print(stack.pop()) print(stack.pop()) 队列与双端队列 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表 队列是一种先进先出的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作。 队列的实现 class Queue(object): """队列""" def __init__(self): self.__list = [] def enqueue(self,item): """往队列中添加一个item元素""" self.__list.append(item) def dequeue(self): """从队列头部删除一个元素""" return slef.pop(0) def is_empty(self): """判断一个队列是否为空""" return self.__list == [] def size(self): """返回队列的大小""" return len(self.__list) if __name__ == "__main__": s = Queue() s.enqueque(1) s.enqueque(2) s.enqueque(3) s.enqueque(4) print(s.pop()) print(s.pop()) print(s.pop()) print(s.pop()) 双端队列 双端队列,是一种具有队列和栈的性质的数据结构 双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。双端队列可以在队列任意一端入队和出队 双端队列的实现 操作: Deque()创建一个空的双端队列 add_front(item)从队头加入一个item元素 add_rear(item)从队尾加入一个item元素 remove_front()从队头删除一个item元素 remove_rear()从队尾删除一个item元素 is_empty()判断双端是否为空 size()返回队列大小 class Deque(object): """双端队列""" def __init__(self): self.__list = [] def add_front(self, item): """往队列头部添加一个item元素""" self.__list.insert(0, item) def add_rear(self, item): """往队列尾部添加一个item元素""" self.__list.append(item) def pop_front(self): """从队列头部删除一个元素""" return self.__list.pop(0) def pop_rear(self): """从队列尾部删除一个元素""" return self.__list.pop() def is_empty(self): """判断一个队列是否为空""" return self.__list == [] def size(self): """返回队列大小""" return len(self.__list) 原创文章,转载周知 持续更新... 个人博客地址:www.limiao.tech
概念 在程序中,经常需要将一组(通常为同一个类型的)数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等(例如,Python中的列表)。一组数据中包含的元素个数可能发生变化(可以增加或者删除元素)。 对于元素增删改查的需求,最简单的解决办法就是将这一组元素当做一个序列,用元素序列里的位置和顺序,表示实际应用中的某种有意义的信息,或者表示数据之间的某种关系。 这样的一组序列元素的组织形式,即可抽象为线性表,一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系。线性表是最基本的数据结构之一。 根据线性表的实际存储方式,分为两种实现模型: 顺序表:将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示 链表: 将元素存放再通过链接构造起来的一系列存储块中 顺序表的基本形式 数据元素本身连续存储,每个元素所占的存储单元大小相同,元素的下标是其逻辑地址,而元素存储的物理地址(实际内存地址)可以通过存储区的起始地址加上逻辑地址与存储单元大小的乘积计算而得 即: L0c(i) = L0 + i * c 作图解释为下: 1_note_shunxubiao.png 32位操作系统中,一个整型占用4个字节(Byte),因此列表my_list中四个整型占用字节数为16个字节,且每个元素所占用字节数相同 所以访问指定元素时无需从头遍历,通过计算便可获得对应地址,其时间复杂度为O(1). 顺序表的基本形式的特殊形式 如果元素的大小不统一,则须采用元素外置的形式,将实际数据元素另行存储,而顺序表中各单元位置保存对应元素的地址信息(即链接)。由于每个链接所需的存储量相同,通过上述公式,可以计算出元素链接的存储位置,而后顺着链接找到实际存储的数据元素。此时公式中的 c 则不再是数据元素大小,而是存储一个链接地址所需的存储量。 顺序表的结构 不考虑用Python语言具体实现,真正实现数据表结构的时候,怎么构造数据 2_note_顺序表的结构.png 出了存储数据的数据区之外,往往还会加上表头信息 表头信息即:上图中上面的部分 下面部分为数据区 (连续的存储空间,内存的概念见后面的图解) 构造一个数据表的时候,首先要预估数据需要多少的空间,指明数据存储所需空间,即数据区。如上图中所示,即为8个数据。那么就要向计算机申请8个空间,在表头指明 一个顺序表的完整信息包括两部分,一部分是表中的元素集合,另一部分是为实现正确操作而需记录的信息,即有关表的整体情况的信息,这部分信息主要包括元素存储去的容量和当前表中已有的元素个数两项。 顺序表的两种基本实现方式 一体式结构: 3_note_顺序表的两种实现方式一.png 一体式结构,存储表信息的单元与元素存储区以连续的方式安排在一块存储区里,两部分数据的整体形成一个完整的顺序表对象,这种结构整体性强,易于管理。 由于数据元素存储区域是表对象的一部分,顺序表创建后,元素存储区就固定了 分离式结构: 4_note_顺序表的两种实现方式二.png 分离式结构,表对象里只保存与整个表有关的信息(容量个元素个数),实际数据元素存放在另一个独立的元素存储区里,通过链接与基本表对象关联。 元素存储区替换 一体式结构由于顺序表信息区与数据区连续存储在一起,所以想要更换数据区,就只能整体搬迁,即整个顺序表对象(存储顺序表的结构信息的区域)改变了。 分离式结构想要更换数据区,只需要将表信息区中的数据区链接地址更新即可,而该顺序表对象不变。 元素存储区扩充 采用分离式结构的顺序表,若将数据区更换为存储空间更大的区域,则可以在不改变表对象的前提下对其数据存储区进行了扩充,所有使用这个表的地方都不必修改。只要程序的运行环境还有空闲存储,这种表结构就不会因为满了而导致操作无法进行。此种顺序表被称为动态顺序表,因为其容量可以在使用中动态变化。 扩充的两种策略 每次扩充增加固定数目的存储位置,如每次扩充增加8个元素位置,这种策略称为线性增长 每次扩充容量加倍,如每次扩充增加一倍存储空间。 特点: 减少了扩充操作的执行次数,但可能会浪费空间资源。以空间换时间,推荐的方式。 补充: 内存: 5_内存.png 思维导图 6_顺序表思维导图.png 顺序表的操作 增加元素 7_顺序表的操作.png 尾端加入元素,如图所示,直接在顺序表的元素末尾加上元素,其时间复杂度为O(1) 保序的加入元素,如图所示,将增加的元素50,放在索引为1的位置,则对应的其他元素则分别向后移动,此为保序,没有破坏增加元素之前的元素顺序,但因会让增加元素所在位置之后的元素都产生移动,其时间复杂度为O(n) 非保序的加入元素,其时间复杂度为O(1),由于其会破坏顺序表原有的元素顺序,因此不常用 删除元素 8_顺序表的操作_删除元素.png ) 删除表尾的元素,其时间复杂度为O(1) 保序的元素删除,时间复杂度为O(n) 非保序的元素删除,时间复杂度为O(1) Python 中的顺序表 Python 中的list和tuple两种类型采用了顺序表的实现技术 tuple 是不可变类型,即不变的顺序表,因此不支持改变其内部状态的任何操作,而其他方面,则与list的性质类似 list 的基本实现技术 Python 标准类型list 就是一种元素个数可变的线性表,可以加入和删除元素,并在各种操作中维持已有元素的顺序(即保序),而且还具有以下行为特征: 基于下标(位置) 的高效元素访问和更新,时间复杂度是O(1); 为满足该特征,应该采用顺序表技术,表中元素保存在一块连续的存储区中。 允许任意加入元素,而且在不断加入元素的过程中,表对象的标识不变;为满足该特征,必须能更换元素存储区,并且为保证更换存储区时list对象的标识不变,只能采用分离式实现技术。 在Python的官方实现中,list就是一种采用分离式技术实现的动态顺序表。因此,使用list.append()加入元素比在指定位置插入元素效率高。 重点总结: 在Python的官方实现中,list实现采用了下面的策略,在建立空表时,系统分配一块能容纳8个元素的存储区;在执行插入操作(insert和append)时,如果元素存储区满就换一块4倍大的存储区。但如果此时的表已经很大(目前的阈值为50000),则改变策略,采用加一倍的方法。引入这种改变策略的方式是为了避免出现过多空闲的存储位置。 作者:techLee 个人博客地址:www.limiao.tech 原创文章,转载请告知
Python 正则表达式(regex) 正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑 正则表达式非Python独有,在Python中使用re模块实现 常见匹配模式 模式 描述 \w 匹配数字、字母、下划线 \W 匹配非数字、字母、下划线 \s 匹配任意空白字符,等价于[\t\n\r\f] \S 匹配任意非空字符 \d 匹配任意数字,等价于[0-9] \D 匹配任意非数字 \A 匹配字符串开始 \Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串 \z 匹配字符串结束 \G 匹配最后匹配完成的位置 \n 匹配一个换行符 \t 匹配一个制表符 ^ 匹配字符串的开头 $ 匹配字符串的末尾 . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 [...] 用来表示一组字符,单独列出:[abc]匹配"a","b"或"c" [^...] 不再[]中的字符:[^abc]匹配除了a,b,c之外的字符 * 匹配0个或多个的表达式 + 匹配1个或多个的表达式 ? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪模式 {n} 精确匹配n个前面表达式 {n,m} 匹配n到m次由前面的正则表达式定义的片段,贪婪模式 a|b 匹配a或b () 匹配括号内的表达式,也表示一个组 re.match re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话, match()就返回none re.match(pattern,string,flags=0) 常规匹配 import re content = 'Hello 111 2222 World hello python' print(len(content)) res = re.match('^Hello\s\d\d\d\s\d{4}\s\w{5}\s.*python$', content) print(res) print(res.group()) print(res.span()) 运行结果: 33 <_sre.SRE_Match object; span=(0, 21), match='Hello 111 2222 World '> Hello 111 2222 World (0, 21) 泛匹配 import re content = 'Hello 111 2222 World hello python' res = re.match('^Hello.*python$', content) print(res) print(res.group()) print(res.span()) 运行结果: <_sre.SRE_Match object; span=(0, 33), match='Hello 111 2222 World hello python'> Hello 111 2222 World hello python (0, 33) 匹配目标 import re content = 'Hello 111 2222 World hello python' res = re.match('^Hello\s(\d+)\s(\d+)\s.*python$', content) print(res) print(res.group(1), res.group(2)) 运行结果: <_sre.SRE_Match object; span=(0, 33), match='Hello 111 2222 World hello python'> 111 2222 贪婪模式 import re content = 'Hello 111 2222 World hello python' res = re.match('^H.*(\d+)\s(\d+).*python$', content) print(res) print(res.group(1), res.group(2)) 运行结果: <_sre.SRE_Match object; span=(0, 33), match='Hello 111 2222 World hello python'> 1 2222 非贪婪模式 import re content = 'Hello 111222 World hello python' res = re.match('^He.*?(\d+).*?python$', content) print(res) print(res.group(1)) 运行结果: <_sre.SRE_Match object; span=(0, 31), match='Hello 111222 World hello python'> 111222 匹配模式 模式 描述 re.I 匹配的字符忽略大小写 re.M 多行匹配 re.L 本地化识别匹配 re.U 根据Unicode进行相应化解析 re.S 让 . 匹配包括换行符 import re content = """Hello 1112222 World hello python""" res = re.match('^H.*?(\d+).*?python$', content, re.S) print(res) print(res.group(1)) 运行结果: <_sre.SRE_Match object; span=(0, 43), match='Hello 1112222 World \n hello python'> 1112222 转义 import re content = """The apple's price is $5.00""" res = re.match('The apple\'s price is \$5.00', content, re.S) print(res) print(res.group()) <_sre.SRE_Match object; span=(0, 26), match="The apple's price is $5.00"> The apple's price is $5.00 总结:尽量使用泛匹配、使用括号得到匹配目标、尽量使用非贪婪模式、由换行符就用re.S re.search re.search 扫描整个字符串并返回第一个成功的匹配 # 使用re.match() import re content = """This is a string""" res = re.match('a', content, re.S) print(res) 运行结果: None # 使用re.search() import re content = """This is a string""" res = re.search('a\s\w*', content, re.S) print(res) print(res.group()) 运行结果: <_sre.SRE_Match object; span=(8, 16), match='a string'> a string 总结:为匹配方便,能用search就不用match re.findall 搜索字符串,以列表形式返回全部能匹配的子串 import re content = """This is a string""" res = re.findall('a\s\w*', content, re.S) print(res) 运行结果: ['a string'] re.sub 替换字符串中每一个匹配的子串后返回替换后的字符串 import re content = """This is 222211111 string""" res = re.sub('\d+', 'a',content) print(res) 运行结果: This is a string re.compile 将正则字符串编译成正则表达式对象 将一个正则表达式串编译成正则对象,以便于复用该匹配模式 import re content = """This is 222211111 string""" pattern = re.compile('\d+') res = re.search(pattern, content) print(res) print(res.group()) 运行结果: <_sre.SRE_Match object; span=(8, 17), match='222211111'> 222211111 欢迎访问 个人博客地址:www.limiao.tech