
技术新手
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。 知识在于点滴积累
MySQL 添加列,修改列,删除列 示例:ALTER TABLE tb_financial MODIFY CREATE_TIME DATETIME(3) DEFAULT NULL COMMENT '录入时间'; ALTER TABLE:添加,修改,删除表的列,约束等表的定义。 查看列:desc 表名; 修改表名:alter table t_book rename to bbb; 添加列:alter table 表名 add column 列名 varchar(30); 删除列:alter table 表名 drop column 列名; 修改列名MySQL: alter table bbb change nnnnn hh int; 修改列名SQLServer:exec sp_rename't_student.name','nn','column'; 修改列名Oracle:lter table bbb rename column nnnnn to hh int; 修改列属性:alter table t_book modify name varchar(22); 修改comment ALTER TABLE tb_money_withdraw MODIFY COLUMN PROGRESS VARCHAR(10) COMMENT '提现进度:0 提现申请 1审核通过 2 审核不通过 3提现成功 4 提现失败'; --注意:字段名和字段类型照写就行 sp_rename:SQLServer 内置的存储过程,用与修改表的定义。 MySQL 查看约束,添加约束,删除约束 添加列,修改列,删除列 查看表的字段信息:desc 表名; 查看表的所有信息:show create table 表名; 添加主键约束:alter table 表名 add constraint 主键 (形如:PK_表名) primary key 表名(主键字段); 添加外键约束:alter table 从表 add constraint 外键(形如:FK_从表_主表) foreign key 从表(外键字段) references 主表(主键字段); 删除主键约束:alter table 表名 drop primary key; 删除外键约束:alter table 表名 drop foreign key 外键(区分大小写); 修改表名:alter table t_book rename to bbb; 添加列:alter table 表名 add column 列名 varchar(30); 删除列:alter table 表名 drop column 列名; 修改列名MySQL: alter table bbb change nnnnn hh int; 修改列名SQLServer:exec sp_rename't_student.name','nn','column'; 修改列名Oracle:alter table bbb rename column nnnnn to hh int; 修改列属性:alter table t_book modify name varchar(22); sp_rename:SQLServer 内置的存储过程,用与修改表的定义。 知识在于点滴积累
前言 这一章节主要讲解Xpath的基础语法,学习如何通过Xpath获取网页中我们想要的内容;为我们的后面学习Java网络爬虫基础准备工作。 备注:此章节为基础核心章节,未来会在网络爬虫的数据解析环节经常使用,学会Xpath解析语法,可为未来爬虫解析省去很多麻烦。 Xpath简介 XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力。起初 XPath 的提出的初衷是将其作为一个通用的、介于XPointer与XSLT间的语法模型。但是 XPath 很快的被开发者采用来当作小型查询语言。 简单来说我们通过Xpath可以获取XML中的指定元素和指定节点的值。在网络爬虫中我们通过会把爬虫获取的HTML数据转换成XML结构,然后通过XPath解析,获取我们想要的结果。 接下来为大家分享以下xpath的表达式以及用法。 一.选取节点 Xpath使用路径表达式在XML文档中选取节点。节点是通过沿着路径来选取的,通过路径可以找到我们想要的节点或者节点范围。 表达式|描述|用法|说明 nodename|选取此节点的所有子节点|xpath(‘span’)|选取span元素的所有子节点 /|从根节点选取|xpath(‘/div’)|从根节点上选取div节点 // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 xpath(‘//div’) 从当前节点选取含有div节点的标签 . 选取当前节点 xpath(‘./div’) 选取当前节点下的div标签 .. 选取当前节点的父节点 xpath(‘../’) 回到上一级节点 @ 选取属性 xpath(“//div[@id=’1001’]”) 获取div标签中,含有ID属性且值为1001的标签 二.谓语(Predicates) 谓语用来查找某个特定的节点或者包含某个指定的值的节点。 谓语被嵌在方括号中。 表达式描述 | 用法说明 /bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。 /bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。 /bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。 //title[@lang]选取所有拥有名为 lang 的属性的 title 元素。 //title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 /bookstore/book[position()35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 /bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 三. 通配符 XPath 通配符可用来选取未知的 XML 元素,通配指定节点。 表达式 描述 用法 说明 * 匹配任何元素节点 xpath(/div/*) 选取div下的所有子节点 @* 匹配任何属性节点 xpath(/div[@*]) 选取所有带属性的div节点 node() 匹配任何类型的节点 xpath(//div[@class=’tb_cls’]).node() 选择标签为div且类属性为tb_cls的所有标签 四.多路径选择 通过在路径表达式中使用“|”运算符,您可以选取若干个路径。 用法 说明 xpath(//book/title |//book/price) 选取 book 元素的所有 title 和 price 元素。 xpath(//title| //price) 选取文档中的所有 title 和 price 元素 五.XPath 轴 轴可定义相对于当前节点的节点集。 表达式 描述 用法 说明 ancestor 选取当前节点的所有先辈(父、祖父等) xpath(//div[@id=’123’]/ancestor::*) 选择标签为div且ID号为123的所有先辈标签 ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 xpath(//div[@id=’123’]/ancestor-or-self::*) 选择标签为div且ID号为123的所有先辈标签且包含自己 attribute 选取当前节点的所有属性 xpath(//div[@id=’123’]/attribute::class) 选择标签为div且ID号为123的类属性名称 child 选取当前节点的所有子元素 xpath(//div[@id=’123’]/child::book) 选择标签为div且ID号为123的所有子元素的为book 节点 descendant 选取当前节点的所有后代元素(子、孙等) xpath(./descendant::*) 返回当前节点的所有后代节点(子节点、孙节点) following 选取文档中当前节点结束标签后的所有节点 xpath(./following::*) 选取文档中当前节点结束标签后的所有节点 parent 选取当前节点的父节点 xpath(./parent::*) 选取当前节点的父节点 preceding 选取文档中当前节点的开始标签之前的所有节点 xpath(//div[@id=’123’]/preceding::*) 选择标签为div且ID号为123的开始标签之前的所有节点 preceding-sibling 选取当前节点之前的所有同级节点 xpath(//div[@id=’123’]/preceding-sibling::*) 选择标签为div且ID号为123的之前的所有同级节点 self 选取当前节点 xpath(./self::*) 选取当前节点 六.XPath 运算符 表达式 描述 用法 说明 + 加法 6 + 4 10 - 减法 6 - 4 2 * 乘法 6 * 4 24 div 除法 8 div 4 2 = 等于 price=9.80 如果 price 是 9.80,则返回 true。 如果 price 是 9.90,则返回 false。 != 不等于 price!=9.80 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 false。 < 小于 price<= 小于或等于 price<=9.80 如果 price 是 9.00,则返回 true。 如果 price 是 9.90,则返回 false。 > 大于 price>9.80 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 false。 >= 大于或等于 price>=9.80 如果 price 是 9.90,则返回 true。 如果 price 是 9.70,则返回 false。 or 或 price=9.80 or price=9.70 如果 price 是 9.80,则返回 true。 如果 price 是 9.50,则返回 false。 and 与 price>9.00 and price 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。 mod 计算除法的余数 5 mod 2 1 七.常用的功能函数 使用功能函数能够更好的进行模糊搜索 表达式 描述 用法 说明 starts-with 选取id值以ma开头的div节点 xpath(‘//div[starts-with(@id,”ma”)]‘) 选取id值以ma开头的div节点 contains 选取id值包含ma的div节点 xpath(‘//div[contains(@id,”ma”)]‘) 选取id值包含ma的div节点 and 选取id值包含ma和in的div节点 xpath(‘//div[contains(@id,”ma”) and contains(@id,”in”)]‘) 选取id值包含ma和in的div节点 text() 选取节点文本包含ma的div节点 xpath(‘//div[contains(text(),”ma”)]‘) 选取节点文本包含ma的div节点 转载于网络爬虫基础-Xpath语法(一) 知识在于点滴积累
select trim(字段) from 表 删除左右空格 select ltrim(字段) from 表 删除左空格 select rtrim(字段) from 表 删除右空格 知识在于点滴积累
Mysql清空表(truncate)与删除表中数据(delete)的区别 为某基于wordpress搭建的博客长久未除草,某天升级的时候发现已经被插入了几万条垃圾留言,如果一条条删除那可真是累人的活。遂考虑直接进入mysql直接清空表或者删除表中数据。 本文记录一下这2种操作模式的区别,目标对象是表wp_comments,里面的所有留言均是垃圾留言,均可删除。然后便有了以下2种方式(进入mysql操作界面后): truncate table wp_comments; delete * from wp_comments; 其中truncate操作中的table可以省略,delete操作中的*可以省略。这两者都是将wp_comments表中数据清空,不过也是有区别的,如下: truncate是整体删除(速度较快), delete是逐条删除(速度较慢)。 truncate不写服务器log,delete写服务器log,也就是truncate效率比delete高的原因。 truncate不激活trigger(触发器),但是会重置Identity(标识列、自增字段),相当于自增列会被置为初始值,又重新从1开始记录,而不是接着原来的ID数。而delete删除以后,Identity依旧是接着被删除的最近的那一条记录ID加1后进行记录。 如果只需删除表中的部分记录,只能使用DELETE语句配合where条件。 DELETE FROM wp_comments WHERE…… 知识在于点滴积累
mysql是我们项目中非常常用的数据型数据库。但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况。下面就来介绍一下如何彻底解决数据库中文乱码情况。 1、中文乱码 1.1、中文乱码 create table user(name varchar(11)); # 创建user表 insert into table user("carl"); # 添加数据 select * from user; insert into user value("哈哈"); 无法插入中文字符: 1.2、查看表字符编码 mysql> show create table user \G; *************************** 1. row *************************** Table: user Create Table: CREATE TABLE `user` ( `name` varchar(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec) 我们可以看到表的默认字符集是latin1. 所以我们在创建表的时候就需要指定表的字符集: create table user(name varchar(11)) default charset=utf8; 这样在Linux里面可以访问并且可以插入与访问这个表了。 1.3、数据库与操作系统编码 虽然在服务器端可以显示中文正常,但是在客户端可能会显示乱码。因为我们的服务器是UTF8。 而且数据库的编码也存在问题。 这里我们可以看character_sert_database与character_set_server的字符集都是latin1.那么在mysql数据库中,server,database,table的字符集都默认是latin1.下面我们就来看看如何解决mysql乱码情况。 2、mysql设置变量的范围 2.1、session范围 查看数据库编码: show variables like '%char%'; 修改字符编码: set character_set_server=utf8; set character_set_database=utf8; show variables like '%char%'; 我们可以看到字符集已经修改成都是utf8了。但是这里有一个问题,那就是我们重新打开一个命令窗口然后查看数据编码就会出现下面的画面: 2.2、global范围 mysql设置变量的范围默认是session范围。如果设置多个会话的字符集那么需要设置global范围:Set [global|session] variables … set global character_set_database=utf8; set global character_set_server=utf8; show variables like '%char%'; 当我们跨会话查看mysql字符集都会看到都是utf8。如果你以为万事大吉了的话,那么你就大错特错了。 2.3、设置数据全局范围 当我们数据库重启的时候,你们发现设置global范围的值又变成latin1了。 service mysqld restart mysql -uroot -pyourpassword show variables like '%char%'; 不要怕,下面就教你终极大招: 修改mysql配置文件/etc/my.cnf。 [mysqld] character-set-server=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8 请注意这几个参数配置的位置,不然可能会启动不起来mysql服务: OK。这下如果你重启mysql服务也会发现它的字符集是utf8. 而且我们创建表的时候不需要指定字符编码,它默认就是utf8; drop database test; create database test; use test; create table user(name varchar(11)); show create table user \G; 3、总结 我看网上很多答案都是直接在session级别设置mysql的字符编码,这是治标不治本的方法。我们还是要从源头上解决这个问题。那就是修改mysql默认的配置文件,把它的字符集修改成能够使用中文字符的UTF8就OK了。 转载于彻底解决mysql中文乱码 知识在于点滴积累
yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法。 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: def addlist(alist): for i in alist: yield i + 1 取出alist的每一项,然后把i + 1塞进去。然后通过调用取出每一项: alist = [1, 2, 3, 4] for x in addlist(alist): print x, 这的确是yield应用的一个例子 1.包含yield的函数 假如你看到某个函数包含了yield,这意味着这个函数已经是一个Generator,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数: def h(): print 'To be brave' yield 5 h() 可以看到,调用h()之后,print 语句并没有执行!这就是yield,那么,如何让print 语句执行呢?这就是后面要讨论的问题,通过后面的讨论和学习,就会明白yield的工作原理了。 2.yield是一个表达式 Python2.5以前,yield是一个语句,但现在2.5中,yield是一个表达式(Expression),比如: m = yield 5 表达式(yield 5)的返回值将赋值给m,所以,认为 m = 5 是错误的。那么如何获取(yield 5)的返回值呢?需要用到后面要介绍的send(msg)方法。 3.透过next()语句看原理 现在,我们来揭晓yield的工作原理。我们知道,我们上面的h()被调用后并没有执行,因为它有yield表达式,因此,我们通过next()语句让它执行。next()语句将恢复Generator执行,并直到下一个yield表达式处。比如: def h(): print 'Wen Chuan' yield 5 print 'Fighting!' c = h() c.next() c.next()调用后,h()开始执行,直到遇到yield 5,因此输出结果: Wen Chuan 当我们再次调用c.next()时,会继续执行,直到找到下一个yield表达式。由于后面没有yield了,因此会拋出异常: Wen Chuan Fighting! Traceback (most recent call last): File "/home/evergreen/Codes/yidld.py", line 11, in <module> c.next() StopIteration 4.send(msg) 与 next() 了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数send(msg)。其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做 c.next() 和 c.send(None) 作用是一样的。 来看这个例子: def h(): print 'Wen Chuan', m = yield 5 # Fighting! print m d = yield 12 print 'We are together!' c = h() c.next() #相当于c.send(None) c.send('Fighting!') #(yield 5)表达式被赋予了'Fighting!' 输出的结果为: Wen Chuan Fighting! 需要提醒的是,第一次调用时,请使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有yield语句来接收这个值。 5.send(msg) 与 next()的返回值 send(msg) 和 next()是有返回值的,它们的返回值很特殊,返回的是下一个yield表达式的参数。比如yield 5,则返回 5 。到这里,是不是明白了一些什么东西?本文第一个例子中,通过for i in alist 遍历 Generator,其实是每次都调用了alist.Next(),而每次alist.Next()的返回值正是yield的参数,即我们开始认为被压进去的东东。我们再延续上面的例子: def h(): print 'Wen Chuan', m = yield 5 # Fighting! print m d = yield 12 print 'We are together!' c = h() m = c.next() #m 获取了yield 5 的参数值 5 d = c.send('Fighting!') #d 获取了yield 12 的参数值12 print 'We will never forget the date', m, '.', d 输出结果: Wen Chuan Fighting! We will never forget the date 5 . 12 6.throw() 与 close()中断 Generator 中断Generator是一个非常灵活的技巧,可以通过throw抛出一个GeneratorExit异常来终止Generator。Close()方法作用是一样的,其实内部它是调用了throw(GeneratorExit)的。我们看: def close(self): try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("generator ignored GeneratorExit") # Other exceptions are not caught 因此,当我们调用了close()方法后,再调用next()或是send(msg)的话会抛出一个异常: Traceback (most recent call last): File "/home/evergreen/Codes/yidld.py", line 14, in <module> d = c.send('Fighting!') #d 获取了yield 12 的参数值12 StopIteration 转载于彻底理解Python中的yield 知识在于点滴积累
接下来的图表展现了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示)。 下面对每个组件都做了简单介绍,并给出了详细内容的链接。数据流如下所描述。 来源于https://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/architecture.html 知识在于点滴积累
PyCharm默认会使用虚拟的Python解释器,即使没有安装也能够运行Python代码,但有强迫症的程序员一定不能忍受Project中存在这么多的文件目录 设置Python版本 File->Settings->Project->Project Interpreter,设置本地安装的Python解释器版本 创建Python工程 创建工程时,选择Existing interpreter已经存在的解释器。 现在就可以愉快的编写Python代码了 知识在于点滴积累
xms -xmx相关参数设置 打开pycharm的安装目录 D:\PyCharm\PyCharm 2018.2.3\bin下文件pycharm.exe.vmoptions 修改默认(版本2016.2)的 -server -Xms128m -Xmx512m 为 -server -Xms256m -Xmx1024m 启动会变快的 知识在于点滴积累
对象的5种基本类型 属性 知识在于点滴积累
打开Anaconda安装目录下的etc文件如:C:\Anaconda3\etc\jupyter我的安装目录在C:\Anaconda3 再打开jupyter_notebook_config.json文件作如下修改即可: 知识在于点滴积累
1.下载pip 地址:https://pypi.python.org/pypi/pip#downloads 注意选择tar.gz压缩包,目前最新版本为9.0.1,这里选择的版本是:pip-9.0.1.tar.gz (md5, pgp) 点击:下载 2.解压安装 解压下载的压缩包至工作目录下(如D:),打开Windows cmd,运行如下命令进入解压后的pip目录 cd /d D:\pip-9.0.1 使用如下命令进行安装 python setup.py install 3.添加环境变量 添加windows系统环境变量,与安装python时添加的方法一样 如我的python目录是:F:\Python27; 则添加如下2个目录到系统环境变量里:F:\Python27;F:\Python27\Scripts; 4.pip常用命令 安装成功后,重新进入CMD后运行pip,可以看到帮助文档: pip常用命令如下: 1 2 3 4 5 6 7 8 9 10 11 #安装包 pip install xxx #升级包,可以使用-U 或者 --upgrade pip install -U xxx #卸载包 pip uninstall xxx #列出已安装的包 pip list 5.常见问题 最近遇到过使用pip命令时报错AttributeError: 'module' object has no attribute 'wraps',发现是pip安装版本错误导致,使用上述方法重新安装最新版本pip即可解决。 6.执行python setup.py install报错 python错误:ImportError: No module named setuptools 这句错误提示的表面意思是:没有setuptools的模块,说明python缺少这个模块,那我们只要安装这个模块即可解决此问题,下面我们来安装一下: 1.下载setuptools包:https://pypi.python.org/pypi/setuptools 2.解压setuptools包 3.编译setuptools :python setup.py build 4.开始执行setuptools安装:python setup.py install 这时再执行:python setup.py install 成功! 知识在于点滴积累
标题: #h1级标题 ##h2级标题 ###h3级标题 ####h4级标题 #####h5级标题 ######h6级标题 分割线:三个以上的短线 即可作出分割线 ---- 超链接:[连接名称](网址 , 标题) [我是链接名](http://www.izhangbo.cn, "我是标题") [<i class="icon-refresh"></i> 点我刷新](/sonfilename/) 另一种超链接写法:[链接名][链接代号] [here][3] 然后在别的地方定义 3 这个详细链接信息, [3]: http://www.izhangbo.cn "聚牛团队" 直接展示链接的写法:<http://www.izhangbo.cn> 键盘键 <kbd>Ctrl+[</kbd> and <kbd>Ctrl+]</kbd> code格式:反引号 Use the `printf()` function. ``There is a literal backtick (`) here.针对在代码区段内插入反引号的情况`` 强调: *斜体强调* **粗体强调** 图片  使用 icon 图标文字 <i class="icon-cog"></i> 段落:以一个空行开始,以一个空行结束,中间的就是一个段落。 表格: Item | Value -------- | --- Computer | $1600 Phone | $12 Pipe | $1 无序列表:使用 - 加一个空格() - 无需列表1 - 无序列表2 - 无序列表3 有序列表:使用 数字 加一个英文句点 1. 有序列表 2. 有序列表 3. 有序列表 4. 有序列表 5. 有序列表 换行缩进形成代码区块 这里先换行,然后缩进4个空格,之后的内容便可以原样显示了,适合用于显示代码内容。直到文本结束或最后一个存在缩进的行为止。 块引用 >给引用的文本开始位置都加一个 '>', >便可组成一个块引用。在块引用中,可以结合 >其他markdown元素一块使用,比如列表。 >**强调** 也可以只在第一行加大于号,其他位置不加。 >- 块引用里使用列表,需要和上面的内容隔开一个空行 >- 记得加空格哦。 知识在于点滴积累
来源链接https://blog.csdn.net/testcs_dn/article/details/45719357 读文件 读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。 知识在于点滴积累
函数:open() 1:作用:打开一个文件 2:语法: open(file[, mode[, buffering[, encoding[, errors[, newline[, closefd=True]]]]]]) 3:参数说明: file: 要打开的文件名,需加路径(除非是在当前目录)。唯一强制参数 mode: 文件打开的模式 buffering: 设置buffer(取值为0,1,>1) encoding: 返回数据的编码(一般为UTF8或GBK) errors: 报错级别(一般为strict,ignore) newline: 用于区分换行符(只对文本模式有效,可以取的值有None,'\n','\r','','\r\n') closefd: 传入的file参数类型(缺省为True) 常用的是file,mode和encoding这三个参数 4:参数详细说明: 4.1.mode:文件打开的模式。有如下几种模式 'r': 以只读模式打开(缺省模式)(必须保证文件存在) 'w':以只写模式打开。若文件存在,则会自动清空文件,然后重新创建;若文件不存在,则新建文件。使用这个模式必须要保证文件所在目录存在,文件可以不存在。该模式下不能使用read()方法 'a':以追加模式打开。若文件存在,则会追加到文件的末尾;若文件不存在,则新建文件。该模式不能使用read()方法。 下面四个模式要和上面的模式组合使用 'b':以二进制模式打开 't': 以文本模式打开(缺省模式) '+':以读写模式打开 'U':以通用换行符模式打开 常见的mode组合 'r'或'rt': 默认模式,文本读模式 'w'或'wt': 以文本写模式打开(打开前文件会被清空) 'rb': 以二进制读模式打开 'ab': 以二进制追加模式打开 'wb': 以二进制写模式打开(打开前文件会被清空) 'r+': 以文本读写模式打开,可以写到文件任何位置;默认写的指针开始指在文件开头, 因此会覆写文件 'w+': 以文本读写模式打开(打开前文件会被清空)。可以使用read() 'a+': 以文本读写模式打开(写只能写在文件末尾)。可以使用read() 'rb+': 以二进制读写模式打开 'wb+': 以二进制读写模式打开(打开前文件会被清空) 'ab+': 以二进制读写模式打开 4.2.buffering:设置buffer 0: 代表buffer关闭(只适用于二进制模式) 1: 代表line buffer(只适用于文本模式) 1: 表示初始化的buffer大小 4.3.errors:报错级别 strict: 字符编码出现问题时会报错 ignore: 字符编码出现问题时程序会忽略而过,继续执行下面的程序 4.4.closefd: True: 传入的file参数为文件的文件名 False: 传入的file参数只能是文件描述符 Ps: 文件描述符,就是一个非负整数,在Unix内核的系统中,打开一个文件,便会返回一个文件描述符。 注意:使用open打开文件后一定要记得关闭文件对象 5:实例: 存在文件 test.txt ,文件内容如下 hello good boy how are you? I am fine. 5.1:以默认的方式打开 f = open('test.txt') print f.read() hello good boy how are you? I am fine. f.close() 5.2:以只写的方式打开 f = open('test.txt','w') f.read() Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> f.read() IOError: File not open for reading f.write('good bye!\n') f.close() f = open('test.txt') print f.read() good bye! f.close() 5.3:以追加的方式打开 f = open('test.txt','a') f.write('see you tomorrow!\n') f.close() f = open('test.txt','r') print f.read() good bye! see you tomorrow! f.close() 5.4:判断文件是否被关闭 try: all_the_text = f.read() finally: f.close() f.read() Traceback (most recent call last): File "<pyshell#60>", line 1, in <module> f.read() ValueError: I/O operation on closed file 注:不能把open语句放在try块里,因为当打开文件出现异常时,文件对象file_object无法执行close()方法。 6:其他: file()与open() 相同点: 两者都能够打开文件,对文件进行操作,用法和参数也相似 不同点: file 打开文件,相当于这是在构造文件类 open 打开文件,是用python的内建函数来操作 来源https://blog.csdn.net/doiido/article/details/43675465 知识在于点滴积累
sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代码来说明它作用的解释一直没看明白。因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。 下面我们通过一个极简单的test.py程序的运行结果来说明它的用法。 #test.py import sys a=sys.argv[0] print(a) 将test.py保存在c盘的根目录下。 在程序中找到 ‘运行’->点击->输入"cmd"->回车键 进入控制台命令窗口(如下图),先输入cd c: (作用是将命令路径改到c盘根目录),然后输入test.py运行我们刚刚写的程序: 得到的结果是C:\test.py,这就是0指代码(即此.py程序)本身的意思。 然后我们将代码中0改为1 : a=sys.argv[1] 保存后,再从控制台窗口运行,这次我们加上一个参数,输入: test.py what 得到的结果就是我们输入的参数what,看到这里你是不是开始明白了呢。 那我们再把代码修改一下: a=sys.argv[2:] 保存后,再从控制台窗台运行程序,这次多加几个参数,以空格隔开: test.py a b c d e f 得到的结果为[‘b’, ’c’, ’d’, ’e’, ’f’] 应该大彻大悟了吧。Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该 将程序保存了,从外部来运行程序并给出参数 参考Python3 中 sys.argv[ ]的用法解释 知识在于点滴积累
# -*- coding: utf-8 -*- # 测试文件名为: # text.txt # 测试文件内容为: # abcdefg # 每次操作后将文件复原 # r # 以只读方式打开文件,文件不可写 # 要打开的文件不存在时会报错 # 文件的指针将会放在文件的开头 # 这是默认模式 # # file = open('test.txt', 'r') # # FileNotFoundError: [Errno 2] No such file or directory: 'test.txt' # file = open('text.txt', 'r') # print(file.read()) # # abcdefg # file.write('aaa') # # io.UnsupportedOperation: not writable # file.close() # rb # 以二进制格式打开一个文件用于只读,文件不可写 # 要打开的文件不存在时会报错 # 文件指针将会放在文件的开头 # 这是默认模式 # # file = open('test.txt', 'rb') # # FileNotFoundError: [Errno 2] No such file or directory: 'test.txt' # file = open('text.txt','rb') # print(file.read()) # b'abcdefg' # # file.write(b'aaa') # # io.UnsupportedOperation: not writable # file.close() # r+ # 打开一个文件用于读写,写入内容为str # 文件指针将会放在文件的开头 # 重新写入的内容从头开始替换 # file = open('text.txt', 'r+') # file.write('aaa') # file.close() # file = open('text.txt','r') # print(file.read()) # # 'abcdefg' # file.close() # rb+ # 以二进制格式打开一个文件用于读写,写入内容为bytes # 文件指针将会放在文件的开头 # 重新写入的内容从头开始替换 # file = open('text.txt','rb+') # # file.write('aaa') # # TypeError: a bytes-like object is required, not 'str' # file.write(b'aaa') # file.close() # file = open('text.txt','rb') # print(file.read()) # # b'aaadefg' # file.close() # w # 打开一个文件只用于写入,写入内容为str # 文件不可读 # 如果该文件已存在则将其覆盖,原文件内容将清空 # 如果该文件不存在,创建新文件 # file = open('test.txt', 'w') # 创建一个空文件 # file = open('text.txt', 'w') # file.write('gfedcba') # file = open('text.txt', 'r') # print(file.read()) # file.close() # wb # 以二进制格式打开一个文件只用于写入,写入内容为bytes # 文件不可读 # 如果该文件已存在则将其覆盖,原文件内容将清空 # 如果该文件不存在,创建新文件 # file = open('test.txt', 'wb') # 创建一个空文件 # file = open('text.txt', 'wb') # file.write(b'gfedcba') # file = open('text.txt', 'r') # print(file.read()) # file.close() # w+ # 打开一个文件用于读写,写入内容为str # 如果该文件已存在则将其覆盖,原文件内容将清空 # 如果该文件不存在,创建新文件 # file = open('test.txt', 'w+') # 创建一个空文件 # file = open('text.txt', 'w+') # file.write('gfedcba') # file = open('text.txt', 'r') # print(file.read()) # file.close() # wb+ # 以二进制格式打开一个文件用于读写,写入内容为bytes # 如果该文件已存在则将其覆盖 # 如果该文件不存在,创建新文件 # file = open('text.txt', 'wb+') # file.write(b'gfedcba') # file = open('text.txt', 'r') # print(file.read()) # file.close() # a # 打开一个文件用于追加(只写),写入内容为str # 如果该文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后 # 如果该文件不存在,创建新文件进行写入 # file = open('test.txt', 'a') # 创建一个空文件 # file = open('text.txt', 'a') # file.write('aaa') # file.close() # file = open('text.txt') # print(file.read()) # file.close() # ab # 以二进制格式打开一个文件用于追加(只写),写入内容为bytes # 如果该文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后 # 如果该文件不存在,创建新文件进行写入 # file = open('test.txt', 'ab') # 创建一个空文件 # file = open('text.txt', 'ab') # file.write(b'aaa') # file.close() # file = open('text.txt') # print(file.read()) # file.close() # a+ # 打开一个文件用于追加(读写),写入内容为str # 如果该文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后 # 如果该文件不存在,创建新文件用于读写 # file = open('test.txt', 'a+') # 创建一个空文件 # file = open('text.txt', 'a+') # file.write('aaa') # file.close() # file = open('text.txt') # print(file.read()) # file.close() # ab+ # 以二进制格式打开一个文件用于追加(读写),写入内容为bytes # 如果该文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后 # 如果该文件不存在,创建新文件用于读写 # file = open('text.txt', 'ab+') # file.write(b'aaa') # file.close() # file = open('text.txt') # print(file.read()) # file.close() 参考python open 关于读、写、追加的总结 知识在于点滴积累
sublime text3 每当运行报错error时,都会出现一长串的path路径,如何不显示呢? 可以通过注释掉Packages/Default/exec.py的四个特定行来更改。 首先,您需要从Package Control中安装PackageResourceViewer插件。 接下来,打开命令调色板Ctrl+Shift+P,键入prv,以显示PackageResourceViewer选项。 选择PackageResourceViewer: Open Resource 然后选择Default, 然后exec.py。 现在可以点击Esc清除命令调色板。 在打开的文件中,向下滚动到大约270行,也可以Ctrl+F,专门寻找这个代码块: if "PATH" in merged_env: self.debug_text += "[path: " + str(merged_env["PATH"]) + "]" else: self.debug_text += "[path: " + str(os.environ["PATH"]) + "]" 选择所有4行,然后通过点击Ctrl+/将其注释掉。最后,点击Ctrl+S保存文件。 如果你希望报error时PATH再次完全打印,只需随时打开Packages/Default/exec.py并取消注释之前注释的行,然后保存该文件。 建议exec.py在每次升级版本时,通过上述步骤编辑和重新运行,因为新版本中的该文件可能会有重大更改。 参考sublime text3 当运行报错error时,取消显示路径path的方法 知识在于点滴积累
错误如下 原因 anaconda插件连接jsonserver服务出现错误 可能是,当anaconda插件尝试连接jsonserver服务时,该服务暂未启动,所以之后在console中输入import socket; socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("localhost", 7381)),并没有什么问题。所以设置容忍启动错误参数,即可跳过这条错误。 解决 修改sublime text anaconda默认配置最末尾的参数为"swallow_startup_errors": true,即可。 知识在于点滴积累
安装Sublime Text 3 官网下载 选择对应的版本安装。完事后,要安装一个基础的、必备的包管理:Package Control,用来以后安装插件用的。 安装指导 https://sublime.wbond.net/installation import urllib.request,os,hashlib; h = '7183a2d3e96f11eeadd761d777e62404' + 'e330c659d4bb41d3bdf022e94cab3cd0'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by) 打开ST3,点击菜单 View -> Show Console,会在底部出现一个命令输入框,然后将上面的命令拷贝到输入框中,回车,等待,安装成功。 插件安装 经过上面安装了Package Control后,我们就可以通过快捷键 Ctrl+Shift+P 打开 Package Control 来安装插件了。在打开的输入框中输入 install ,会根据你的输入自动提示,选择 Install Package。 我们要安装支持非UTF8编码的一个插件,只需要在输入框中输入 convert,自动匹配后,选择 ConvertToUTF8 插件,回车,等待,安装完毕,这样,ST就支持显示如 GBK 等编码的内容了。 我以为必装的插件: ConvertToUTF8 支持 GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS 等编码的插件 Bracket Highlighter 用于匹配括号,引号和 html 标签。对于很长的代码很有用。安装好之后,不需要设置插件会自动生效 DocBlockr DocBlockr 可以自动生成 PHPDoc 风格的注释。它支持的语言有 Javascript, PHP, ActionScript, CoffeeScript, Java, Objective C, C, C++ Emmet(Zen Coding) 快速生成HTML代码段的插件,强大到无与伦比,不知道的请自行 google SideBar Enhancements 这个插件改进了侧边栏,增加了许多功能,如按F12调用浏览器查看页面 Themr 主题管理,切换主题的时候,不用自己修改配置文件了,用这个可以方便的切换主题 JsFormat 格式化 js 代码 Goto-CSS-Declaration 安装后按快捷键 win 键 +Alt+. 跳转到 css 文件该 class 的声明处,方便修改查看,注意对应的css文件要同时打开才行. Prettify Code 格式化 Html/CSS/JavaScript,一键让代码变整齐。 Sublime?Linter 自动提示补齐代码,支持 JavaScript、Python、PHP 等等常用语言。 查看如何升级、卸载 sublime text 插件 去 Sublime Text官网插件区查看更多 Sublime Text 插件 主要快捷键列表 掌握基本的代码编辑器的快捷键,能让你打码更有效率。刚开始可能有些生疏,只要花一两个星期坚持使用并熟悉这些常用的快捷键,今后就能解放鼠标了,省心省力又省时,何乐而不为呢。 以下是个人总结不完全的快捷键总汇,祝愿各位顺利解放自己的鼠标。 选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本。 Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名、函数名等。 Ctrl+L 选中整行,继续操作则继续选择下一行,效果和 Shift+↓ 效果一样。 Ctrl+Shift+L 先选中多行,再按下快捷键,会在每行行尾插入光标,即可同时编辑这些行。 Ctrl+Shift+M 选择括号内的内容(继续选择父括号)。举个栗子:快速选中删除函数中的代码,重写函数体代码或重写括号内里的内容。 Ctrl+M 光标移动至括号内结束或开始的位置。 Ctrl+Enter 在下一行插入新行。举个栗子:即使光标不在行尾,也能快速向下插入一行。 Ctrl+Shift+Enter 在上一行插入新行。举个栗子:即使光标不在行首,也能快速向上插入一行。 Ctrl+Shift+[ 选中代码,按下快捷键,折叠代码。 Ctrl+Shift+] 选中代码,按下快捷键,展开代码。 Ctrl+K+0 展开所有折叠代码。 Ctrl+← 向左单位性地移动光标,快速移动光标。 Ctrl+→ 向右单位性地移动光标,快速移动光标。 shift+↑ 向上选中多行。 shift+↓ 向下选中多行。 Shift+← 向左选中文本. Shift+→ 向右选中文本。 Ctrl+Shift+← 向左单位性地选中文本。 Ctrl+Shift+→ 向右单位性地选中文本。 Ctrl+Shift+↑ 将光标所在行和上一行代码互换(将光标所在行插入到上一行之前)。 Ctrl+Shift+↓ 将光标所在行和下一行代码互换(将光标所在行插入到下一行之后)。 Ctrl+Alt+↑ 向上添加多行光标,可同时编辑多行。 Ctrl+Alt+↓ 向下添加多行光标,可同时编辑多行。 编辑类 Ctrl+J 合并选中的多行代码为一行。举个栗子:将多行格式的 CSS 属性合并为一行。 Ctrl+Shift+D 复制光标所在整行,插入到下一行。 Tab 向右缩进。 Shift+Tab 向左缩进。 Ctrl+K+K 从光标处开始删除代码至行尾。 Ctrl+Shift+K 删除整行。 Ctrl+/ 注释单行。 Ctrl+Shift+/ 注释多行。 Ctrl+K+U 转换大写。 Ctrl+K+L 转换小写。 Ctrl+Z 撤销。 Ctrl+Y 恢复撤销。 Ctrl+U 自动读取图片宽高。 Ctrl+F2 设置书签 Ctrl+T 左右字母互换。 F6 单词检测拼写。 搜索类 Ctrl+F 打开底部搜索框,查找关键字。 Ctrl+shift+F 在文件夹内查找,与普通编辑器不同的地方是sublime允许添加多个文件夹进行查找,略高端,未研究。 Ctrl+P 打开搜索框。举个栗子:1、输入当前项目中的文件名,快速搜索文件,2、输入@和关键字,查找文件中函数名,3、输入:和数字,跳转到文件中该行代码,4、输入#和关键字,查找变量名。 Ctrl+G 打开搜索框,自动带:,输入数字跳转到该行代码。举个栗子:在页面代码比较长的文件中快速定位。 Ctrl+R 打开搜索框,自动带@,输入关键字,查找文件中的函数名。举个栗子:在函数较多的页面快速查找某个函数。 Ctrl+: 打开搜索框,自动带#,输入关键字,查找文件中的变量名、属性名等。 Ctrl+Shift+P 打开命令框。场景栗子:打开命名框,输入关键字,调用sublime text或插件的功能,例如使用package安装插件。 Esc 退出光标多行选择,退出搜索框,命令框等。 显示类 Ctrl+Tab 按文件浏览过的顺序,切换当前窗口的标签页。 Ctrl+PageDown 向左切换当前窗口的标签页。 Ctrl+PageUp 向右切换当前窗口的标签页。 Alt+Shift+1 窗口分屏,恢复默认1屏(非小键盘的数字) Alt+Shift+2 左右分屏-2列 Alt+Shift+3 左右分屏-3列 Alt+Shift+4 左右分屏-4列 Alt+Shift+5 等分4屏 Alt+Shift+8 垂直分屏-2屏 Alt+Shift+9 垂直分屏-3屏 Ctrl+K+B 开启/关闭侧边栏。 F11 全屏模式 Shift+F11 免打扰模式 参考 前端神器Sublime Text下载、使用教程、插件推荐说明、全套快捷键 知识在于点滴积累
上一篇写了如果安装Anaconda,由于Anaconda插件本身无法知道Python安装的路径,所以需要设置Python主程序的实际位置。选择Settings-Default选项,搜寻“python_interpreter” key, 并键入python主程序的磁盘位置。 选择Settings-Users选项,键入以下json数据。保存,重启ST3即可。 { "python_interpreter":"C:/ProgramData/Anaconda3/python.exe", "suppress_word_completions":true, "supperss_explicit_completions":true, "complete_parameters":true, } 参考sublime text3 下搭建python IDE环境 --Anaconda插件篇 知识在于点滴积累
一,下载Sublime Text 3 官网: Sublime Text - Download 二,生成Package Control界面 参考Sublime Text 3 安装Package Control,Package Control 使用Ctrl+`快捷键或者通过View->Show Console菜单打开命令行 输入如下代码: import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read()) 如果顺利的话,此时就可以在Preferences菜单下看到Package Settings和Package Control两个菜单了。 三,配置包 点击刚刚生成的Package Control ->输入install 或者Ctrl+shift+p 键入 install packages 进入安装界面: 我自己安装两个插件: 1.SideBarEnhancements => 侧边栏管理 2.Anaconda (最强的Python IDE插件) 同样方式安装Anaconda、SublimeREPL 3.键位绑定 当然每次通过Tools->SublimeREPL->Python这样的方式比较繁琐 将这样的操作和一个按键如F1绑定后,就会方便很多啦 e.g.打开Preferences->Key Bindings-User,复制一下代码: [{"keys":["f1"], "caption": "SublimeREPL: Python - RUN current file", "command": "run_existing_window_command", "args": {"id": "repl_python_run","file": "config/Python/Main.sublime-menu"} }] Ctrl+s 保存就好. 参考链接:sublime text 3 打造成python IDE 环境 知识在于点滴积累
1、导出数据 2、默认CSV格式 3、乱码 4、解决 文件->另存为,会发现编码为UTF-8,正是MySQL表的编码方式。我们选择编码方式为ANSI,保存类型为所有,覆盖源文件 知识在于点滴积累
分位数 使用QUARTILE函数算出 第一分位数:25%分位数 第二分位数:中位数 第三分位数:75%分位数 知识在于点滴积累
import pymysql db = pymysql.connect("localhost","root","","hank") #打开数据库 (如果连接失败会报错) cursor = db.cursor() #获取游标对象 sql_select = "select version()" #执行sql查询操作 cursor.execute(sql_select) 1 data = cursor.fetchone() #使用fetchone()获取单条数据 print("DB version is : %s" % data) DB version is : 5.6.39 cursor.execute("drop table if exists hankleo") #如果hankleo表存在,就删除 0 #创建表hankleo sql_create = "create table hankleo(id int,name varchar(10)) engine = innodb charset = utf8" cursor.execute(sql_create) 0 #插入操作 sql_insert = '''insert into hankleo(id,name) values(2,"李明")''' try: #执行sql cursor.execute(sql_insert) db.commit() except: #发生异常 db.rollback() #查询操作 sql_select = '''select * from hankleo''' try: #执行sql语句 cursor.execute(sql_select) #获取所有记录列表 result = cursor.fetchall() for row in result: id = row[0] name = row[1] print("id = %d,name = %s" % (id,name)) except: print("Error:unable to fecth data") id = 2,name = 李明 执行事务 事务机制可以确保数据的一致性 事务有四个属性:原子,一致,隔离,持久;通常称为ACID Python DB API2.0的事务提供了两个方法:commit 和 rollback 对于支持事务的数据库,在python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务,这个区别于mysql客户端,commit()方法提交所有的事务,rollback()方法回滚当前游标的所有操作。 每个方法都开启了一个新的事务 #例子 sql_insert = '''insert into hankleo (id,name) values (1,'china')''' try: cursor.execute(sql_insert) db.commit() except:db.rollback() print("end") #关闭连接 db.close() end 知识在于点滴积累
创建数据表 import pymysql db = pymysql.connect("localhost","root","","hank") cursor = db.cursor() cursor.execute("DROP TABLE IF EXISTS leo") sql = """CREATE TABLE leo ( FIRST_NAME CHAR(20) NOT NULL, LAST_NAME CHAR(20), AGE INT, SEX CHAR(1), INCOME FLOAT)""" cursor.execute(sql) db.close() 新增数据 import pymysql db = pymysql.connect("localhost","root","","hank") cursor = db.cursor() sql = """INSERT INTO leo( FIRST_NAME,LAST_NAME,AGE,SEX,INCOME) VALUES('JOE','B',20,'F',4000) """ try: #执行sql语句 cursor.execute(sql) #提交到数据库执行 db.commit() except: #如果发生数据库执行 db.rollback() db.close() mysql> select * from leo; +------------+-----------+------+------+--------+ | FIRST_NAME | LAST_NAME | AGE | SEX | INCOME | +------------+-----------+------+------+--------+ | Mike | A | 30 | M | 6000 | | JOE | B | 20 | F | 4000 | +------------+-----------+------+------+--------+ 2 rows in set (0.00 sec) 查询 import pymysql db = pymysql.connect("localhost","root","","hank") cursor = db.cursor() sql = "SELECT * FROM leo " try: #执行SQL语句 cursor.execute(sql) #获取所有记录列表 results = cursor.fetchall() for row in results: fname = row[0] lname = row[1] age = row[2] sex = row[3] income = row[4] #打印结果 print("fname=%s,lname=%s,age=%d,sex=%s,income=%d" % (fname,lname,age,sex,income)) except: print("Error:unable to fetch data") fname=Mike,lname=A,age=30,sex=M,income=6000 fname=JOE,lname=B,age=20,sex=F,income=4000 数据库更改 import pymysql db = pymysql.connect("localhost","root","","hank") cursor = db.cursor() sql = "UPDATE leo SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M') #找到sex性别为M的更新其年龄+1 try: cursor.execute(sql) db.commit() except: db.rollback() db.close() mysql> select * from leo; +------------+-----------+------+------+--------+ | FIRST_NAME | LAST_NAME | AGE | SEX | INCOME | +------------+-----------+------+------+--------+ | Mike | A | 31 | M | 6000 | | JOE | B | 20 | F | 4000 | +------------+-----------+------+------+--------+ 2 rows in set (0.00 sec) 删除操作 import pymysql db = pymysql.connect("localhost","root","","hank") cursor = db.cursor() sql = "delete from leo where name = hankleo" try: cursor.execute(sql) db.commit() except: db.rollback() db.close() 知识在于点滴积累
技巧1.利用Spreadsheet Camprare一秒钟识别差异数据 如下图所示,我们如何快速比对我们自己做的表格和上司修改后的表格的差异呢?这里首先来介绍一个非常棒的工具:Spreadsheet Compare 2013。是Excel自带的一款数据比对工具,这个工具可以高效地帮助我们比对多个Excel工作簿(结构相同)之间的差异。那么这个工具都有什么样的使用技巧呢?我这里就抛砖引玉地来介绍一下: 如何快速找到领导修改的内容? 技巧: 1.单击windows 系统“开始”按钮,输入“Spreadsheet Compare 2013”,找到此工具(在最上方),单击打开; 找到这个工具,只有Excel2013才有哦 2.现在Spreadsheet Compare2013这个数据差异比对工具以及打开,它的布局由工具栏、表格展示区、差异内容区等部分组成; Spreadsheet Compare 2013界面 3.单击“home"正下方的"Compare Files",打开对比文件选择对话框,分别选择自己发给领导的表格和领导发回来的表格,单击确定; 选择对比的两个表格,源表格和目标表格 这就是对比结果 4.现在我们就可以看到对比结果了,领导改了哪些东西一目了然。那么如果我们想将结果导出到Excel表格中去看怎么做呢? 细看图中说明 5.单击工具栏上的“Export Results",打开保存对话框,选择相应的文件存放位置和输入文件名,单击确定即可导出结果。 导出结果 选择合适的存放位置 这就上司改了的内容了 注意: 相互比较的两个Excel工作簿结构要一致,包括sheet的数目等。 技巧2.利用高级筛选快速比对两个表格之间的差异 高级筛选是Excel中特别重要的功能之一,其应用范围已经不仅仅局限于筛选数据了,之前的文章中我提到过高级筛选的诸多经典应用案例。今天我在此补充一个,利用高级筛选快速比对Excel工作表的数据 技巧: 1.选中修改后的表格中的任意单元格,单击“数据”选项卡,然后单击筛选按钮旁边的“高级"(这就是高级筛选),打开高级筛选对话框,这一步也可以直接用快捷键(Alt+A+Q); 2.我们看见修改后的表格已经被完全选中,单击下方的条件区域框的折叠按钮,选择修改前的表格,单击确定。 3.选中筛选后的表格,然后按下Alt+;组合键,只选中可见单元格,设置填充为红色; 4.单击“数据”选项卡,再单击”筛选“旁边的”清除“按钮。这时候没有填充色的行就是领导修改过的数据了。 上个动画演示: 高级筛选搞定数据比对是很轻松的事儿 作者:傲看今朝链接:https://www.jianshu.com/p/c6a166869347來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。知识在于点滴积累
虽然天天跟数据打交道,也频繁地使用Excel进行一些简单的数据处理和展示,但长期以来总是小心地避免用Python直接读写Excel文件。通常我都是把数据保存为以TAB分割的文本文件(TSV),再在Excel中进行导入或者直接复制粘贴。 前段时间做一个项目,却不得不使用Python直接生成Excel文件,后来随着需求的变化,还要对已有的Excel文件进行读取。在这个过程中,研究并尝试了一些工具,也走了一些弯路。记录下来,下次再有类似需求的时候就不用漫天遍野地搜索了。 超级无敌大PK 我主要尝试了四种工具,在此并不会给出他们的排名,因为在不同的应用场景下,做出的选择会不同。 XlsxWriter XlsxWriter是我最终选择的用于写操作的工具。顾名思义,它只能用来写文件。 这应该是个比较新的项目,在GitHub上看它最早的提交是在2013年1月份。其官方文档中宣称它支持: 优点 一、功能比较强 相对而言,这是除Excel自身之外功能最强的工具了。比如我就用到了它提供的:字体设置、前景色背景色、border设置、视图缩放(zoom)、单元格合并、autofilter、freeze panes、公式、data validation、单元格注释、行高和列宽设置等等。 最让我惊奇的是,用它生成的带有单元格注释的Excel文件,不论是Excel 2007还是Excel 2013都可正常打开(下面会提到,这个任务用Excel自身都无法完成)。 二、支持大文件写入 如果数据量非常大,可以启用constant memory模式,这是一种顺序写入模式,得到一行数据就立刻写入一行,而不会把所有的数据都保持在内存中。 缺点 一、不支持读取和修改 作者并没有打算做一个XlsxReader来提供读取操作。不能读取,也就无从修改了。它只能用来创建新的文件。我是利用xlrd把需要的信息读入后,用XlsxWriter创建全新的文件。 另外,即使是创建到一半Excel文件,也是无法读取已经创建出来的内容的(信息应该在,但是并没有相应的接口)。因为它的主要方法是write而不是set。当你在某个单元格写入数据后,除非你自己保存了相关的内容,否则还是没有办法读出已经写入的信息。从这个角度看,你无法做到读出->修改->写回,只能是写入->写入->写入。 二、不支持XLS文件 XLS是Office 2013或更早版本所使用的格式,是一种二进制格式的文件。XLSX则是用一系列XML文件组成的(最后的X代表了XML)一个压缩包。如果非要创建低版本的XLS文件,就请移步xlwt吧。 三、暂时不支持透视表(Pivot Table) 透视表是非常麻烦的东西,除了自身复杂的结构外,还需要一套数据缓存。我向作者提出了这个需求,不过这是个很难完全实现的功能,我们慢慢期待吧。 xlrd&xlwt 我的程序在第一版的时候,使用xlwt创建XLS文件,然后通过Microsoft Excel API将其转换为XLSX文件,并写入高级的Data Validation(Excel 2007的Data Validation比Excel 2003要强大不少)和单元格注释。 我的程序最终的版本也依然用xlrd从已有的文件中读出所需的信息。 xlrd&xlwt主要是针对Office 2013或更早版本的XLS文件格式。 优点 一、支持XLS格式 XlsxWriter和OpenPyXL都不支持XLS格式,从这个角度看,xlrd&xlwt仍然有一定的不可替代性。 缺点 一、对XLSX支持比较差 目前xlrd已经可以读取XLSX文件了,有限地支持。至于xlwt我没有试验过,估计是够呛。 二、对修改的支持比较差 xlrd和xlwt是两个相对独立的模块,虽然xlutils提供方法帮助你把xlrd.Book对象复制到xlwt.Workbook对象,但跟XlsxWriter类似,后者只是提供write方法,使得你无法很容易地获取当前已经写入的数据并进行有针对性的修改。如果非要这样做,你要不断地保存,然后再用新的xlrd.Book对象读取你要的信息,还是比较麻烦的。 三、功能很弱 除了最基本的写入数据和公式,xlwt所提供的功能非常少(Excel 2013本身支持的功能也就很少)。对于读取也是一样的,很多信息在读入时就丢失掉了。 OpenPyXL OpenPyXL是比较综合的一个工具,能读能写能修改,功能还算可以但也有很大的缺陷。我在中间版本的时候是打算完全依赖它的,但后来发现一个严重的问题就放弃了。 优点 一、能读能写能修改 OpenPyXL的工作模式跟XlsxWriter和xlwt有很大的区别,它用的是getter/setter模式。你可以随时读取某个单元格的内容,并根据其内容进行相应的修改,OpenPyXL会帮你记住每个单元格的状态。 特别需要注意的一点:虽然它支持修改已有文件,但由于其所支持的功能有限,读入文件时会忽略掉它所不支持的内容,再写入时,这些内容就丢失了。因此使用时一定要慎重。比如下面的缺点中提到它无法读入公式,那如果你修改一个带有公式的文件,保存之后,所有的公式就都没有了。 二、功能还算可以 整体来讲,它所支持的功能介于XlsxWriter和xlwt之间。 缺点 一、不支持XLS 这件事情只能让xlrd和xlwt去做。 二、不支持读取公式 这其实是个不太简单的事情,虽然我没尝试过,但相信xlrd也做不好这件事。 Excel的单元格如果是一个公式,它内部会同时保存公式本身和运算结果的缓存。用OpenPyXL读取单元格内容,它不会告诉你这个单元格的公式是什么,甚至不会告诉你这个单元格存的是公式,它只会拿到这个缓存的运算结果。我本来想利用它判别单元格是不是用了公式,然后做出不同的处理。结果遇到了这个问题,最后只好采取了其他变通的方式去做。 Microsoft Excel API 大部分Windows环境的开发人员都会选择Microsoft Excel API。实际上不仅仅是Python,几乎各种语言都有相应的方法使用它,因为核心的逻辑完全是由Microsft Excel自身提供的。语言相关的部分只是负责跟Windows的COM组件进行通信。 在Python中首先需要安装Python for Windows extensions(pywin32),具体的文档可以查阅Win32 Modules和Python COM。 当然你还必须要安装某一个版本的Microsoft Office Excel,它内部的DLL负责实际的操作。 优点 一、最大的优点:强大无极限 因为直接与Excel进程通信,你可以做任何在Excel里可以做的事情。 二、文档丰富 MSDN上的文档绝对是世界上最优秀的文档。没有之一。 三、调试方便 你完全可以直接在Excel里面用宏先调试你想要的效果。甚至如果你不清楚怎么用程序实现某个操作,你可以通过宏录制的方法得到该操作的处理代码。 缺点 一、致命的缺点:慢到死 因为需要与Excel进程通信,其效率是非常低的。 如果让Excel窗口可见,随着程序的运行,你可以看到每一句程序所带来的变化,单元格的内容一个一个地改变。如果要写入的数据很多,那速度是无法忍受的。 二、平台限制 目前还没有发现可以在非Windows系统使用它的方法。 另外,基于它的程序能做什么事情,很大程度上依赖于当前系统所安装的Excel版本。不同的版本在功能上有很大的差异,API也会有差异。用起来会比较麻烦。 三、Excel自身bug导致的问题 我刚好发现了其中一个,这和Python没有任何关系,可以完全在Excel中手动复现。在Excel 2007中随便创建一个文件,给某个单元格添加注释,保存。换台电脑,用Excel 2013打开,就会报错,然后注释就消失了。 同样如果你的程序在一台装有Excel 2007的机器上创建一个带有注释的Excel文件,把这个文件拿到Excel 2013中打开也会报错,也看不到注释。反过来也一样。 关于初始化 Excel的com接口的具体细节我就不介绍了,需要的话直接查阅相关的MSDN文档即可。这里只提几个特殊的小问题。 要想得到一个可以操作的excel对象,一般可以有两种方式: 二者的区别在于,Dispatch方法会试图寻找并复用一个已有的Excel进程(比如你已经在运行着的Excel程序),而DispatchEx则一定会创建一个新的Excel进程。一般情况使用前者就可以了,还能节省一些资源的开销。但也会带来一些麻烦,有一些状态是在一个Excel进程内共享的,你在同进程的其他窗口内操作有可能会影响到Python程序所要进行的处理,导致各种错误。比如当你手动开启的Excel窗口中,某个单元格正处于编辑状态,那Python程序控制的大部分操作都有可能失败(即使它操作的是另一个文件),因为一个Excel进程中无法让两个单元格同时被编辑。 为了避免麻烦,我一般都使用DispatchEx方法。 关于窗口可见 可以让新启动的Excel进程窗口可见,就像你通过双击桌面上的图标启动一样,程序所控制的每一步操作,在这个窗口中都可以观察得到。你也可以同时进行手动的操作,但一旦这样做,很有可能使你的Python程序崩溃。 窗口不可见也会带来一些麻烦,前面说了,通过Python启动的Excel进程跟你直接从桌面打开的Excel进程没有什么区别,在使用Excel的过程中,我们经常会遇到各种弹出的错误、警告或者提示框,这些在用Python处理时也有可能遇到。尤其当你的程序还没完全调试好时。 我一般都会让程序控制的Excel进程在调试过程中可见,正式使用时不可见,通过类似这样的命令(假设你有一个叫做is_debug的变量记录当前是否在调试状态): 关于保存并覆盖已有文件 打开和保存文件的细节不在这里多说了,可以查看MSDN中相关的API介绍,非常详细。这里只说一下在另存为时,如果目标文件已经存在怎么办。Excel的API另存为方法似乎并没有提供参数决定是否直接覆盖同名的目标文件,在窗口操作中,这种情况会弹出一个确认框来让用户决定。我们的程序当然不想这么做,实际上如果你按照上面所说的让窗口不可见,你也就看不到弹出的窗口。 可以把DisplayAlert属性关闭,这样Excel就不会弹出确认窗,而是直接覆盖同名文件。 关于结束Excel进程 进程是一种资源,我们申请了资源,在用完之后就必须要释放掉。尤其如果你隐藏了Excel窗口,用户只有查看系统进程,否则无法关闭你所开启的进程。 但是一个Excel进程是可以同时开启多个文件的,这些文件可能是你程序的其他部分开启的,也可能是用户自己开启的。这样你就不能随意地结束Excel进程,否则会影响到其他人或程序的操作。 我一般会在我的处理完成后(关闭了我自己打开或者创建的Excel文件),判断一下当前Excel进程是否还开启着其他的文档,如果没有了才会结束该进程。 关于枚举常量 Excel API中有各种各样的枚举常量,我还没有找到在Python中直接引用这些常量的方法,目前的办法是找到所需的常数的值,自己定义这些常数。比如我用到了如下这些枚举常量: 要想知道某一个枚举常量的数值,可以查阅MSDN中Excel Enumerations相关的资料。 【2014年7月31日更新】感谢@依云提醒,在Python也能够直接引用相关的常量,即通过win32com.client.constants获取常量的值。不过这里还有一点比较tricky的地方,如果直接用Dispatch或者DispatchEx得到Excel对象,是无法从constants中取出常量值的,需要手动运行makepy,或者通过win32com.client.gencache.EnsureDispatch获得Excel对象: 来源于http://www.raincent.com/content-10-10533-1.html 知识在于点滴积累
来源 https://www.kesci.com/home/project/59e4331c4663f7655c499bc3 知识在于点滴积累
1.COUNTIF函数 COUNTIF函数用来计算单元格区域内符合条件的单元格个数。 COUNTIF函数只有两个参数 COUNTIF(单元格区域,计算的条件) 例如:计算上海市的数量 知识在于点滴积累
我们一直说的思考能力,它是可以经培养和训练,后天习得的特质。这也意味着我们可以借助前辈们的经验,站在巨人的肩膀上眺望。 行业内常把这种可总结和复用的经验叫做思考框架。 一个好的思考框架,首先应该满足易学。如果大部分人都掌握不了,那它只是少部分人的术。让初读的人觉得优雅,能够用一句话解释清楚,就不必用整篇文章赘述。 其次要满足易用。框架之所以称为框架,它只是骨,内里的血肉能因不同人不同理解发挥出不同的效果,才算用得起来。 今天便介绍给大家一款思考框架:矩阵思维。 这里的矩阵不涉及数学概念,我第一次接触到它,还是在大学毕业季,那时不断为面试准备,囫囵吞枣地学了不少应试招数。其中一种叫波士顿矩阵(BCG Matrix)。它是由波士顿咨询公司创始人首创。 波士顿矩阵 在传统以营销为主导的企业中,不论是日用品消费还是生产制造加工,企业一定有一系列的产品。波士顿矩阵认为,产品战略管理可以从两个角度衡量:市场增长率和相对市场占有率。 市场增长率是包括企业销售额、竞争对手强弱及利润高低的综合指标。而相对市场占有率则代表了企业在市场上的竞争实力。 这两个都是可量化的指标,将它们分别作X轴和Y轴,则能划分出四个象限。 企业的所有产品,都会落在四个象限中。产品可以是一款洗发水,可以是一项虚拟服务、也可以是一款APP。于是这些产品被分为高增长率-高占有率、高增长率-低占有率、低增长率-高占有率、低增长率-低占有率。 在产品管理中,我们把高增长率-高占有率的产品称为明显产品,从财务报告上看,它总是能产生利润,但是高增长往往意味着高投资。某种情况下,它不代表着自给自足。如果市场份额处于垄断或者领先地位时,那么企业不必再维持投入以保持高增长,此时产品能源源不断地维持现金流,它被称为现金牛。 现金牛产品的特点是高市场份额和低增长率。产品已经迈入成熟期,其特征是产生大量的现金收入,数额远大于维持市场份额所需再投入的资金,是企业支持其他产品的后盾。 低增长率-低占有率的产品叫做瘦狗产品,这类产品对企业都是鸡肋,财务特点是利润率低、处于保本或亏损状态。这类产品往往会实行撤退或者整顿的战略。 低市场份额而高增长率的产品是问题产品,这些产品吸纳的资金总是多于所产生的资金。虽然高增长率意味着市场未来潜力好,但是份额不高要打上一个问号。不投入资金,产品会衰亡,即使投入资金,若只能勉强维持住市场份额。那么它最终仍属于瘦狗产品。 象限是动态的,明星产品的目标是成为现金牛,问题产品需要摆脱泥沼增加市场份额,而所有的产品都可能衰退为瘦狗。 举个例子吧,老王是一家消费品公司的老板,他公司主营产品是生发水,因为祖传秘方,在市场上处于领导地位,但是秃头的男人总共就那么多,所销售额近年来没有起色,未来也不会有。按照波士顿矩阵的象限划归。老王生发水应该是现金牛。 现在老王准备拓展新业务,分别是养生枸杞、保温杯、和佛珠手串。老王用生发水赚来的利润支持另外三个产品的开发。养生枸杞因为和生发水搭配营销比较好(别问我为什么),所以市场份额节节攀升。老王一看有戏,便重金投入,把养生枸杞打造成了明星产品,未来有成为第二个现金牛的潜质。 保温杯虽然和养生枸杞捆绑销售,销售额增长比较快,但是市场份额并不高,很多顾客并不买账。设计款式连中年男性都嫌弃。所以它现在是尴尬的问题产品,是改设计,还是偃旗息鼓?至于佛珠手串,顾客更喜欢大金链子,所以既没有销量又没有份额。 上述例子只是让大家对产品的象限有一个大概了解。这篇文章并不是要讲市场营销或者产品管理,即使不了解波士顿矩阵也不要紧。因为本文的主题是思考框架,我们把精力聚焦在矩阵和象限中。 实际上,在我最初学习波士顿矩阵的时候,我对现金牛、瘦狗的概念依旧一知半解。但我牢牢记住了矩阵式思考,记住了象限划分。 何为象限?我们拿两个量化指标将分析对象划分出多个种类:高-高、高-低、低-低、低-高,对象落在了四个象限,它便是矩阵思维下的产物。 初中我们把它称之为象限和坐标轴,可视化中我们把它理解为散点图,而现在,我希望大家把它认为是一种思考方式。这种思考方式,一直伴随在我往后的工作中,只要留意,矩阵思维其实有很多应用。 电商SKU 电商网站商品繁多,这里不谈品类管理,而是从电商运营的角度分析产品。 大家都应该听过爆款产品,在淘宝店铺运营中,爆款产品意味着高曝光量和低利润率。这个词第一次听其他运营提及时,他们说很多爆款产品并不赚钱,往往是做高店铺的流量。当很多人被爆款产品吸引过来的同时,会去购买店铺其他正常利润的商品,这里还会配合优惠券做交叉销售,提高营收,这种方法是俗称的带量。 在你不知道矩阵思维的时候,可能只有带量这么一个概念。而学会了矩阵,你就能听出上述那段话的两个指标:曝光量和利润率。现在用它们划分出四个象限。 高曝光量-高利润率的商品,属于电商中的明星产品,是重要的现金流业务。这里的曝光量可以是淘宝站内的店铺流量,也可以是独立电商平台的各种营销渠道。除了明星产品外,还对应着高曝光量-低利润率的导流商品,低曝光量-高利润率的成长潜力商品,低曝光量-低利润率的鸡肋商品等。 每种类别的商品对应不同的运营策略,潜力商品可以在后期运营中增长曝光量,培养搜索权重;鸡肋商品则要优化转化率。这里通过象限梳理清楚了基于商品的运营逻辑,避免无头苍蝇般的抓瞎。 矩阵思维的一个优点是方便归类和聚焦,它是可以指导策略的。 商品的象限维度不止曝光量和利润率。我们可以尝试曝光量-转化率,去分析商品落地页的效果,比如高曝光量-低转化率的商品,是不是设计和文案有问题?也可以尝试利润率-回购率的象限维度,衡量商品长期的盈利多寡,某个商品虽然利润低了些,但是用户会反复购买,那么它也是半个明星产品。 矩阵的维度是很灵活的,大家要学会举一反三。 RFM RFM模型是客户管理中的经典方法,它用来划分客户价值。 RFM主要依赖三个核心指标:消费金额、消费频率和最近一次消费时间。我以前的文章曾经介绍过这部分,所以这里不多讲。 上图便是传统RFM模型的结构(这图是不是快腻了?),对应着用户消费分层的八个象限,也就是一个立方体形态。它属不属于矩阵思维呢? 它是的。矩阵思维只是一个思考框架,它本来就没被限制固定的形态。我能用两个指标划分四个象限,那么就不能用三个指标划分出八个象限? 曾经遇到过一位数据运营,就很灵活的运用RFM将它套入到企业端的运营分析中,那是一款PaaS,他将企业端客户在产品上的使用人数、使用深入程度以及最近一次使用时间进行分层。 写这点,是希望打破各位思维中的墙。只要象限合理、可用,数量是不是四并不重要。 绩效管理 在阿里巴巴的绩效管理中,会涉及两项考评:工作业绩和价值观。 这里把员工的管理划分成了四个象限:工作业绩强价值观好的是明星;工作业绩差而价值观好的是小白兔;工作业务好但是价值观差的是野狗;工作业绩差并且价值观也差的是狗。另外还有一块细分叫做牛,处于四个象限的交汇点,属于价值观和业务都不错的中坚骨干力量,第五个维度。 它也是一种矩阵思维的应用,不过应用在了人力资源管理上。管理模式没有对错,价值观也是一项难以量化的指标,即使是工作业绩,不同部门的标准也往往不一样,所以这种矩阵思维,更多是不同象限内人的管理策略,不涉及实际的分析。 销售管理 说到管理人,剔除掉价值观,我们单独拎出员工的绩效看。 销售每天都要跑客户,假如你是销售们的经理,你会怎么管理员工?这里不谈纯激励向的手段,如果想要对销售人本身做一点分析,我们也不妨引入矩阵。 拿销售们关心的两个KPI:成单率和平均成单额看。成单率是销售每个月成功单数在所有拜访中的占比,是工作效率和业务能力体现。成单额则是和客户价值挂钩。某个销售每天跑单量非常多,他或许是业绩Top,但他未必是最有效率的。高成单率-高平均成单额的销售才可以称为明星,它在销售管理中作为标杆和KOL树立。 这的矩阵思维,是为了挑选出正确的人。销售们不同于商品或者用户,往往采用军队化的方法统一管理,而矩阵是为了更科学有效。高成单率-低销售额和低成单率-高销售额的销售都有变为明星的潜力,可以为这两个象限内的销售培训和总结方法,可能是话术不好,可能是跟进不及时,可能是客户分配不对等。 早启动、晚总结、树标杆、老带新。如果某销售对拉高成单率有一手,他就能作为一名师傅在团队中推广。销售管理中,经理们常常更看重摸索出一套打法,然后把它推广的做法。所以销售的矩阵管理,就是把方法论聚焦。 上面讲的是区域经理或者销售经理如何抓团队,这套方法也能用在抓客户。RFM模型就是售后维护阶段的应用了,售前获客也是同样的道理。 时间管理 怎么用矩阵思维对付自己? 在很多时间管理方法中,事情的优先度会被建议使用两种维度: 紧急程度和重要程度。紧急程度是时间方面的约束,比如某项工作的Deadline逼近,那么它的紧急程度高,有些事情可以一个月后完成,那么紧急程度就低。重要程度则是事件造成的影响或者是破坏程度。 重要程度和紧急程度结合,很容易理解。下图列举了很多工作生活中常见的常见。 这种划分方式有助于提高自己的时间和项目管理能力,如果手头上自己有很多工作,不妨拿矩阵划分一下,以此作为执行依据。至于重要程度和紧急程度的等级,即可以二分,也可以用P1、P2、P3、P4更细的粒度。 古人云,轻重缓急,就是几百年前矩阵思维在时间管理中的智慧体现了。 搜索行为分析 这里说一个产品和用户行为结合的案例。 大家应该都用过搜索,搜索是伴随用户需求最直接的应用。不论是google或者百度这类搜索引擎,淘宝或者京东的商品搜索,乃至各类APP端的搜索框,都会接收用户输入的一段词作为查询,我们把它叫做query。 query常是一串文本,比如:什么是波士顿矩阵、矩阵的应用、美的空调、运动鞋、中山公园火锅等等。 各位在搜索的时候,有没有思考过,怎么判断查询结果的好坏呢?因为每个query都会查找到不同的结果,而这些结果的质量会影响到用户体验。用户搜索一个商品,然后服务器告诉用户没有查找到,或者虽然返回了结果,但是结果页的文案、图片或者标题差强人意,用户也失去了点击下去的欲望。这都让人抓狂。 矩阵思维当然能应用在搜索分析这类看似抽象的问题上。 我们设立两个指标维度:用户搜索后对结果的点击率,以及搜索词的查询量。前者反应了用户对搜索需求的被满意程度,后者反应了用户对该搜索的需求量。 上图是虚构的一家数据分析培训网站上的用户搜索数据。我们可以看到Python教程的搜索结果最高,说明用户需求量大,但是点击率不高,可能是用户对搜索结果,也就是课程质量不满意,而R语言教程则好上不少,可能是它的质量稍高一筹。另外一方面,Oracle和PowerBI的搜索量小,说明这部分用户基数有限,但是PowerBI点击率不错,可以考虑往后拓展这部分渠道。 实际的搜索场景更复杂些,平台型公司把搜索作为战略入口,它是一门系统化的工程。标签的索引、内容的预召回、个性化推荐都会影响结果,以后有机会再讲这块。而在中小型公司,矩阵依然是一种简明有效的方法。 KANO模型 KANO模型是对用户需求分类和优先排序的有用工具,以分析用户需求对用户满意的影响为基础,体现了产品性能和用户满意之间的非线性关系。 上面这段话摘自百科,简而言之,KANO模型认为,产品经理在梳理产品需求过程中,可以通过两个维度,“用户满意度”以及“功能完善程度”衡量,将功能划分四种不同类型的需求。 用户满意度指如果产品具备这个功能,那么用户的喜爱程度会上升。功能完善程度是如果产品不提供这个功能,那么用户的满意度会下降。这两个指标通过用户调研的量表计算出来,因为篇幅有限,计算过程就省略了。 如图,Better代表用户满意度,Worse代表功能完善度。高满意度-高具备度的功能是期望功能,这类功能是产品集中投入的点。高满意度-低具备度是魅力型功能,不提供该功能。用户的满意度不会降低,但是提供了,用户则会很喜欢。 低满意度-高具备度是产品的必备属性。如果没有这个功能,用户会认为这是件未完成品,这类功能需求属于用户的基本需求,这类功能做得再怎么好,用户的满意度也不会提升。低满意度-低具备度是无差异功能,对于用户是无关痛痒的,也就是大家俗称的伪需求。 KANO模型是对功能/服务的优先级进行探索,产品经理通过矩阵将抽象的需求概念落到实处,因为它本身就是可量化的,所以避免了很多口水仗。 当然,需求管理还能用一种简化方法,衡量的指标同时间管理中的重要程度-紧急程度一样。比如某个需求是老板要的很紧急,虽然它确实不重要;某个需求在未来的营销活动中很重要,但是短期内可以不实现。 如图,Better代表用户满意度,Worse代表功能完善度。高满意度-高具备度的功能是期望功能,这类功能是产品集中投入的点。高满意度-低具备度是魅力型功能,不提供该功能。用户的满意度不会降低,但是提供了,用户则会很喜欢。 产品功能分析 KANO模型用矩阵思维衡量了一项产品功能的优先级排序,当产品上线后,我们再次请出矩阵来判断功能的实际好坏。 平台级产品往往包含多个功能模块,越大越复杂,而不同模块产生的价值不同,为了避免撕逼,这里使用功能使用率和留存率两个维度分析。 功能日使用率是使用人数在日活跃人数中的占比,直接说明了功能使用者的多寡。留存率很好了解,这里的留存有两种考察:第一是用户使用了功能后,在某个周期再次使用该功能的概率。第二种是用户使用功能后,他再次打开APP的概率。前者考量了功能本身的粘性,后者则是看它对产品整体活跃的贡献。具体怎么用看需求。 下图是一个建议说明: 划分出功能矩阵后,运营能有针对性地围绕不同功能做文章,将各项指标提高上去。留存好、使用高的功能自然是尖刀。留存差、使用少的功能则避免花费太多力气。 PM也能量化不同功能的价值,什么功能需要迭代?什么功能需要延期?都清清楚楚烂熟于心。然后结合KANO模型看需求是不是和实际数据对应。 这里需要注意,功能本身是有限制的,比如账单功能,用户的使用频率是每个月一次,那么在指标上就不用期待太好看的数字。为了公平起见,产品矩阵的指标计算最好以新用户的使用情况为准,因为老用户容易受到各种运营的干扰。 总结 一口气介绍了多个案例,矩阵思维可以应用在商品运营、用户运营、人员管理、时间管理、用户行为分析、用户需求分析、产品功能分析等多个场景上。我相信还有更多的场景等待大家探索。 它之所以是一种经典的思维框架,在于将无序的数据通过象限归类为了有序。当面对一堆数据或信息一筹莫展时,想一想矩阵的象限划分,它也许就是点燃闪电的火苗。搜索词能被划,产品需求能被划,那么你的难点呢? 最初我并没有学会波士顿矩阵,但我牢牢地记住了矩阵这个词,无非是划四个格子嘛。是不是咨询公司首创我不知道,但在往后遇到和象限有关的技巧或者案例,我都把它们归类在矩阵思维中。 本文阅读到现在,也不过10分钟,但我相信如果你和曾经的我一样了解透了它的核心逻辑,那么恭喜你,以后的工作中,它会是一种下意识的习惯了。 思维框架本身没什么神秘,共勉之。 转自秦路(tracykanc)公众号文章 https://mp.weixin.qq.com/s/s6aBQliD-oG7GGwqSTiIRA 知识在于点滴积累
首先新建表 第一张表 order_info 第二张表 user_info 登录mysql mysql -u root -p 在开始加载数据之前配置编码 查看默认编码 show variables like "%char%"; 配置编码为utf8或gbk set names 'utf8'; #或者 set names 'gbk'; 加载user_info_utf表的数据 load data local infile 'G:/user_info_utf.csv' into table data.user_info fields terminated by ','; 加载order_info_utf表的数据 load data local infile 'G:/order_info_utf.csv' into table data.order_info fields terminated by ','; 注意 可以直接拖拽文件到命令行,生成的路径要改为正斜杠 SQL加载后结果 user_info表 order_info表 知识在于点滴积累
创建数据库 mysql -u root -p CREATE DATABASE Hank; 删除数据库 drop database Hank; 选择数据库 use Hank; MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的。 MySQL支持多种类型,大致可以分为三类: 数值 、日期/时间 和 字符串(字符)类型 。 数值类型 MySQL支持所有标准SQL数值数据类型。 这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。 关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。 BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。 作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767) (0,65 535) 大整数值 MEDIUMINT 3 字节 (-8 388 608,8 388 607) (0,16 777 215) 大整数值 INT或INTEGER 4 字节 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值 BIGINT 8 字节 (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值 FLOAT 4 字节 (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值 DOUBLE 8 字节 (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值 DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值 日期和时间类型 表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。 每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。 TIMESTAMP类型有专有的自动更新特性,将在后面描述。 类型 大小(字节) 范围 格式 用途 DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值 TIME 3 '-838:59:59'/'838:59:59' HH:MM:SS 时间值或持续时间 YEAR 1 1901/2155 YYYY 年份值 DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值 TIMESTAMP 4 1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳 知识在于点滴积累
知识在于点滴积累
配色推荐网址 colour.adobe.com 案例 知识在于点滴积累
信息图 分析图 知识在于点滴积累
树形图 多应用于数据量大、分类层级多的图表 桑葚图 应用于数据复杂的图表 热力图 特殊时间数据 关系图 例如微博大V关注 箱线图 标靶图 词云图 地理图 知识在于点滴积累
当你键入 raw_input() 的时候,你需要键入 ( 和 ) 也就是“括号(parenthesis)”。这和你格式化输出两个以上变量时的情况有点类似,比如说 "%s %s" % (x, y) 里边就有括号。对于 input 而言,你还可以让它显示出一个提示,从而告诉别人应该输入什么东西。你可以在 () 之间放入一个你想要作为提示的字符串,如下所示: y = str(input("Name? ")) Name? hank age = int(input("How old are you? ")) height = int(input("How tall are you? ")) weight = int(input("How much do you weigh? ")) print ("So, you're %r old, %r tall and %r heavy." % ( age, height, weight)) How old are you? 24 How tall are you? 176 How much do you weigh? 125 So, you're 24 old, 176 tall and 125 heavy. 在命令行界面下运行你的程序,然后在命令行输入 pydoc input 看它说了些什么。如果你用的是 Window,那就试一下 python -m pydoc -b 输入 q 退出 pydo 上网找一下 pydoc 命令是用来做什么的? pydoc是python自带的一个文档生成工具,使用pydoc可以很方便的查看类和方法结构 使用 pydoc 再看一下 open, file, os, 和 sys 的含义。看不懂没关系,只要通读一下,记下你觉得有意思的点就行了。 知识在于点滴积累
在习题 9 中我你接触了一些新东西。我让你看到两种让字符串扩展到多行的方法。第一种方法是在月份之间用 \n (back-slash n )隔开。这两个字符的作用是在该位置上放入一个“新行(new line)”字符。 使用反斜杠 (back-slash) 可以将难打印出来的字符放到字符串。针对不同的符号有很多这样的所谓“转义序列(escape sequences)”,但有一个特殊的转义序列,就是 双反斜杠(double back-slash) 。这两个字符组合会打印出一个反斜杠来。接下来我们做几个练习,然后你就知道这些转义序列的意义了。 另外一种重要的转义序列是用来将单引号 ' 和双引号 " 转义。想象你有一个用双引号引用起来的字符串,你想要在字符串的内容里再添加一组双引号进去,比如你想说"I "understand" joe.",Python 就会认为 "understand" 前后的两个引号是字符串的边界,从而把字符串弄错。你需要一种方法告诉 python 字符串里边的双引号不是真正的双引号。 要解决这个问题,你需要将双引号和单引号转义,让 Python 将引号也包含到字符串里边去。这里有一个例子: "I am 6'2\" tall." # 将字符串中的双引号转义 'I am 6\'2" tall.' # 将字符串种的单引号转义 'I am 6'2" tall.' 第二种方法是使用“三引号(triple-quotes)”,也就是 """,你可以在一组三引号之间放入任意多行的文字。接下来你将看到用法。 tabby_cat = "\t I'm tabbed in." persian_cat = "I'M split\non a line." backslash_cat = "I'm \\ a \\ cat." fat_cat = """ I'll do a list: \t* Cat food \t* Fishies \t* Catnip\n\t* Grass """ print (tabby_cat) print(persian_cat) print (backslash_cat) print (fat_cat) I'm tabbed in. I'M split on a line. I'm a cat. I'll do a list: * Cat food * Fishies * Catnip * Grass 加分习题 1.上网搜索一下还有哪些可用的转义字符。 转义字符 描述 (在行尾时) 续行符 \ 反斜杠符号 ' 单引号 " 双引号 \a 响铃 \b 退格(Backspace) \e 转义 \000 空 \n 换行 \v 纵向制表符 \t 横向制表符 \r 回车 \f 换页 \oyy 八进制数,yy代表的字符,例如:\o12代表换行 \xyy 十六进制数,yy代表的字符,例如:\x0a代表换行 \other 其它的字符以普通格式输出 2.使用 ''' (三个单引号)取代三个双引号,看看效果是不是一样的? tabby_cat = "\t I'm tabbed in." persian_cat = "I'M split\non a line." backslash_cat = "I'm \\ a \\ cat." fat_cat = ''' I'll do a list: \t* Cat food \t* Fishies \t* Catnip\n\t* Grass ''' print (tabby_cat) print(persian_cat) print (backslash_cat) print (fat_cat) I'm tabbed in. I'M split on a line. I'm a cat. I'll do a list: * Cat food * Fishies * Catnip * Grass 3.将转义序列和格式化字符串放到一起,创建一种更复杂的格式。 tabby_cat = "\t I'm tabbed in." persian_cat = "I'M split\non a line." backslash_cat = "I'm \\ a \\ cat." fat_cat = ''' I'll do a list: \t* Cat food \t* Fishies \t* Catnip\n\t* Grass ''' print ("%s" % (tabby_cat)) print("%s" % (persian_cat)) print ("%s" % (backslash_cat)) print ("%s" % (fat_cat)) I'm tabbed in. I'M split on a line. I'm a cat. I'll do a list: * Cat food * Fishies * Catnip * Grass 4.记得 %r 格式化字符串吗?使用 %r 搭配单引号和双引号转义字符打印一些字符串出来。 将 %r 和 %s 比较一下。 注意到了吗?%r 打印出来的是你写在脚本里的内容,而 %s 打印的是你应该看到的内容。 tabby_cat = "\t I'm tabbed in." persian_cat = "I'M split\non a line." backslash_cat = "I'm \\ a \\ cat." fat_cat = ''' I'll do a list: \t* Cat food \t* Fishies \t* Catnip\n\t* Grass ''' print ("%s的打印结果") print ("%s" % (tabby_cat)) print("%s" % (persian_cat)) print ("%s" % (backslash_cat)) print ("%s" % (fat_cat)) print ("%r的打印结果") print ("%r" % (tabby_cat)) print("%r" % (persian_cat)) print ("%r" % (backslash_cat)) print ("%r" % (fat_cat)) %s的打印结果 I'm tabbed in. I'M split on a line. I'm a cat. I'll do a list: * Cat food * Fishies * Catnip * Grass %r的打印结果 "\t I'm tabbed in." "I'M split\non a line." "I'm \ a \ cat." "\nI'll do a list:\n\t* Cat food\n\t* Fishies\n\t* Catnip\n\t* Grass\n" 知识在于点滴积累
字符串 转义字符串 转义字符 描述 (在行尾时) 续行符 \ 反斜杠符号 ' 单引号 " 双引号 \a 响铃 \b 退格(Backspace) \e 转义 \000 空 \n 换行 \v 纵向制表符 \t 横向制表符 \r 回车 \f 换页 \oyy 八进制数,yy代表的字符,例如:\o12代表换行 \xyy 十六进制数,yy代表的字符,例如:\x0a代表换行 \other 其它的字符以普通格式输出 知识在于点滴积累
import pandas as pd #导入pandas import matplotlib.pyplot as plt #导入matplotlib from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False %matplotlib inline 数据读取与索引 bra = pd.read_csv('data/bra.csv') bra.head() 选取列 bra.content bra[['creationTime','productColor']].head() 选择行 bra[1:6] 选择行和列 bra.ix[[2,3],[1,3]] #使用ix bra.ix[1:5,['productColor']] bra.iloc[[2,3],[1,3]] #使用iloc bra.loc[1:5,['content','creationTime','productSize']] #使用loc bra.loc[1:5,'content':'userClientShow'] 数据预处理 缺失值 bra.describe() #查看数据的分布情况,可返回变量和观测的数量、缺失值和唯一值的数目、平均值、分位数等相关信息 bra['userClientShow'].unique() #userClientShow列有几种选项 bra['userClientShow'].isnull().sum() #初始缺失值数量 bra['userClientShow'].fillna('不详',inplace=True) #缺失值替换为“不详” bra['userClientShow'].isnull().sum() #赋值后的缺失值数量 新增列 bra.dtypes #查看属性 bra['creationTime'] = pd.to_datetime(bra['creationTime']) #更新类型 bra.dtypes bra['hour'] = [i.hour for i in bra['creationTime']] #新建hour列 bra 字符串操作 bra.productSize.unique() #查看productSize的唯一值 cup = bra.productSize.str.findall('[a-zA-Z]+').str[0] #新增列cup cup2 = cup.str.replace('M','B') cup3 = cup2.str.replace('L','C') cup4 = cup3.str.replace('XC','D') bra['cup'] = cup4 bra.head() bra['cup'].unique() #查看cup唯一值 数据转换 bra.productColor.unique() #查看productColor唯一值 def getColor(s): if '黑' in s: return '黑色' elif '肤' in s: return '肤色' elif '蓝' in s: return '蓝色' elif '红' in s: return '红色' elif '紫' in s: return '紫色' elif '白' in s: return '白色' elif '粉' in s: return '粉色' elif '灰' in s: return '灰色' elif '绿' in s: return '绿色' elif '青' in s: return '青色' else: return s bra['color'] = bra['productColor'].map(getColor) #从productColor列查询,赋值到定义的函数getColor,最终新增列color bra bra.color.unique() #查询color的唯一值 数据可视化 x = [1991,1992,1993,1994,1995,1996,1997] y = [23,56,38,29,34,56,92] plt.plot(x,y) #调用函数plot plt.figure(figsize=(8,6),dpi=80) #调用函数firgure plt.plot(x,y) hour = bra.groupby('hour')['hour'].count() #hour列排序 hour plt.xlim(0,25) #横轴0~25 plt.plot(hour,linestyle='solid',color='royalblue',marker='8') #颜色深蓝 cup_style = bra.groupby('cup')['cup'].count() #cup列唯一值得数量 cup_style plt.figure(figsize=(8,6),dpi=80) labels = list(cup_style.index) plt.xlabel('cup') #x轴为cup plt.ylabel('count') #y轴为count数量 plt.bar(range(len(labels)),cup_style,color='royalblue',alpha=0.7) #alpha为透明度 plt.xticks(range(len(labels)),labels,fontsize=12) plt.grid(color='#95a5a6',linestyle='--',linewidth=1,axis='y',alpha=0.6) plt.legend(['user-count']) for x,y in zip(range(len(labels)),cup_style): plt.text(x,y,y,ha='center',va='bottom') color_style = bra.groupby('color')['color'].count() #color列唯一值得数量 color_style plt.figure(figsize=(8,6),dpi=80) plt.subplot(facecolor='gainsboro',alpha=0.2) colors = ['brown','orange','gray','white','pink','purple','red','green','wheat','blue','gold','springgreen','black'] #颜色种类 labels = list(color_style.index) plt.xlabel('count') #x轴为count数量 plt.ylabel('color') #y轴为color plt.title('Color Distribution') #定义标题 plt.barh(range(len(labels)),color_style,color=colors,alpha=1) plt.yticks(range(len(labels)),labels,fontsize=12) plt.grid(color='#95a5a6',linestyle='--',linewidth=1,axis='x',alpha=0.4) bra.head(30) 知识在于点滴积累
最近有不少同学在后台问我数据分析的职业发展相关,这里先列一个简易大纲。它更多是以我所在的互联网行业展开的。 入门和职业规划应该从两个角度考虑:领域和路线。 领域是不少新人常忽略的要素,其实数据分析不会脱离业务存在。你进入哪个行业,很大程度会决定你初期的技能树和技能点。譬如金融领域的风控模型、营销领域的生命周期、广告领域的点击率预估等,各有各的特色。 如果是一位应届生,不妨多了解自己感兴趣的领域,和专业相关是最好的,并且积累相关的经验,为面试做准备。 如果已经有一定行业履历,只是想要转岗数据分析师,那么跨岗不跨行,避免跳到一个陌生的领域。 领域经验太宽泛,我给不了太多的指点,主要也就三点:1.自己感兴趣的,2.自己擅长的,3.有钱途的。从职场生涯看,成为某领域的数据专家,会是一个更好的筹码。 而路线大致可以划分成四大方向: 数据分析,数据挖掘,数据产品,数据工程。 数据分析/数据运营/商业分析 这是业务方向的数据分析师。 绝大部分人,都是从这个岗位开始自己的数据之路,也是基数最大的岗位。 因为基数大,所以这类岗位通常鱼龙混杂。有些虽然叫数据分析师,但是每天只需要和Excel打交道,完成leader布置的表格整理工作就行。混个几年,成为一位数据分析主管,给下面的新人继续布置Excel任务。 又有一种数据分析师,岗位职责要求你掌握常用的机器学习算法,面试首先推导一个决策树或者逻辑回归。入职后也是各类代码,和分析打交道的情况不多。 都叫数据分析师,其实天差地别。 这里更多指互联网行业,偏业务的数据分析师,一般属于运营部门。不少公司也称数据运营或者商业分析。 这类岗位的职位描述一般是: 负责和支撑各部门相关的报表; 建立和优化指标体系; 监控数据的波动和异常,找出问题; 优化和驱动业务,推动数据化运营; 找出可增长的市场或产品优化空间; 输出专题分析报告; 实际情况是,不少业务端的数据分析师,主要工作只做第一点。别管它用汇总、分析、数据支持什么修饰词,基本是跑SQL,做报表。硬生生活成了业务端的表哥。 这是很常见的情况,也是入门新人的第一个坑。因为从头到尾,这类分析师,都没有解决问题。 业务部门往往更关心,某个指标为什么下跌或者上升。产品的用户是什么样的?怎么能更好的完成自己的KPI。 以活跃指标的下跌举例: 活跃指标下跌了多少?是属于合理的数据波动,还是突发式? 什么时候开始的下跌? 是整体的活跃用户下跌,还是部分用户? 为什么下跌?是产品版本,还是运营失误? 怎么解决下跌的问题 这是一套标准的解决思维。分别对应what、when、who、why、how,每一部分都不是三言两语可以解释清楚。不要看它简单,例如你通过多维分析,发现某个地区的活跃下跌了,不要急着把它作为分析的结论,这是不合格的数据分析。某地区的活跃下跌,只是现象,不是原因,把它作为结论提交,肯定会被骂的。 你要解决的是,为什么这个地区的活跃下跌了。是该地渠道,是该地竞争对手,是该地市场环境? 这些问题都是细化深入的范畴。并且,它们要能以量化解释,而不是我认为。 做好了这点,才是一个真正的业务端的数据分析师。 当然,这一点看的是leader。leader能否带你进入业务分析的大门,决定你将来是不是成为一个表哥。新人切记切记。 解决问题是一方面工作,另外一方面,数据分析师的职责是将业务数据体系化,建立一套指标框架。活跃下跌的问题,本质上也是指标问题。什么时候开始下跌,哪部分下跌,都能转化成对应指标,如日活跃用户数,新老用户活跃数,地区活跃数。 你不能衡量它,就无法增长它,指的就是指标体系。指标体系可以是业务部门建立,但数据分析师也挺合适。一方面他们比数据挖掘这类技术岗位更贴合业务,一方面不像业务岗位对数据抓瞎。 两者结合,这岗位也能称为数据运营。 指标体系如果工程化自动化,也就是BI,所以数据分析师可以算半个BI分析师,这里不包括BI报表开发。BI如果采购第三方,数据分析师负责BI没问题,如果自有开发,那么BI岗技术的色彩更浓厚。 数据分析思维和业务的理解,是分析师赖以生存的技能。很多时候,工具是锦上添花的作用。掌握Excel+SQL/hive,了解描述统计学,知道常见的可视化表达,足够完成大部分任务。机器学习这类能力,对此类数据分析师不是必须的,Python也一样,只是加分项。毕竟为什么下跌,你无法用数据挖掘解答。 数据分析师是一个基础岗位,如果专精于业务,更适合往管理端发展,单纯的工具和技巧很难拉开差距。数据分析的管理岗,比较常见的有数据运营经理/总监,数据分析经理等,相对应的能力是能建立指标体系,并且解决日常的各类「为什么」问题。 商业/市场分析是另外一个方向,更多见于传统行业。 你要开一家超市,你得考虑哪里开,这就要考虑居民密度,居民消费能力,竞争对手的多寡,步行交通距离,开车交通距离等。这些数据是宏观的大指标,往往靠 搜索和调研 完成,这是和互联网数据分析师最大的差异。 若往其他分支发展,比如数据挖掘工程师,则要继续掌握Python和机器学习等。从业务型发展上来的好处是接地气,具备商业洞察力(天天搞报表,怎么可能不熟),这点是直接做数据挖掘,或者程序员转岗,所不具备的。 新人,比较普适的发展路线是先成为一位数据分析师。积累相关的经验, 在一两年后, 决定往后的发展,是数据挖掘,还是专精数据分析成为管理岗。 学习资料: 这里对学习资料不再多做推荐,看历史文章: 如何七周成为数据分析师 数据挖掘/算法专家 这是技术向的数据岗,有些归类在研发部门,有些则单独成立数据部门。 数据挖掘工程师要求更高的 统计学能力、数理能力以及编程技巧 。 从概念上说,数据挖掘Data mining是一种方式,机器学习Machine Learning是一门方法/学科。机器学习主要是有监督和无监督学习,有监督又可划分成回归和分类,它们是从过去的历史数据中学习到一个模型,模型可以针对特定问题求解。 数据挖掘的范围则大得多,即可以通过机器学习,而能借助其他算法。比如 协同过滤、关联规则、PageRank等 ,它们是数据挖掘的经典算法,但不属于机器学习,所以在机器学习的书籍上,你是看不到的。 除此之外,还有一个领域,属于最优化问题的 运筹学 。 现实中的问题往往有很多约束,比如护士排班,一共有三班(早、中、晚),现在要求每班满足最低护士人数,每位护士尽量不能连班,每位护士不能连续工作5天。每位护士的夜班数要均衡,每位护士每月的班数要均衡…这些问题很难用机器学习的方法完成,而在最优化领域,则有遗传算法、模拟退火算法、蚁群算法等。 实际的应用场景中,如外卖行业,如何寻找骑手效率最大化的最优路径,同样属于最优化,也是数据挖掘的工作范畴。 数据挖掘工程师,除了掌握算法,同样需要编程能力去实现,不论R、Python、Scala/Java,至少掌握一种。模型的实施,往往也要求Hadoop/Spark的工程实践经验,精通SQL/Hive是必须的。 常见数据挖掘项目的闭环如下: 定义问题 数据抽取 数据清洗 特征选取/特征工程 数据模型 数据验证 迭代优化 单看环节,数据挖掘对分析能力没有业务型那么高。这不代表业务不重要,尤其在特征选取方面,对业务的理解很大程度会影响特征怎么选取,进而影响模型质量。用户流失是一个经典的考题,如何选取合适的特征,预测用户会否流失,能够考察对业务是否深刻洞察。 数据挖掘的业务领域一样可以细分。金融行业的信用模型和风控模型/反欺诈模型、广告模型的点击预估模型、电商行业的推荐系统和用户画像系统。从需求提出到落地,数据挖掘工程师除了全程跟进也要熟悉业务。 因为要求高,所以 数据挖掘的平均薪资高于数据分析师 。 一个分工明确的团队,数据分析师负责将业务需求抽象成一个具体的数据假设或者模型。比如,运营希望减少用户流失,那么设立一个流失指标,现在需要预测用户流失率的模型。模型可以是数据分析师完成,也能是数据挖掘工程师。最终由数据挖掘团队部署到线上。 在一些公司,高级数据分析师会等价于数据挖掘工程师(其实行业内,对Title并没有严格的标准),只是工程能力可以稍弱,模型部署由专门的工程团队完成。 数据挖掘工程师,往后发展,称为算法专家。后者对理论要求更严苛,几乎都要阅读国外的前沿论文。方向不局限于简单的分类或者回归,还包括图像识别、自然语言处理、智能量化投顾这种复合领域。这里开始会对从业者的学校和学历提出要求,名校+硕士无疑是一个大优势,也有很多人直接做数据挖掘。 深度学习则更前沿,它由神经网络发展而来,是机器学习的一个子集。因为各类框架开枝散叶,诸多模型百花齐放,也可以算一个全新的分支。除了要求熟悉TensorFlow, Caffe, MXNet等深度学习框架,对模型的应用和调参也是必备的,后者往往是划分普通人和大牛的天堑。 算法专家和深度学习专家,薪资level会更高一级,一般对应于业务型的数据运营/分析总监。 数据科学家 是上述岗位的最终形态之一,要么理论能力非常强,往往担任研究院的一把手。要么工程能力突出,上述的系统都能完成平台化的部署。 学习资料: 这类岗位对基础知识要求扎实,所以书籍需要比较大的阅读量,而且要保持领域新论文的吸收。 统计知识,除了「商务与经济统计」外,国外有一本「The Elements of Statistical Learning」,评价不错。 机器学习的入门,李航的「统计学习方法」,周志华的「机器学习」都是好书,英文好也能看PRML。 Python入门书籍的推荐太多,略过。「用Python进行数据分析」是必备的,当然这本书有点老,活用官网最新文档和stackoverflow,基本无碍。Python可视化查阅文档也够了,不用看书。 再进一步,则是机器学习的代码实现,比较知名的有「集体智慧编程」,「机器学习实战」等。其实最近还有不少新书,「Python DataScience Handbook」等,我当然不可能都看过,所以也不好推(hu)荐(you)。 除了基础,行业领域的也别落下,诸如 推荐系统实战、计算广告…按需学习 。如果你们公司对于人才有较高的挑战(一个人当两个人用),大概Spark/Hadoop机器学习相关的框架也得了解。 数据产品经理 这个岗位比较新兴,它有两种理解,一种是具备 强数据分析能力的PM,一种是公司数据产品的规划者。 前者,以数据导向优化和改进产品。在产品强势的公司,数据分析也会划归到产品部门,甚至运营也属于产品部。这类产品经理有更多的机会接触业务,属于顺便把分析师的活也干了,一专多能的典型。 他们会运用不同的数据源,对用户的行为特征分析和挖掘,达到改进产品。最典型的场景就是AB测试。大到页面布局、路径规划、小到按钮的颜色和样式,均可以通过数据指标评估。 下图的案例,就是弱化心愿单按钮的存在感,让用户更多的聚焦在直接购买而不是收藏,最终让销售额提高了35%。 俗话说,再优秀的产品经理也跑不过一半AB测试。此类数据产品经理,更多是注重数据分析能力,擅长用分析进行决策。数据是能力的一部分。 后者,是真正意义上的数据产品经理。在公司迈大迈强后,数据量与日俱增,此时会有不少数据相关的产品项目:包括大数据平台、埋点采集系统、BI、推荐系统、广告平台等。这些当然也是产品,自然需要提炼需求、设计、规划、项目排期,乃至落地。 我们不妨看几个数据产品经理要求: 负责大数据产品的设计,输出需求文档、产品原型; 负责推荐算法的产品策略,完成相关推荐及个性化推荐产品的需求分析; 负责分析和挖掘用户消费内容的行为数据,为改进算法策略提供依据; 负责客户端数据需求的对接,制定相关埋点规范及口径,相关业务指标验证; 报表展示工具的落地和应用; 和C端注重用户体验不同,数据产品,更注重整体的分析能力和逻辑。除了产品经理最基础的Axure、Visio、MindManager等工具。往往还需要很多技术型的能力。比如了解BI/DW原理和实施、了解常用的推荐算法、了解机器学习模型等。这也很容易理解,C端要求你了解用户需求,而在数据端,主要用户就是数据。 这当然不是说,用户体验不重要,拿推荐算法来说,除了满足用户最基本的感兴趣,也要考虑时效性,考虑新兴趣的挖掘,考虑无数据时的冷启动问题…这些一样是用户体验,只是解决方案也得从数据出发。再多思考一步,模型是离线还是实时,实时怎么实现它?技术细则不用多考虑,但你要知道会有这些坑。后端的数据产品,如报表,用户往往是你隔壁工位的小秦或小路,设计得丑一点不要紧,要是数据指标口径不统一,那才会分分钟骂街。 虽然数据PM需要熟悉各类数据模型、指标、数据挖掘和数据工程的实现,但是聚焦点是把它作为一个项目去实现,故而不用精通。 数据产品经理是一个比较新兴的岗位,所以有丰富经验的从业者并不多,我个人认为,还是存在比较大的职业缺口。当然也有其他问题,一是因为新兴,部门负责人本身也没有想好他们能干什么,不少数据PM还从事表哥的工作。二是数据产品本身可借鉴的经验不多,像APP产品,可以下载体验,总归有一个学习的过程。然而用户画像、BI、算法策略,都是其他公司的内部机密,无从参考,我就遇到不少对用户画像实现非常感兴趣的数据PM。 从职业发展上看, 数据分析师做数据产品经理更合适 。普通的产品经理,对前端、后端的技术栈尚未熟悉,何况日新月异的数据栈。这个岗位,适合对数据特别感兴趣,但是数理天赋不高的职场人,那么以沟通、项目管理和需求规划为能力,也不错。 学习资料: 数据产品经理,如果有数据挖掘经验,那么技术相关的书籍倒不重要,别落伍就行,更关注产品经理本身的能力,包括Axure,各类文档的编写、项目管理、需求整理等,市面上资料比较多。 这里再补充两本,「数据挖掘与数据化运营实战」,没啥高深技术,但是能够了解体系的初步建立。「数据挖掘技术—应用于市场营销、销售与客户关系管理」,这本书我推荐它是纠结的,它的知识点比较丰富,业务人员也能看懂,但是翻译的实在太糟糕了…… 更多书籍参考其他岗位即可。 数据工程师 数据工程师其实更偏技术,从职业道路上看,程序员走这条路更开阔。 在很多中小型的公司,一方面数据是无序的、缺失的、原始的,另外一方面各种业务报表又嗷嗷待哺。没办法,分析师只能自己撸起袖子,一个人当三个人用。兼做数据清洗+ETL+BI。 经历过的大概都懂,数据分析踏上数据工程的不归路如下: 每天都要从五六张表上join,那么不妨加工成一张中间表; ETL的依赖关系越来越复杂,尝试用kettle/airflow等框架搞定,弄个DAG美滋滋; 运营部门的周报次次都要这几个指标,看看能否做一个自动化BI; 数据量逐日增多,最近T+1的日报需要几个小时完成,研究下查询语句的优化; 查询语句的优化空间也不大了,开始迁移到Hadoop/Spark分布式平台,新技术栈的学习; 新平台,原有的工具也不管用了,某大牛说apache上有工具能解决这个问题,于是阅读文档; 公司部署了私有化的埋点采集,数据缺失比较厉害,业务部门天天骂娘,继续埋Flume/Kafka的坑; 等等… 如果分析师在技术方面的灵性不错,那么技能点会往技术栈方向迁移。从最初的SQL,到了解Hadoop集群、了解presto/impala/spark、了解ELK、了解分布式存储和NoSQL…… 这也是一个不错的发展方向,因为数据挖掘需要了解算法/模型,理论知识要求过高,不少硕士和博士还过来抢饭碗,自己不擅长容易遇到天花板。选择更底层的工程实现和架构,也是出路,薪资也不会低于数据挖掘/算法专家。 部分归属到技术部的数据分析师,虽然Title叫数据分析(其实应该叫数据分析开发工程师),很多工作也是围绕ETL/DW/BI进行,那么这就是标准的数据工程路线。 部分公司会将机器学习模型的部署和实现交给数据工程团队,这要求数据工程师熟悉sparkMLlib、Mahout此类框架。 数据工程师,可以从数据分析师的SQL技能,往数据的底层收集、存储、计算、运维拓展。往后发展则是数据总监、或者数据架构师。因为数据分析出身,与纯技术栈的程序员比,思考会更贴合业务,比如指标背后的数据模型,但是技术底子的薄弱需要弥补。 另外,DBA、BI这些传统的数据库从业者,也是能按这条路线进阶,或者选择数据产品经理方向。 学习资料: 数据工程类的书籍,我看的不多,给不了建议。主要按各类名词搜索吧,什么linux、数据仓库、Hadoop、Spark、Storm、Elasticsearch等。这类岗位发展,技术更新速度比较快,所以需要保持吸收以及活用开源。 最后 以上四个岗位就是数据分析的发展方向,它们互有关联,如果从整个架构图来看(一篇历史旧文有更详细的描述:从零开始,构建数据化运营体系 )。 我们可以将其划分为 数据收集—数据加工—数据运营—数据触达。 数据收集负责收集各种各样的原始数据,比如用户何时何地做了什么事情。它依赖于埋点采集系统,而埋点采集,需要收集什么类型数据,往往由数据产品经理确定规范(还是看公司,数据运营和数据分析师也能负责)。 收集上来的数据需要存储,往往因为高吞吐量,需要保证数据和日志的稳定性,会采用Flume+Kafka,如果有实时统计要求,也得考虑流数据。这块则是数据工程的范畴,包括原始数据的再加工,数据清洗,都是专门的数据团队完成。 当获得数据后,首先第一点是讲各种明细数据加工业务指标,没有指标不成方圆,这里由数据分析师定义的。有了指标,配合各种数据产品输出,如用户画像用户标签、BI报表,这些数据产品都由数据PM统筹排期…另外一方面,数据挖掘工程师和算法专家则凭各种数据建立模型,进行实时或离线运算。 模型可能会预测用户会不会购买某个商品,可能是做出一系列的推荐,可能是判断用户属于哪个类型,不一而足。 更上面一层是业务相关,数据分析师会监控和分析BI上指标的波动、数据挖掘工程是通过用户反馈数据,衡量算法的优劣、数据PM按AB测试的结果改进产品。数据工程师保证系统的稳定。 所有层次一环扣一环,每个岗位在其中都发挥特有的作用。数据工程偏底层技术,数据分析偏上层业务,数据挖掘和数据产品处于中间形态。不同公司虽然业务形态不一致,架构会有差异,但是职责不会偏差太大。这也是数据分析为什么会有四个方向。 讲到这里,你大概对数据分析的职业规划有了明晰的了解。当然,它们彼此间并不完全独立,到后期,很多界限会变得模糊。所以规划是一方面,是否愿意执行、学习和吃透,才是职业真正的道路呀。 本文转载自秦路 https://ask.hellobi.com/blog/qinlu/10261 知识在于点滴积累
# Here's some new strange stuff, remember type it exactly. days = "Mon Tue Wed Thu Fri Sat Sun" months = "Jan\n Feb\n Mar\n Apr\n May\n Jun\n Jul\n Aug" print("Here are the days: ", days) print("Here are the months: ", months) print(""" There's something going on here. With the three double-quotes. We'll be able to type as much as we like. Even 4 lines if we want, or 5, or 6. """) Here are the days: Mon Tue Wed Thu Fri Sat Sun Here are the months: Jan Feb Mar Apr May Jun Jul Aug There's something going on here. With the three double-quotes. We'll be able to type as much as we like. Even 4 lines if we want, or 5, or 6. 知识在于点滴积累
formatter = "%r %r %r %r" print (formatter % (1, 2, 3, 4)) print (formatter % ("one", "two", "three", "four")) print (formatter % (True, False, False, True)) print (formatter % (formatter, formatter, formatter, formatter)) print (formatter % ( "I had this thing.", "That you could type up right.", "But it didn't sing.", "So I said goodnight." )) 1 2 3 4 'one' 'two' 'three' 'four' True False False True '%r %r %r %r' '%r %r %r %r' '%r %r %r %r' '%r %r %r %r' 'I had this thing.' 'That you could type up right.' "But it didn't sing." 'So I said goodnight.' 知识在于点滴积累
现在我们将做一批练习,在练习的过程中你需要键入代码,并且让它们运行起来。我不会解释太多,因为这节的内容都是以前熟悉过的。这节练习的目的是巩固你学到的东西。我们几个练习后再见。不要跳过这些习题。不要复制粘贴! print("Mary had a little lamb.") print ("Its fleece was white as %s." % 'snow') print ("And everywhere that Mary went.") print ("."* 10 )# what'd that do? end1 = "C" end2 = "h" end3 = "e" end4 = "e" end5 = "s" end6 = "e" end7 = "B" end8 = "u" end9 = "r" end10 = "g" end11 = "e" end12 = "r" print (end1 + end2 + end3 + end4 + end5 + end6,) print (end7 + end8 + end9 + end10 + end11 + end12) Mary had a little lamb. Its fleece was white as snow. And everywhere that Mary went. .......... Cheese Burger 知识在于点滴积累
虽然你已经在程序中写过字符串了,你还没学过它们的用处。在这章习题中我们将使用复杂的字符串来建立一系列的变量,从中你将学到它们的用途。首先我们解释一下字符串是什么 东西。 字符串通常是指你想要展示给别人的、或者是你想要从程序里“导出”的一小段字符。Python 可以通过文本里的双引号 " 或者单引号 ' 识别出字符串来。这在你以前的 print 练习中你已经见过很多次了。如果你把单引号或者双引号括起来的文本放到 print 后面,它们就会被 python 打印出来。 字符串可以包含格式化字符 %s,这个你之前也见过的。你只要将格式化的变量放到字符串中,再紧跟着一个百分号 % (percent),再紧跟着变量名即可。唯一要注意的地方,是如果你想要在字符串中通过格式化字符放入多个变量的时候,你需要将变量放到 ( ) 圆括号(parenthesis)中,而且变量之间用 , 逗号(comma)隔开。就像你逛商店说“我要买牛奶、面包、鸡蛋、八宝粥”一样,只不过程序员说的是”(milk, eggs, bread, soup)”。 我们将键入大量的字符串、变量、和格式化字符,并且将它们打印出来。我们还将练习使用简写的变量名。程序员喜欢使用恼人的难度的简写来节约打字时间,所以我们现在就提早学会这个,这样你就能读懂并且写出这些东西了。 x = "There are %d types of people." % 10 #说明有10种类型的人 binary = "binary" #定义变量 do_not = "don't" #定义变量 y = "Those who know %s and those who %s." % (binary, do_not) #代入变量 print (x) #运行x print (y) #运行y print ("I said: %r." % x) #说明,运行x print ("I also said: '%s'." % y) #说明,运行y hilarious = False joke_evaluation = "Isn't that joke so funny?! %r" print (joke_evaluation % hilarious) #两个变量合并 w = "This is the left side of..." #定义w e = "a string with a right side." #定义e print (w + e) #运行w+e结果 There are 10 types of people. Those who know binary and those who don't. I said: 'There are 10 types of people.'. I also said: 'Those who know binary and those who don't.'. Isn't that joke so funny?! False This is the left side of...a string with a right side. 知识在于点滴积累
R下载安装https://mirrors.tuna.tsinghua.edu.cn/CRAN/ RStudio下载安装https://www.rstudio.com/products/rstudio/download/#download 知识在于点滴积累
每一种编程语言都包含处理数字和进行数学计算的方法。不必担心,程序员经常撒谎说他们是多么牛的数学天才,其实他们根本不是。如果他们真是数学天才,他们早就去从事数学相关的行业了,而不是写写广告程序和社交网络游戏,从人们身上偷赚点小钱而已。 这章练习里有很多的数学运算符号。我们来看一遍它们都叫什么名字。你要一边写一边念出它们的名字来,直到你念烦了为止。名字如下: + plus 加号 - minus 减号 / slash 斜杠 * asterisk 星号 % percent 百分号 < less-than 小于号 > greater-than 大于号 <= less-than-equal 小于等于号 >= greater-than-equal 大于等于号 知识在于点滴积累
你已经学会了 print 和算术运算。下一步你要学的是“变量”。在编程中,变量只不过是用来指代某个东西的名字。程序员通过使用变量名可以让他们的程序读起来更像英语。而且因为程序员的记性都不怎么地,变量名可以让他们更容易记住程序的内容。如果他们没有在写程序时使用好的变量名,在下一次读到原来写的代码时他们会大为头疼的。 如果你被这章习题难住了的话,记得我们之前教过的:找到不同点、注意细节。 在每一行的上面写一行注解,给自己解释一下这一行的作用。 倒着读你的 .py 文件。 朗读你的 .py 文件,将每个字符也朗读出来。 用jupyter notebook运行代码 加分习题 编辑内容上方是条件,下面是包含条件的问题,翻译出来的就是结果了。在前面一节提到过,计算的时候print后面不用加引号,从上述结果来看也同样适用于变量赋值,上面的space_in_a_car=4.0,加了浮点数,所以结果也带有浮点数,浮点数详细说明也请参照上一章。值得注意的是,编辑的代码要保持变量一致性,包含变量的输入内容一定要和条件中的变量一摸一样,而这就需要我们的细心,否则的话翻译出来是没有结果的,会出现下面这种情况: Traceback (most recent call last): File "ex4.py", line 8, in <module> average_passengers_per_car = car_pool_capacity / passenger NameError: name 'car_pool_capacity' is not defined 附加题: 1.我在程序里用了 4.0 作为 space_in_a_car 的值,这样做有必要吗?如果只用 4 会有什么问题? 4.0包含浮点数,进行运算得到的结果会更清洁,不加浮点数如果得到的结果包含小数,就只会显示整数部分,这样会导致结果不精确。 2.记住 4.0 是一个“浮点数”,自己研究一下这是什么意思。 浮点数作用就是使计算结果更加精确的 3.在每一个变量赋值的上一行加上一行注解。 4.记住 = 的名字是等于(equal),它的作用是为东西取名。 5.记住 _ 是下划线字符(underscore)。 6.将 python 作为计算器运行起来,就跟以前一样,不过这一次在计算过程中使用变量名来做计算,常见的变量名有 i, x, j 等等。 知识在于点滴积累