1008~1015

1008内容概要

  • 爬虫框架之Scrapy

  • 非关系型数据库之MongoDB

    只要MySQL没有忘记 学习MongoDB是非常轻松的!!!
    
  • MongoDB简介

  • MongoDB下载与安装

  • MongoDB重要概念

  • MongoDB基本操作

1008内容详细

爬虫框架之Scrapy

框架:别人提前给你搭建好了基本架构 具备了一定的功能

Scrapy是网络爬虫中使用频率最高功能最为完善的框架

# 1.下载scrapy框架
	pip3 install scrapy
	'''mac本一般直接下载即可 但是windows电脑可能会出错'''
   	windows电脑如果下载报错并且没有典型的关键字特征那么需要做额外配置
    	 1.pip3 install wheel
         2.https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
         3.文件的存放位置如何明确
        	pip3 install 文件名  # 通过报错信息查看存放位置
         4.pip3 install pywin32
         5.pip3 install scrapy
    
# 2.验证scrapy是否下载成功
	windows命令行cmd终端内输入scrapy即可

Scrapy基本使用

# 创建一个项目
	scrapy startproject 项目名
    '''自动生成一个内部含有多个py文件及文件夹的文件夹'''
# 创建爬虫文件
	scrapy genspider jd www.jd.com
    '''自动创建py文件并填写一定的代码 方便统一管理'''
# 执行爬虫文件
	scrapy runspider jd.com
    scrapy crawl jd

Scrapy文件介绍

项目名文件夹
	项目名同名的文件夹
    	spiders文件
        	存放爬虫项目文件
    settings.py	 # 配置文件
    	"""ROBOTS.TXT爬虫协议"""
    items.py  # 数据存储相关的文件
    middlewares.py  # 中间件文件
    	'''在一个完整的操作流程中可以穿插多个小的操作步骤'''
    pipelines.py  # 数据存储相关的文件

MongoDB数据库

数据库的分类
	关系型数据库
    	MySQL、Oracle、PostgreSQL、MariaDB、sql server、sqlite
        """固定的表结构 并且可以建立外键关系"""
    非关系型数据库
    	redis、mongodb、memcache
        """没有固定的表结构 并且数据的存储采用的是k:v键值对形式"""
    
非关系型数据库之MongoDB
	该数据库存储数据的量和处理时间较于关系型数据库快很多
    该数据库也是大数据生态圈里面常用的一款软件
    该数据库是一款最像关系型数据库的非关系型数据库(文本结构)
  
"""
横向扩展与纵向扩展
		以提升计算机性能为例
	横向扩展:买来多台计算机组合使用(常用 企业)
	纵向扩展:就在一台计算机上面不停的优化(个人)
"""

MongoDB重要概念

# 为了理解和学习的方便 我们还可以使用MySQL的名词来称呼
database 	database		库
table		collection  	集合
row			document    	文档
column       field       	 字段

MongoDB下载与安装

https://www.mongodb.com/try/download/community
	下载msi文件即可
  
bin文件夹
	'''里面存放一堆启动文件'''
    mongod.exe	服务端
    mongo.exe   客户端
data文件夹
	'''里面存放数据相关文件'''
log文件夹
	'''里面存放日志相关文件'''

启动步骤

1.去官网下载msi文件 双击安装即可
2.mongodb文件介绍
	bin文件夹
    	所有的启动程序一般都是放在该文件夹内
    data文件夹
    	存储数据
    log文件夹
    	存储日志(操作记录)
3.查看mongodb文件夹内是否含有data和log文件夹
	如果没有需要你自己手动创建
    如果有则直接跳过
4.在data文件内创建db文件夹(目的是为了管理文件资源)
5.将启动文件所在的路径添加到环境变量中
6.在MongoDB文件夹根目录下
	创建mongod.cfg文件
    	在该文件内拷贝以下代码
        systemLog:
       		destination: file
       		path: "D:\MongoDB\log\mongod.log"
       		logAppend: true
        storage:
           journal:
              enabled: true
           dbPath: "D:\MongoDB\data\db"
        net:
           bindIp: 0.0.0.0
           port: 27017
        setParameter:
           enableLocalhostAuthBypass: false
7.系统服务制作
		mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db  --serviceName "MongoDB" --serviceDisplayName "MongoDB"  --install  --auth
'''auth即让服务端以校验用户身份的方式启动 不加则不校验''' 

8.启动\关闭
    net start MongoDB
    net stop MongoDB

9.登录
	mongo

基础命令

'''mongodb语句不需要使用分号结束'''
# 1.查看所有的数据库名词
	show dbs  # show databases;
    """
    mongodb默认三个数据库
    	admin config local
    """

# 2.退出客户端
	exit  # exit();
    quit()  # quit();

补充

MongoDB的特性在于无需可以创建东西 指定即可使用但是只有在真正用到了该东西之后才会保存到硬盘 在此之前都是在内存中临时创建

针对库的增删改查

# 查看
show dbs  
"""show databases;"""

# 新增
use db1  # 现在内存中自动创建 如果db1内写入了数据那么才会刷到硬盘中
"""create database db1;"""

# 修改
忽略

# 删除
先插入数据  db.db1.insert({'name':'jason'})
db.dropDatabase()  # db是关键字 当前在哪个库下执行改命令就是删除哪个库
"""drop database db1;"""

针对集合(表)的增删改查

# 相当于MySQL中的表的概念
要想操作collection必须先有database

# 增
db.createCollection('表名')
db.collection名字  # 如果单纯的创建不插入数据 那么也只是在内存临时创建

# 查
show tables
show collections

# 改
忽略

# 删
db.collection名字.drop()

针对文档(记录)增删改查

# 增
db.t1.insert({})  # 单条数据
	insert也可以插入多条  db.t1.insert([{},{},{}])
db.t1.insertMany([{},{},{}])  # 多条数据


# 查
db.t1.find()  # select * from t1;
db.t1.find({'name':'jason'})# select * from t1 where name='jason';


# 改 
db.t1.update({'name':'jason'},{$set:{'name':'jasonNB'}})  # 修改
db.t1.update({'name':'jasonNB'},{'name':'jason666'})  # 替换(少用)

# 删
db.t1.remove({})  # delete from t1;
db.t1.remove({'name':'jason'})# delete from t1 where name='jason';

1009内容概要

  • 文档操作补充

  • 用户权限管理

  • 查询关键字(有很多)

    只要MySQL的SQL语句没忘记 学这个相当的简单!!!
    '''SQL语句和NoSQL语句对照着写'''
    
  • 分组与聚合

  • 其他查询补充

1009内容详细

文档操作补充

涉及到数据的嵌套查找 支持直接点键或者索引
	db.t1.deleteOne({'addr.counytry':'Japan'})
    db.t1.deleteOne({'hobby.1':'tea'})
    # .键.索引.索引.键.键 可以无限制的往下点点点

用户权限管理

"""涉及到用户权限相关 引号推荐全部使用双引号"""
"""
mongodb针对用户权限的创建,数据可以保存在不同的数据库下
之后在登录的时候只需要自己指定账户数据来源于哪个数据库即可
但是管理员用户数据一般情况下推荐保存到admin库下
而普通用户任意库都可以,我们为了便于管理可以在test库下创建
"""
管理员账户需要在admin数据库下创建
1.切换到admin数据库下
use admin
2.创建账户并且赋予权限
db.createUser(
    {
        user: "root",
        pwd: "123",
        roles: [ { role: "root", db: "admin" } ]
    }
)

其他用户在test数据库下创建
1.切换到test数据库下
use test
2.创建账户并赋予权限
db.createUser(
    {
        user: "jyb",
        pwd: "123",
        roles: [ { role: "readWrite", db: "test" },
                { role: "read", db: "db1" } ]
    }
)
# 针对test库用于读写的权限  针对db1库只拥有读的权限
'''上述账户都可以创建多个'''
# 最好是使用管理员打开cmd操作下列命令
先停止服务
    	net stop MongoDB
再移除服务
    	MongoD --remove
再次添加
    	mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\Server\4.4\log\mongod.log --logappend --dbpath D:\MongoDB\Server\4.4\data  --serviceName "MongoDB" --serviceDisplayName "MongoDB"  --install --auth
            
            
mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data  --serviceName "MongoDB" --serviceDisplayName "MongoDB"  --install --auth            
            
    再次启动
    	net start MongoDB
  
两种验证方式
	1.直接在登录的时候验证
    	mongo -u "root" -p "123" --port 27017 --authenticationDatabase "admin"
   	2.进入之后再验证
    	mongo
        use admin
        db.auth("root","123")
"""进入公司之后所有的数据库等都会有权限管理"""

数据准备

"""针对数据的主键值 不知道会默认创建知道了则使用指定的"""
#2、插入单条
user0={
    "name":"jason",
    "age":10,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'BJ'
    }
}

db.user.insert(user0)

#3、插入多条
user1={
    "_id":1,
    "name":"ax",
    "age":10,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'weifang'
    }
}

user2={
    "_id":2,
    "name":"wi",
    "age":20,
    'hobbies':['music','read','run'],
    'addr':{
        'country':'China',
        'city':'hebei'
    }
}

user3={
    "_id":3,
    "name":"yo",
    "age":30,
    'hobbies':['music','drink'],
    'addr':{
        'country':'China',
        'city':'heibei'
    }
}

user4={
    "_id":4,
    "name":"jg",
    "age":40,
    'hobbies':['music','read','dancing','tea'],
    'addr':{
        'country':'China',
        'city':'BJ'
    }
}

user5={
    "_id":5,
    "name":"jn",
    "age":50,
    'hobbies':['music','read',],
    'addr':{
        'country':'China',
        'city':'henan'
    }
}
db.user.insertMany([user1,user2,user3,user4,user5])

NoSQL诀窍

在不熟练的情况下 可以先写SQL语句 之后对比着拼接出NoSQL语句

查询

学习mongodb的查询语句只要对比着MySQL去学,非常的容易!

并且在书写mongodb查询语句的时候,我们可以先使用MySQL的SQL语句

然后参考SQL语句再书写mongodb语句(相当于将MySQL语句翻译成mongodb)

查询指定字段

# 1、select name,age from db1.user where id=3;
db.user.find(
    {'_id':3},
    {'_id':0,'name':1,'age':1}
)
'''0表示不要 1表示要'''
针对主键字段_id如果不指定默认是必拿的
普通字段不写就表示不拿

比较运算符

# SQL:=,!=,>,<,>=,<=
# MongoDB:{key:value}代表什么等于什么,"$ne","$gt","$lt","$gte","$lte"

#1、select * from db1.user where name = "jason";
db.user.find({'name':'jason'})

#2、select * from db1.user where name != "jason";
db.user.find({'name':{"$ne":'jason'}})

#3、select * from db1.user where id > 2;
db.user.find({'_id':{'$gt':2}})

#4、select * from db1.user where id < 3;
db.user.find({'_id':{'$lt':3}})

#5、select * from db1.user where id >= 2;
db.user.find({"_id":{"$gte":2,}})

#6、select * from db1.user where id <= 2;
db.user.find({"_id":{"$lte":2}})

逻辑运算符

# SQL:and,or,not
# MongoDB:字典中逗号分隔的多个条件是and关系"$or"的条件放到[]内 "$not"取反

#1、select * from db1.user where id >= 2 and id < 4;
db.user.find({'_id':{"$gte":2,"$lt":4}})

#2、select * from db1.user where id >= 2 and age < 40;
db.user.find({"_id":{"$gte":2},"age":{"$lt":40}})

#3、select * from db1.user where id >= 5 or name = "ax";
db.user.find({
    "$or":[
        {'_id':{"$gte":5}},
        {"name":"ax"}
        ]
})
"""取反操作了解一下即可"""
#4、select * from db1.user where id % 2=1;
db.user.find({'_id':{"$mod":[2,1]}})
#5、上题,取反
db.user.find({'_id':{"$not":{"$mod":[2,1]}}})

成员运算

# SQL:in,not in
# MongoDB:"$in","$nin"

#1、select * from db1.user where age in (20,30,31);
db.user.find({"age":{"$in":[20,30,31]}})

#2、select * from db1.user where name not in ('ax','yo');
db.user.find({"name":{"$nin":['ax','yo']}})

#3、select * from db1.user where age in (20,30,31) or name!='jason';
db.user.find({
    '$or':[
        {'age':{'$in':[20,30,31]}},
        {'name':{'$ne':'jason'}}
    ]
})

正则匹配

用一些符号的组合去文本中筛选出符合条件的数据
# SQL: regexp 正则
# MongoDB: /正则表达/i

#1、select * from db1.user where name regexp '^j.*?(g|n)$';
db.user.find({'name':/^j.*?(g|n)$/i})

范围/模糊查询

find({查询条件},{筛选字段})
"""
MySQL
	关键字	like
	关键符号
		%	匹配任意个数的任意字符
		_   匹配单个个数的任意字符
MongoDB:
	通过句点符
	$all
"""
#1、查看有dancing爱好的人
db.user.find({'hobbies':'dancing'})  # 默认就是范围查询

#2、查看既有dancing爱好又有tea爱好的人
db.user.find({
    'hobbies':{
        "$all":['dancing','tea']
        }
})

#3、查看第4个爱好为tea的人
db.user.find({"hobbies.3":'tea'})

#4、查看所有人最后两个爱好
db.user.find({},{'_id':0,'name':1,'hobbies':{"$slice":-2}})

#5、查看所有人前面两个爱好
db.user.find({},{'_id':0,'name':1,'hobbies':{"$slice":2}})

#6、查看所有人中间的第2个到第3个爱好
db.user.find({},{"_id":0,"name":1,'hobbies':{"$slice":[1,2]}})

排序

"""
MySQL:
	关键字  			order by
	升序 降序		    asc  desc
MongoDB
	关键字				sort
	升序 降序		    1	-1
"""
# 排序:1代表升序,-1代表降序
# select * from db.user order by age asc;
db.user.find().sort({"age":1})

# select * from db.user order by age desc,_id asc
db.user.find().sort({"age":-1,'_id':1})

分页(限制查询条数)

"""
MySQL	
	关键字		limit
	分页		 5,5
MongoDB	
	关键字		limit
	分页	     skip
"""
# 分页:limit代表取多少个document,skip代表跳过前多少个document 
# select * from db.user limit 2,1
db.user.find().sort({'age':1}).limit(1).skip(2)

杂项补充

# 获取数量
db.user.count({'age':{"$gt":30}}) 
--或者
db.user.find({'age':{"$gt":30}}).count()



#1、{'key':null} 匹配key的值为null或者没有这个key的数据
db.t2.insert({'a':10,'b':111})
db.t2.insert({'a':20})
db.t2.insert({'b':null})

> db.t2.find({"b":null})
{ "_id" : ObjectId("5a5cc2a7c1b4645aad959e5a"), "a" : 20 }
{ "_id" : ObjectId("5a5cc2a8c1b4645aad959e5b"), "b" : null }

#2、查找所有
db.user.find() #等同于db.user.find({})


#3、查找一个,与find用法一致,只是只取匹配成功的第一个
db.user.findOne({"_id":{"$gt":3}})

数据准备

from pymongo import MongoClient
import datetime

client=MongoClient('mongodb://root:123@localhost:27017')
table=client['db1']['emp']
# table.drop()

l=[
('jason','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
('ax','male',78,'20150302','teacher',1000000.31,401,1),
('wxx','male',81,'20130305','teacher',8300,401,1),
('yh','male',73,'20140701','teacher',3500,401,1),
('lz','male',28,'20121101','teacher',2100,401,1),
('jly','female',18,'20110211','teacher',9000,401,1),
('jx','male',18,'19000301','teacher',30000,401,1),
('成龙','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3)
]

for n,item in enumerate(l):
    d={
        "_id":n,
        'name':item[0],
        'sex':item[1],
        'age':item[2],
        'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'),
        'post':item[4],
        'salary':item[5]
    }
    table.save(d)

分组查询

# 1.按照部门分组
db.emp.aggregate({'$group':{'_id':'$post'}})

# 2.按照年龄分组
db.emp.aggregate({'$group':{'_id':'$age'}})

# 3.求每个部门的平均年龄
db.emp.aggregate({
    '$group':{
        '_id':'$post',
        '平均年龄':{'$avg':'$age'}
    }
                 })

# 4.求每个部门的最高薪资与最低薪资
db.emp.aggregate({
    '$group':{
        '_id':'$post',
        '最高薪资':{'$max':'$salary'},
        '最低薪资':{'$min':'$salary'}
    }
})

# 5.查询岗位名以及各岗位内的员工姓名
# SQL语句:select post,group_concat(name) from emp group by post;
db.emp.aggregate({
    "$group":{"_id":"$post","names":{"$push":"$name"}}
})

# 6.select * from db1.emp where id > 3 group by post;  
db.emp.aggregate(
    {"$match":{"_id":{"$gt":3}}},  # 分组之前筛选数据
    {"$group":{"_id":"$post"}}
)

# 7.select * from db1.emp where id > 3 group by post having avg(salary) > 10000;  
db.emp.aggregate(
    {"$match":{"_id":{"$gt":3}}},  # 出现在$group上面就是where
    {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}},
    {"$match":{"avg_salary":{"$gt":10000}}}  # 出现在$group下面就是having
)

1011爬取王者荣耀官网英雄资料中所有英雄的皮肤图片

import requests
import os
from lxml import etree
import time

# 判断文件夹存在
if not os.path.exists(r'wzry_skin'):
    os.mkdir(r'wzry_skin')

res = requests.get('https://pvp.qq.com/web201605/herolist.shtml')
# 字符编码
res.encoding = 'gbk'
# print(res.text)
tree = etree.HTML(res.text)
# 找有英雄的li标签
li_list = tree.xpath('//*[@class="herolist-box"]/div[2]/ul[1]/li')

for li in li_list:
    # 英雄对应的数字编号
    desc_link = li.xpath('./a/@href')[0].split('.')[0].split('/')[1]

    # 拼接链接
    res1 = requests.get('https://pvp.qq.com/web201605/' + li.xpath('./a/@href')[0])
    res1.encoding = 'gbk'
    tree1 = etree.HTML(res1.text)
    # 计数,确定有多少皮肤
    skin_num = tree1.xpath('.//ul[@class="pic-pf-list pic-pf-list3"]/@data-imgname')[0].count('&0')

    for num in range(1, skin_num + 1):
        url = 'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/%s/%s-bigskin-%s.jpg' % (
            desc_link, desc_link, num)
        name = tree1.xpath('.//ul[@class="pic-pf-list pic-pf-list3"]/@data-imgname')[0].split('|')[num - 1].strip(
            '&0')
        print(name)
        res2 = requests.get(url)
        img = res2.content
        file_path = os.path.join(r'wzry_skin', '%s.jpg' % name)
        with open(file_path, 'wb')as f:
            f.write(img)
        time.sleep(0.5)

1012内容概要

  • 数据分析的概念
  • 数据分析的工作流程
  • 数据分析三剑客简介
  • ipython模块
  • jupyter模块
  • Anaconda软件使用

1012内容详细

数据分析的概念

# 什么是数据分析
	就是从现有的数据中挖掘出价值
    
# 数据分析应用领域
	商品推荐
    	eg:在淘宝上搜索了一款产品之后 接下来就会疯狂给你推荐相关产品
    量化交易
    	股票 期货 等数据分析
    短视频推送
    	抖音 今日头条等短视频推荐
    ...
"""
数据分析绝对是未来所有公司不可或缺的岗位,目前社会上获取数据方式太多了,这么多的数据,只要我们拥有数据分析的技能,绝对可以应付任何岗位上的工作
"""

# 为什么数据分析需要学python
	python简单易学 并且是数据分析必备的语言

数据分析的工作流程

# 以下工作流程是一般情况下常见流程 也有可能会出现偏差
1.需求分析
	搞明白到底要分析什么数据 以什么方式分析 想要什么样的结果
    
2.数据采集
	数据的来源:
        1.公司内部自带
        	直接调用即可	MySQL MongoDB
        2.网络爬虫获取
        	需要编写代码	爬虫相关技能
        3.第三方服务
        	花钱直接购买	钞能力
         
3.数据清洗
	针对获取到的数据还需要校验是否符合分析条件
    	缺失数据 异常数据...
     
4.数据分析
	选择相应的计算公式 算法模型分析数据
  
5.生成数据分析报告
	攥写分析报告并给出分析之后的规律及建议
 
6.数据可视化
	将复杂的数据用图标的形式展示出来 便于查看相应规律
    数据可视化一般是结合数据分析报告一起

数据分析三剑客简介

numpy
	数学计算模块  该模块是很多计算模块的底层模块
pandas
	数据分析最为核心的模块之一 主要用于操作excel表格
    """
    既然excel软件可以非常轻松快捷的操作表格数据为什么还需要学pandas
    	当表格的数据低于10万行的时候采取excel软件操作方便
    	但是数据高于10万行之后使用excel软件就会出现卡顿不方便
   	所以pandas模块能够解决数据量较大的情况下的处理操作
    """
matplotlib
	数据可视化 

ipython模块

在cmd终端中可以编写python代码 但是存在以下缺陷
	1.代码没有提示
    2.代码不会自动缩进
    3.通篇一个颜色过于单调
 
在cmd中编写代码是否可以解决掉上面多个缺陷
	pip3 install ipython
    
打开cmd之后直接输入ipython进入全新的编程环境
	1.代码有提示
    2.代码自动缩进
    3.通篇颜色不单调

jupyter模块

pip3 install jupyter

命令行输入jupyter notebook即可
	会自动调用当前计算机默认的浏览器打开一个界面
	如果你调用了非默认浏览器访问地址需要输入一个token值 在启动服务的展示信息中含有
    打开的界面取决于终端输入jupyer notebook命令的左侧路径
 
右上方功能区域
	upload用于上传任意类型的文件
    new下拉框
    	python3用于创建notebook文件
        Text File用于创建文本文件
        Folder用于创建文件夹
        Terminal用于模拟cmd终端

notebook文件的后缀名是.ipynb 该文件无法以正常的双击直接打开
需要使用专门的notebook环境才可以打开并且查看内部的真实数据
	以后看到该类型的文件就使用jupyter notebook打开

"""
其实该模块就可以进行数据分析相关的工作 但是有一个非常大的缺陷
就是数据分析过程中需要使用到的其他模块都需要自己下载
	并且跟数据分析相关的模块不下于200个
"""

Anaconda软件

# 内部集成了很多数据分析相关软件及功能 并且自动下载了接近300个数据分析相关模块

去官网下载安装完成之后并不会在界面上生成图标 第一次需要自己搜索打开
	点击电脑左下方放大镜搜索anaconda navigator点击启动即可
    
左侧菜单栏
	Home
    	主要是一些已经准备好的软件 有直接可以使用和下载即可使用
    Environments
    	里面主要包含数据分析相关的模块
    Learning
    	里面含有大量的技术教程
    Community
    	里面含有大量技术交流平台

Jupyter Notebook详细操作

"""
主界面点击jupyter notebook之后无法呼起浏览器打开界面原因在于
	你的计算机名词含有中文
"""

单词
	cell	单元格
    cut		剪切
    copy	拷贝
    paste	粘贴
    above	在...上面
    below	在...下面
    replace 替换
    delete	删除
    undo	撤销
    split	切割
    merge	合并
  
命令行模式与编辑模式
	蓝色对应的是命令行模式、绿色对应的是编辑模式
     两种模式的切换
        编辑模式切换到命令行模式 按esc键
        命令行模式切换到编辑模块 鼠标左键点击即可
     
1.运行当前单元格
	ctrl+enter
2.运行当前单元格并选中下方的单元格
	shift+enter
3.如何书写md格式的标题
	方式1:命令行模式下按m键 之后按照警号个数书写几级标题执行即可
    方式2:编辑模式下先写文本 之后进入命令行模式按数字来控制几级标题
4.如何在当前单元格的下方新建一个单元格
	命令行模式下按b键
5.如何在当前单元格的上方新建一个单元格
	命令行模式下按a键
6.如何删除单元格
	命令行模式下连续按两下d键
7.如何撤销删除
	命令行模式下按z键

1013内容概要

科普

"""
很多编程语言对数字精确度不是很敏感 python亦是如此
	1234567890.0987654321
	1234567890.01

但是python又可以做人工智能 机器学习 量化交易 数据分析等高精确度的工作
内部其实就是通过相应的模块来实现
"""

主体:数据分析三剑客之numpy科学计算库

  • numpy简介
  • numpy前戏
  • numpy数据结构
  • numpy数据类型
  • numpy其他功能

1013内容详细

numpy简介

1.Numpy是高性能科学计算和数据分析的基础包
2.也是pandas等其他数据分析的工具的基础
3.NumPy具有多维数组功能,运算更加高效快速

下载模块
	在notebook中如果需要执行pip命令下载模块
    	只需要在命令行的开头加上一个感叹号即可
 			!pip3 install numpy
"""
在安装完anaconda之后该软件也会给我们提供一个下载模块的工具
	conda使用方式与pip一致
		conda install numpy
"""

导入模块
	import numpy
    import numpy as np  # 更加倾向于起别名 np

numpy前戏

"""
notebook单元格左侧如果是星号表示当前单元格正在执行 是数字表示执行完毕
"""
# 身高
height = [170,173,178,180,183]
# 体重
weight = [76,65,70,77,75]
'''求BMI指数:身体质量指数=体重(KG)/身高(m)的平方'''
BMI = weight/(height/100)**2  # 理想完美 现实报错


import random
# 伪造数据
h = []
w = []
for i in range(100000000):
    h.append(random.randint(153,180))
    w.append(random.uniform(51,88))
    
  
'''纯python代码实现'''
import time
# for循环计算
start_time = time.time()
for i in range(100000000):
    w[i]/(h[i]/100) ** 2
end_time = time.time() - start_time
end_time


'''numpy解决方案'''
import numpy as np
H = np.array(h)
W = np.array(w)
# 数组运算
start_time = time.time()
BMI = W/(H/100)**2
end_time = time.time() - start_time
end_time

多维数组

"""
numpy中同一个数组内所有数据数据类型肯定是一致的
	np.array([1,2,False]) >>> array([1, 2, 0])
	np.array([1,2,3.1]) >>> array([1.,2.,3.1])
numpy中进行数据操作的时候同一个数组内所有的数据都挨个对应参与操作
	a1 = np.array([1,2,3,4])
	a2 = np.array([7,8,9,1])
	a1 + a2 >>> array([ 8, 10, 12,  5])
	
	a1 * 10 >>> array([10, 20, 30, 40])
"""
# 一维数组
np.array([1,2,3,4])
# 二维数组(矩阵)
np.array([[1,2,3,4],[9,8,7,6]])

数据类型

布尔型	bool_	
整型	int_ int8 int16 int32 int64
	int32只能表示(-2**31,2**31-1),因为它只有32个位,只能表示2**32个数
无符号整型	uint8 uint16 uint32 uint64	
浮点型	float_ float16 float32 float64	
复数型	complex_ complex64 complex128
"""
1.为什么numpy数据类型以数字居多
	因为numpy主要用于科学计算 只有数字可以参与计算
2.为什么有些数据类型后面加下划线
	因为为了跟python数据类型关键字区分开
"""

常用属性

T			数组的转置(对高维数组而言)
  li1 = [
      [1,2,3],
      [4,5,6]
  ] 
  a = np.array(li1)
  a.T
  执行结果:
  array([[1, 4],
         [2, 5],
         [3, 6]])
  就相当于是将行变成列,列变成行,它也是一个比较常用的方法
dtype	数组元素的数据类型	
size	数组元素的个数	
ndim	数组的维数	
shape	数组的维度大小(以元组形式)

常用方法

"""如何查看某个方法的使用说明"""
	方式1:在方法后面跟问号执行即可
    方式2:写完方法名后先按shift不松开然后按tab即可(shift+tab)
      
array()	将列表转换为数组,可选择显式指定dtype	
arange()	range的numpy版,支持浮点数
	np.arange(1,10,2)
	np.arange(1.2,10,0.4)
linspace()	类似arange(),第三个参数为数组长度	
	np.linspace(1,10,20)
  # 这个方法与arange有一些区别,arange是顾头不顾尾,而这个方法是顾头又顾尾,在1到10之间生成的二十个数每个数字之间的距离相等的,前后两个数做减法肯定相等
zeros()	根据指定形状和dtype创建全0数组	
	np.zeros((3,4))
ones()	根据指定形状和dtype创建全1数组	
	np.ones((3,4))
empty()	根据指定形状和dtype创建空数组(随机值)	
	np.empty(10)
eye()	根据指定边长和dtype创建单位矩阵
	np.eye(5)

索引与切片

1.针对一维数组 索引与切片操作跟python中的列表完全一致

2.花式索引(间断索引)
	age[[0,2,5]] 
3.布尔值索引(逻辑索引)
	age[age>15]

4.针对二维数组索引与切片有些许复杂
	res[行索引(切片),列索引(切片)]
    如果需要获取二维数组的所有行或列元素,那么,对应的行索引或列索引需要用英文 状态的冒号表示
    
array([[  1,   3,   5,   7],
       [  2,   4,   6,   8],
       [ 11,  13,  15,  17],
       [ 12,  14,  16,  18],
       [100, 101, 102, 103]])
arr1[3,3]  # 18
arr1[3,:]  # array([12, 14, 16, 18])
arr1[:,1]  # array([  3,   4,  13,  14, 101])
arr1[0:2,1:3]  # array([[3,5],[4,6]])

运算符

# 数学运算符
	+
		数组对应元素的加和
  -
  	数组对应元素的差
  *
  	数组对应元素的乘积
  /
  	数组对应元素的商
  %
  	数组对应元素商的余数
  //
  	数组对应元素商的整除数
  ** 
  	数组对应元素的幂指数
    
# 比较运算符
	>
		等价np.greater(arr1,arr2)
		判断arr1的元素是否大于arr2的元素
	>=
		等价np.greater_equal(arr1,arr2)
		判断arr1的元素是否大于等于arr2的元素
	<
		等价np.less(arr1,arr2)
		判断arr1的元素是否小于arr2的元素
	<=
		等价np.less_equal(arr1,arr2)
		判断arr1的元素是否小于等于arr2的元素
	==
		等价np.equal(arr1,arr2)
		判断arr1的元素是否等于arr2的元素
	!=
		等价np.not_equal(arr1,arr2)
		判断arr1的元素是否不等于arr2的元素

函数

# 常用的数学函数
	np.round(arr)
		对各元素四舍五入
  np.sqrt(arr)
  	计算各元素的算术平方根  
  np.square(arr)
  	计算各元素的平方值
  np.exp(arr)
  	计算以e为底的指数
  np.power(arr, α)
  	计算各元素的指数
  np.log2(arr)
  	计算以2为底各元素的对数
  np.log10(arr)
  	计算以10为底各元素的对数
  np.log(arr)
  	计算以e为底各元素的对数
    
# 常用的统计函数(必会)
	np.min(arr,axis)
  	按照轴的方向计算最小值
  np.max(arr,axis)
  	按照轴的方向计算最大值
  np.mean(arr,axis)
  	按照轴的方向计算平均值
  np.median(arr,axis )
  	按照轴的方向计算中位数
  np.sum(arr,axis)
  	按照轴的方向计算和
  np.std(arr,axis)
  	按照轴的方向计算标准差
  np.var(arr,axis)
  	按照轴的方向计算方差
  '''
  注意:
  	axis=0时,计算数组各列的统计值 
  	axis=1时,计算数组各行的统计值
  '''
array([[ 80.5, 60., 40.1, 20., 90.7],
       [ 10.5, 30., 50.4, 70.3, 90.],
       [ 35.2, 35., 39.8, 39., 31.],
       [91.2, 83.4, 85.6, 67.8, 99.]])
'''不使用axis参数'''
# 计算每一行的和
Sum = []
for row in range(4):
    Sum.append(np.sum(arr2[row,:]))
# 计算每一列的平均
Avg = []
for col in range(5):
    Avg.append(np.mean(arr2[:,col]))
    
'''使用axis参数'''
arr2.sum(axis = 1)  # 等价np.sum(arr2, axis = 1)
np.mean(arr2, axis = 0)  # 等价arr2.mean(axis = 0)

随机数

numpy中的random子模块
np.random

rand	给定形状产生随机数组(0到1之间的数)	
randint	给定形状产生随机整数	
choice	给定形状产生随机选择	
shuffle	与random.shuffle相同	
uniform	给定形状产生随机数组(随机均匀分布)
normal  随机正态分布


小练习

1.计算数组每一行和每一列的中位数(不能使用axis参数)
	array([
       [ 80.5, 60., 40.1, 20., 90.7],
       [ 10.5, 30., 50.4, 70.3, 90.],
       [ 35.2, 35., 39.8, 39., 31.],
       [91.2, 83.4, 85.6, 67.8, 99.]
    ])
	
    # 每一行均值
    for i in res:
        print('每一行>>>:',i)
        print('均值>>>:',np.average(i))
    # 每一列均值
    for i in range(res.shape[1]):
        print('每一列>>>:',res[:,i])
        print('最小值>>>:',np.min(res[:,i]))
2.jason有10000块钱,去某赌场嗨皮
假设输赢概率都是50%,并且赢一场赚100,输一场亏100
jason总共玩了1500场,写程序计算1500场之后jason还剩多少钱
	"""统计jason每一次赌完后账户总额"""
    # 先定义一个变量存储jason的本金
    money = 10000
    # 再定义一个存储每次赌局之后账户金额的变量
    package = []
    # 先将jason初始的本金添加进来
    package.append(money)
    # 利用for循环模拟1500次赌局
    for i in range(1500):
        # 先判断输赢
        is_right = np.random.choice([1,0])  # 1表示赢 0表示输
        # 判断赢则账户加100
        if is_right:
            money += 100
        # 判断输则账户减100
        else:
            money -= 100
        # 每次循环结束之后都将结构添加到列表中
        package.append(money)
    # 循环结束即1500场完成
    # print(money)
    # print('记录',package)
    # 可视化作图(后期会讲)
    import matplotlib.pyplot as plt
    plt.plot(range(1501),package)  # x轴与y轴坐标数据
    plt.show()

1014内容概要

主体内容:pandas模块(非常重要)

  • pandas模块简介

  • pandas两大数据结构

    Series(过渡)
    DataFrame(核心)
    
  • 两大数据结构详细方法

1014内容详细

pandas模块简介

基于Numpy构建
pandas的出现,让Python语言成为使用最广泛而且最强大的数据分析语言
pandas针对表格文件的操作有非常大的优势
	尤其是数据量超过10万的


pandas的主要功能
	- 具备诸多功能的两大数据结构
  	Series、DataFrame
    都是基于Numpy构建出来的
		公司中使用频繁的是DataFrame,而Series是构成DataFrame的基础,即一个DataFrame可能由N个Series构成
	- 集成时间序列功能
	- 提供丰富的数学运算和操作(基于Numpy)
	- 灵活处理缺失数据
    
# python纯开发环境下
pip3 install pandas
# anaconda环境下
conda install pandas
'''anaconda已经自动帮助我们下载好了数据分析相关的模块,其实无需我们再下载'''

# 导入
import pandas
import pandas as pd  # 更加习惯给它起一个别名pd

补充

数据分析三剑客模块由于使用频率很高 所以在很多ipynb文件的开头都会提前导入
import numpy as np
import pandas as pd
...

数据类型之Series

# 是一种类似于一维数组对象,由数据和相关的标签(索引)组成
第一种:
pd.Series([4,5,6,7,8])  

第二种:
pd.Series([4,5,6,7,8],index=['a','b','c','d','e'])

第三种:
pd.Series({"a":1,"b":2})

第四种:
pd.Series(0,index=['a','b','c'])

缺失数据概念

在数据处理中如果遇到NaN关键字那么意思就是缺失数据
并且NaN属于浮点型

dropna()  # 过滤掉值为NaN的行
fillna()  # 填充缺失数据
isnull()  # 返回布尔数组
notnull()  # 返回布尔数组

数据修改规则

"""
如何判断当前数据是否改变
	1.如果执行操作之后有结果说明原数据没有变
		obj1.fillna(666)
	2.如果执行操作之后没有结果说明原数据改变
		obj1.fillna(666,inplace=True)
		inplace=True该参数很多方法都有 意思就是直接改变原数据
"""

布尔值索引

# 布尔值索引的本质就是按照对应关系筛选出True对应的数据
mask = pd.Series([True,False,False,True,False])
price = pd.Series([321312,123,324,5654,645])
price[mask]
price|mask
(price>200) & (price<900)
price[(price>200) & (price<900)]  # 布尔求值

"""
针对&符号链接的条件都必须要加括号
"""

行索引\行标签

sr1.iloc[0]  # 以行索引取值
sr1.loc['a']   # 以行标签取值

1015内容概要

主体:将pandas模块结束

  • Series数据操作
  • 基本算术方法
  • 核心数据结构之DataFrame
  • 如何读取外部数据
  • DataFrame一系列操作

1015内容详细

Series数据操作

res = pd.Series([111,222,333,444])
# 增
res['a'] = 123
# 查
res.loc[1]
# 改
res[0] = 1
# 删
del res[0]

算术运算符

"""
add		加(add)
sub		减(substract)
div		除(divide)
mul		乘(multiple)
"""
sr1 = pd.Series([12,23,34], index=['c','a','d'])
sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
sr1.add(sr3,fill_value=0)

DataFrame创建方式

表格型数据结构,相当于一个二维数组,含有一组有序的列也可以看作是由Series组成的共用一个索引的字典

第一种:
res = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
第二种:
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
第三种:
pd.DataFrame(np.array([[10,20],[30,40]]),index=['a','b'],columns=['c1','c2'])
更多
pd.DataFrame([np.arange(1,8),np.arange(11,18)])
s1 = pd.Series(np.arange(1,9,2))
s2 = pd.Series(np.arange(2,10,2))
s3 = pd.Series(np.arange(5,7),index=[1,2])
df5 = pd.DataFrame({'c1':s1,'c2':s2,'c3':s3})

"""
以上创建方式都仅仅做一个了解即可
因为工作中dataframe的数据一般都是来自于读取外部文件数据,而不是自己手动去创建
"""

常见属性

1.index    行索引
2.columns  列索引
3.T		   转置
4.values   值索引
5.describe 快速统计

DataFrame数据类型补充

# 在DataFrame中所有的字符类型数据在查看数据类型的时候都表示成object

读取外部数据

pd.read_csv()  # 可以读取文本文件和.csv结尾的文件数据
pd.read_excel()  # 可以读取excel表格文件数据
pd.read_sql()  # 可以读取MySQL表格数据
pd.read_html()  # 可以读取页面上table标签内所有的数据

文本文件读取

pd.read_csv(filepath_or_buffer, sep=',', header='infer', names=None, usecols=None, skiprows=None, skipfooter=None, converters=None, encoding=None)
            
filepath_or_buffer:指定txt文件或csv文件所在的具体路径 
sep:指定原数据集中各字段之间的分隔符,默认为逗号”,” 
      	id	name	income
        1   jason	 10
header:是否需要将原数据集中的第一行作为表头,默认将第一行用作字段名称 
        如果原始数据没有表头需要将该参数设置为None 
names:如果原数据集中没有字段,可以通过该参数在数据读取时给数据框添加具体的表头 
usecols:指定需要读取原数据集中的哪些变量名 
skiprows:数据读取时,指定需要跳过原数据集开头的行数
         有一些表格开头是有几行文字说明的,读取的时候应该跳过
skipfooter:数据读取时,指定需要跳过原数据集末尾的行数 
converters:用于数据类型的转换(以字典的形式指定) 
encoding:如果文件中含有中文,有时需要指定字符编码

基本使用

import pandas as pd
data01 = pd.read_csv(r'data_test01.txt',
           skiprows = 2,  # python能自动过滤掉完全无内容的空行(写2、3都行)
           sep = ',',  # 默认就是逗号 写不写都行 
           skipfooter = 3, 
           )
# 1.针对id原本是01、02自动变成了1、2...
converters = {'id':str}
# 2.点击文件另存修改文件编码之后再次读取出现乱码
encoding='utf-8'
# 3.移除收入千分位非逗号的其他符号
thousands = '&'
# 4.手动将文件表头行删除再次读取
header = None  # 默认用索引
names = ['id','year','month','day','gender','occupation','income']
# 5.指定读取的字段
usecols = ['id','income']

"""
查看方法帮助
方式1
	方法名?
方式2
	光标停留在方法名左括号后面
	先按住shift键不松开,再按tab键(没反应就多按几次)
"""

excel表格读取

pd.read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0, index_col=None, names=None,
na_values=None, thousands=None, convert_float=True)

io:指定电子表格的具体路径 
sheet—name:指定需要读取电子表格中的第几个Sheet,既可以传递整数也可以传递具体的Sheet名称 
header:是否需要将数据集的第一行用作表头,默认为是需要的 
skiprows:读取数据时,指定跳过的开始行数
skip_footer:读取数据时,指定跳过的末尾行数 
index_col:指定哪些列用作数据框的行索引(标签)
na_values:指定原始数据中哪些特殊值代表了缺失值 
thousands:指定原始数据集中的千分位符 
convert_float:默认将所有的数值型字段转换为浮点型字段 
converters:通过字典的形式,指定某些列需要转换的形式

pd.read_excel(r'data_test02.xlsx',
             header = None,
              names = ['ID','Product','Color','Size'], 
             converters = {'ID':str}
             )

数据库数据读取

# 在anaconda环境下直接安装
# pymysql模块
import pymysql
conn = pymysql.connect(host,port,user,password, database, charset)

host:指定需要访问的MySQL服务器
port:指定访问MySQL数据库的端口号 charset:指定读取MySQL数据库的字符集,如果数据库表中含有中文,一般可以尝试将该参数设置为 “utf8”或“gbk”
user:指定访问MySQL数据库的用户名
password:指定访问MySQL数据库的密码
database:指定访问MySQL数据库的具体库名
  
# 利用pymysql创建好链接MySQL的链接之后即可通过该链接操作MySQL
pd.read_sql('select * from user', con = conn)
conn.close()  # 关闭链接

网页表格数据读取

pd.read_html(r'https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin')

数据概览

df.columns  # 查看列 
df.index  	# 查看行
df.shape	# 行列 
df.dtypes  	# 数据类型 
df.head()  	# 取头部多条数据
df.tail()  	# 取尾部多条数据

行列操作

df['列字段名词']  # 获取指定列对应的数据

df.rename(column={'旧列名称':'新列名称'})

# 创建新的列
df['新列名称']=df.列名称/(df.列名称1+df.列名称2)

# 自定义位置
df.insert(3,'新列名称',新数据)

# 添加行
df3 = df1.append(df2)

数据筛选

# 获取指定列数据
df['列名']  # 单列数据
df[['列名1','列名2',...]]  # 多列数据

# 获取指定行数据
sec_buildings.loc[sec_buildings["region"] == '浦东']

sec_buildings.loc[(sec_buildings["region"] == '浦东') & (sec_buildings['size'] > 150),]

sec_buildings.loc[(sec_buildings["region"] == '浦东') & (sec_buildings['size'] > 150),['name','tot_amt','price_unit']]

数据处理

sec_car = pd.read_csv(r'sec_cars.csv')
sec_car.head()
sec_car.dtypes
sec_car.Boarding_time = pd.to_datetime(sec_car.Boarding_time, format = '%Y年%m月')


sec_car.New_price = sec_car.New_price.str[:-1].astype(float)

posted @ 2021-10-18 09:25  wddwyw  阅读(4)  评论(0编辑  收藏  举报