from bs4 import BeautifulSoup,element
# 导入 BeautifulSoup
import lxml
import requests
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc,'lxml') #创建 beautifulsoup 对象
soup1 = BeautifulSoup(open('index.html'))
soup.prettify()#打印 soup 对象的内容,格式化输出
# Beautiful Soup 所有对象可以归纳为4种:
# • Tag
# • NavigableString
# • BeautifulSoup
# • Comment
soup.title # 获取标题信息
soup.head # 获取头
soup.a # 获取第一个 a 链接
soup.p # 获取第一个 p 段落
soup.name
soup.a.attrs # 第一个a标签的属性
soup.p.attrs
soup.a.get('href') # 单独获取某一个属性
soup.a['href']
soup.a['href'] = 'https://www.cnblogs.com/hany-postq473111315/'
# 对属性进行修改
del soup.a['href'] # 删除属性
soup.p.string # 使用 string 获取内容
soup.a.string # 输出 a 的内容
'''
.string 输出的内容,已经把注释符号去掉了,可能会带来麻烦
'''
print(type(soup.a.string))
if type(soup.a.string)==element.Comment:
print(soup.a.string)
soup
soup.head.contents # 将tag的子节点以列表的方式输出
soup.head.contents[0] # 列表方式取值
soup.head.children # list 生成器对象
for item in soup.head.children:
print(item)
# 通过循环输出
'''
.contents 和 .children 属性仅包含tag的直接子节点,
.descendants 属性可以对所有tag的子孙节点进行递归循环
'''
for item in soup.descendants:
print(item)
soup.head.string # 查看内容
soup.title.string
soup.strings
for string in soup.strings:
# soup.strings 为 soup 内的所有内容
print(string)
# 使用 .stripped_strings 可以去除多余空白内容
for string in soup.stripped_strings:
print(string)
soup
soup.p.parent.name # 父标签的名称
soup.head.title.string.parent.name
'''
通过元素的 .parents 属性可以递归得到元素的所有父辈节点
'''
for parent in soup.head.title.string.parents:
# print(parent)
print(parent.name)
'''
.next_sibling 属性获取了该节点的下一个兄弟节点,
.previous_sibling 属性获取了该节点的上一个兄弟节点,
如果节点不存在,则返回 None
注:
因为空白或者换行也可以被视作一个节点,
所以得到的结果可能是空白或者换行。
'''
soup.p.next_sibling
soup.p.previous_sibling
soup.p.next_sibling.next_sibling
'''
.next_siblings 和 .previous_siblings
可以对当前节点的兄弟节点迭代
'''
for sibling in soup.a.next_siblings:
print(sibling)
soup.head.next_element # 后一个节点
soup.head.previous_element # 前一个节点
'''
通过 .next_elements 和 .previous_elements 的迭代器
可以向前或向后访问文档的解析内容
'''
for element in soup.a.next_elements:
print(element)
'''
find_all() 方法搜索当前tag的所有tag子节点,
并判断是否符合过滤器的条件
'''
soup.find_all('b')
import re
for tag in soup.find_all(re.compile('^b')):
# 通过传入正则表达式,进行查找
print(tag)
print(tag.name)
soup.find_all(['a','b'])
# 传递列表,查找元素
soup.find_all(['a','b'])[2]['href']
# 查找指定元素
for tag in soup.find_all(True):
# 查找所有的 tag,不会返回字符串节点
print(tag.name)
# 传递方法
def has_href(tag):
# 如果存在就返回 True
return tag.has_attr('href')
soup.find_all(has_href)
soup.find_all(id = 'link2')
# 寻找指定的属性值
soup.find_all(href = re.compile('tillie'))
# 使用多个指定名字的参数可以同时过滤tag的多个属性
soup.find_all(href=re.compile("tillie"), id='link3')
# class_ 代替 class 进行查找
soup.find_all('a',class_ = 'sister')
'''
通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag
'''
data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
data_soup.find_all(attrs = {'data-foo':'value'})
# attrs = {'data-foo':'value'} 进行筛选
'''
通过 text 参数可以搜索文档中的字符串内容
text 参数接受 字符串 , 正则表达式 , 列表, True
'''
soup.find_all(text=["Tillie", "Elsie", "Lacie"])
soup.find_all(text="Tillie")
soup.find_all(text=re.compile("Dormouse"))
# 使用 limit 参数限制返回结果的数量
soup.find_all('a',limit = 2)
'''
调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点
如果只想搜索tag的直接子节点,可以使用参数 recursive=False
'''
soup.html.find_all('title',recursive=False)
soup.html.find_all('title',recursive=True)
'''
CSS选择器
标签名不加任何修饰,类名前加点,id名前加 #
'''
soup.select('title')
soup.select('a')
soup.select('.sister')
# 通过类名查找
soup.select('#link2')
'''
查找 p 标签中,id 等于 link1的内容,二者需要用空格分开
一定注意是 p 标签下的
'''
soup.select("p #link1")
soup.select('head > title')
soup.select('a[class="sister"]')
# 查找时还可以加入属性元素,属性需要用中括号括起来
'''
select 选择后,使用 get_text() 方法获取内容
'''
soup.select('title')
soup.select('title')[0].get_text()
soup.select('title')[0].string
for title in soup.select('p .sister'):
print(title.get_text())
# 导入 jieba
import jieba
import jieba.posseg as pseg #词性标注
import jieba.analyse as anls #关键词提取
seg_list = jieba.cut("他来到上海交通大学", cut_all=True)
print("【全模式】:" + "/ ".join(seg_list))
print(type(seg_list))
# 精确模式
seg_list = jieba.cut("他来到上海交通大学", cut_all=False)
print("【精确模式】:" + "/ ".join(seg_list))
print(type(seg_list))
# 搜索引擎模式
seg_list = jieba.cut_for_search("他毕业于上海交通大学机电系,后来在一机部上海电器科学研究所工作")
print("【搜索引擎模式】:" + "/ ".join(seg_list))
# 返回列表
seg_list = jieba.lcut("他来到上海交通大学", cut_all=True)
print("【返回列表】:{0}".format(seg_list))
# 返回列表
seg_list = jieba.lcut_for_search("他毕业于上海交通大学机电系,后来在一机部上海电器科学研究所工作")
print("【返回列表】:{0}".format(seg_list))
# 未启用 HMM
seg_list = jieba.cut("他来到了网易杭研大厦", HMM=False) #默认精确模式和启用 HMM
print("【未启用 HMM】:" + "/ ".join(seg_list))
# 识别新词
seg_list = jieba.cut("他来到了网易杭研大厦") #默认精确模式和启用 HMM
print("【识别新词】:" + "/ ".join(seg_list))
# 繁体字文本
ft_text = """人生易老天難老 歲歲重陽 今又重陽 戰地黃花分外香 壹年壹度秋風勁 不似春光 勝似春光 寥廓江天萬裏霜 """
# 全模式
print("【全模式】:" + "/ ".join(jieba.cut(ft_text, cut_all=True)))
# 精确模式
print("【精确模式】:" + "/ ".join(jieba.cut(ft_text, cut_all=False)))
# 搜索引擎模式
print("【搜索引擎模式】:" + "/ ".join(jieba.cut_for_search(ft_text)))
# 示例文本
sample_text = "周大福是创新办主任也是云计算方面的专家"
# 未加载词典
print("【未加载词典】:" + '/ '.join(jieba.cut(sample_text)))
# 载入词典
jieba.load_userdict("userdict.txt")
# 加载词典后
print("【加载词典后】:" + '/ '.join(jieba.cut(sample_text)))
jieba.add_word('石墨烯') #增加自定义词语
jieba.add_word('凱特琳', freq=42, tag='nz') #设置词频和词性
jieba.del_word('自定义词') #删除自定义词语
# 调节词频前
print("【调节词频前】:" + '/'.join(jieba.cut('如果放到post中将出错。', HMM=False)))
# 调节词频
jieba.suggest_freq(('中', '将'), True)
# 调节词频后
print("【调节词频后】:" + '/'.join(jieba.cut('如果放到post中将出错。', HMM=False)))
s = "此外,公司拟对全资子公司吉林欧亚置业有限公司增资4.3亿元,增资后,吉林欧亚置业注册资本由7000万元增加到5亿元。吉林欧亚置业主要经营范围为房地产开发及百货零售等业务。目前在建吉林欧亚城市商业综合体项目。2013年,实现营业收入0万元,实现净利润-139.13万元。"
for x, w in anls.extract_tags(s, topK=20, withWeight=True):
print('%s %s' % (x, w))
for x, w in anls.textrank(s, withWeight=True):
print('%s %s' % (x, w))
# jieba.analyse.set_stop_words("stop_words.txt")
# jieba.analyse.set_idf_path("idf.txt.big");
# for x, w in anls.extract_tags(s, topK=20, withWeight=True):
# print('%s %s' % (x, w))
words = pseg.cut("他改变了中国")
for word, flag in words:
print("{0} {1}".format(word, flag))
# jieba.enable_parallel(4):开启并行分词模式,参数为并行进程数
# jieba.disable_parallel() :关闭并行分词模式
result = jieba.tokenize(u'上海益民食品一厂有限公司')
print("【普通模式】")
for tk in result:
print("word: {0} start: {1} end: {2}".format(tk[0],tk[1],tk[2]))
result = jieba.tokenize(u'上海益民食品一厂有限公司', mode='search')
print("【搜索模式】")
for tk in result:
print("word: {0} start: {1} end: {2}".format(tk[0],tk[1],tk[2]))
# 网址: https://www.jianshu.com/p/883c2171cdb5
'''
进行分词使用 :
jieba.cut
jieba.cut_for_search
jieba.lcut
jieba.lcut_for_search
jieba.cut 和 jieba.lcut 参数
需要分词的字符串
cut_all 参数:是否使用全模式,默认值为 False
HMM 参数:用来控制是否使用 HMM 模型,默认值为 True
HMM 模型,即隐马尔可夫模型(Hidden Markov Model, HMM),
是一种基于概率的统计分析模型,用来描述一个系统隐性状态的转移和隐性状态的表现概率。
其大致原理是:
采用四个隐含状态,分别表示为单字成词,词组的开头,词组的中间,词组的结尾。
通过标注好的分词训练集,可以得到 HMM 的各个参数,
然后使用 Viterbi 算法来解释测试集,得到分词结果。
开发者可以指定自定义词典,以便包含 jieba 词库里没有的词
词语 词频(可省略) 词性(可省略)
使用 jieba.load_userdict(file_name) 载入词典。
使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中动态修改词典。
使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。
通过 jieba.analyse.extract_tags 方法可以基于 TF-IDF 算法进行关键词提取,
该方法共有 4 个参数:
sentence:为待提取的文本
topK:为返回几个 TF/IDF 权重最大的关键词,默认值为 20
withWeight:是否一并返回关键词权重值,默认值为 False
allowPOS:仅包括指定词性的词,默认值为空
使用 jieba.analyse.TFIDF(idf_path=None) 可以新建 TFIDF 实例,
其中 idf_path 为 IDF 频率文件
通过 jieba.analyse.textrank 方法可以使用基于 TextRank 算法的关键词提取,
使用 jieba.analyse.TextRank() 可以新建自定义 TextRank 实例
jieba.posseg.POSTokenizer(tokenizer=None) 新建自定义分词器,
tokenizer 参数可指定内部使用的 jieba.Tokenizer 分词器。
jieba.posseg.dt 为默认词性标注分词器。
jieba.enable_parallel(4):开启并行分词模式,参数为并行进程数
jieba.disable_parallel() :关闭并行分词模式
使用 jieba.tokenize 方法可以返回词语在原文的起止位置。
mode='search' 表示搜索模式
'''
网址: 'https://www.jianshu.com/p/883c2171cdb5'
import lxml
lxml_roles = '''
标签名 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
* 通配符,选择所有元素节点与元素名
@* 选取所有属性
[@attrib] 选取具有给定属性的所有元素
[@attrib='value'] 选取给定属性具有给定值的所有元素
[tag] 选取所有具有指定元素的直接子节点
[tag='text'] 选取所有具有指定元素并且文本内容是 text 节点
'''
from lxml import etree
text='''
<div>
<ul>
<li class="item-0"><a href="link1.html">第一个</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-0"><a href="link5.html">a属性</a>
</ul>
</div>
'''
html = etree.HTML(text)
# html -> <Element html at 0x207bc230e08>
etree.tostring(html,encoding='utf-8').decode('utf-8')
# etree.tostring 解析成字节
etree.tostringlist(html)
# 解析成列表
html.xpath('//li/a')
# li 标签下的 a 标签
html.xpath('//li/a') [0].text
html.xpath('//li[@class="item-1"]')
# li 标签下 class 属性为 item-1 的
# 使用 text 获取节点的文本
html.xpath('//li[@class="item-1"]/a/text()')
# 获取a节点下的内容
from lxml import etree
from lxml.etree import HTMLParser
text='''
<div>
<ul>
<li class="item-0"><a href="link1.html">第一个</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
</ul>
</div>
'''
html = etree.HTML(text,etree.HTMLParser())
html.xpath('//a[@href="link2.html"]/../@class')
# .. 父节点 , @ 取属性
html.xpath('//a[@href="link2.html"]/parent::*/@class')
# 使用 parent::* 来获取父节点
html.xpath('//li//text()')
#获取li下所有子孙节点的内容
# 使用 @ 符号即可获取节点的属性
html.xpath('//li/a/@href')
text1='''
<div>
<ul>
<li class="aaa item-0"><a href="link1.html">第一个</a></li>
<li class="bbb item-1"><a href="link2.html">second item</a></li>
</ul>
</div>
'''
html=etree.HTML(text1,etree.HTMLParser())
# 使用 contains(属性,值) 进行获取
html.xpath('//li[contains(@class,"aaa")]/a/text()')
text1='''
<div>
<ul>
<li class="aaa" name="item"><a href="link1.html">第一个</a></li>
<li class="aaa" name="fore"><a href="link2.html">second item</a></li>
</ul>
</div>
'''
html = etree.HTML(text1,etree.HTMLParser())
html.xpath('//li[@class="aaa" and @name="fore"]/a/text()')
html.xpath('//li[contains(@class,"aaa") and contains(@name,"fore")]/a/text()')
html.xpath('//li[contains(@class,"aaa") and @name="fore"]/a/text()')
lxml_operators = '''
or 或
and 与
mod 取余
| 取两个节点的集合
+ 加 , - 减 , * 乘 , div 除
= 等于 , != 不等于 , < 小于
<= 小于或等于 , > 大于 , >= 大于或等于
'''
# 利用中括号引入索引的方法获取特定次序的节点
text1='''
<div>
<ul>
<li class="aaa" name="item"><a href="link1.html">第一个</a></li>
<li class="aaa" name="item"><a href="link1.html">第二个</a></li>
<li class="aaa" name="item"><a href="link1.html">第三个</a></li>
<li class="aaa" name="item"><a href="link1.html">第四个</a></li>
</ul>
</div>
'''
html = etree.HTML(text1,etree.HTMLParser())
#获取所有 li 节点下 a 节点的内容
html.xpath('//li[contains(@class,"aaa")]/a/text()')
#获取第一个
html.xpath('//li[1][contains(@class,"aaa")]/a/text()')
#获取最后一个
html.xpath('//li[last()][contains(@class,"aaa")]/a/text()')
#获取第三个
html.xpath('//li[position()>2 and position()<4][contains(@class,"aaa")]/a/text()')
#获取倒数第三个
html.xpath('//li[last()-2][contains(@class,"aaa")]/a/text()')
#获取所有祖先节点
html.xpath('//li[1]/ancestor::*')
# 获取 div 祖先节点
html.xpath('//li[1]/ancestor::div')
# 获取所有属性值
html.xpath('//li[1]/attribute::*')
# 获取所有直接子节点
html.xpath('//li[1]/child::*')
# 获取所有子孙节点的 a 节点
html.xpath('//li[1]/descendant::a')
# 获取当前子节点之后的所有节点
html.xpath('//li[1]/following::*')
# 获取当前节点的所有同级节点
html.xpath('//li[1]/following-sibling::*')
import math
# 返回数字的绝对值
math.fabs(-10)
# 返回数字的上入整数
math.ceil(4.1)
math.ceil(-3.2)
# 返回 e 的 x 次幂
math.exp(1)
# 返回数字的下舍整数
math.floor(4.9)
math.floor(-5.6)
# 以 e 为基数
math.log(math.e)
# 以 2 为基数
math.log(8,2)
# 以 10 为基数
math.log10(100)
# 返回 x 的 (小数部分,整数部分)
math.modf(5.75)
math.modf(-5.75)
# x ** y , x 的 y 次幂
math.pow(2,3)
math.pow(2,-3)
# 返回数字 x 的平方根
math.sqrt(16)
math.sqrt(0)
# 返回 x 的反余弦弧度值
math.acos(1)
# 返回 x 的反正切弧度值
math.atan(1)
# math.atan2(y,x)
# 返回给定的 X 及 Y 坐标值的反正切值
math.atan2(4,3)
# 返回 x 的弧度的余弦值
math.cos(0)
# 返回欧几里德范数 sqrt(x*x + y*y)
math.hypot(3, 4)
# 返回的 x 弧度的正弦值
math.sin(math.pi/2)
# 返回 x 弧度的正切值
math.tan(math.pi/2)
# 将弧度转换为角度
math.degrees(math.pi/2)
# 将角度转换为弧度
math.radians(90)
math.pi
math.e
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif']=['SimHei']
#用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False
#用来正常显示负号
df = pd.read_excel('超市营业额.xlsx')
df.head()
# 折线图
plot_params = '''
参数 接收值 说明 默认值
x,y array 表示 x 轴与 y 轴对应的数据; 无
color string 表示折线的颜色; None
marker string 表示折线上数据点处的类型; None
linestyle string 表示折线的类型; -
linewidth 数值 线条粗细: linewidth=1.=5.=0.3 1
alpha 0~1之间的小数 表示点的透明度; None
label string 数据图例内容: label=‘实际数据’ None
'''
x = df['姓名'].head()
y = df['交易额'].head()
# x,y 的值
plt.title('员工和营业额之间的折线图')
# 设置标题
plt.plot(x, y, color='blue',marker='*',linestyle = '-',
linewidth = 0.8,alpha = 0.6,label='营业额')
# 折线图参数
plt.legend()
# 显示图例
plt.xlabel('员工姓名')
# 设置 x 轴标题
plt.xticks(rotation = 45)
# x 轴的字体倾斜
plt.ylabel('营业额(元)')
# 设置 y 轴
# 柱状图
bar_params = '''
参数 说明 类型
x,y x坐标,y坐标 int,float
width 宽度 0~1, 默认0.8
alpha 透明度 0~1之间的小数
bottom 条形的起始位置 也是y轴的起始坐标 , 整数
align 条形的中心位置 "center","lege"边缘
edgecolor 边框颜色
linewidth 边框宽度
color 条形的颜色 "r","b","g","#123465",默认"b"
'c', 'r', 'g', 'k', 'y', 'm', 'b'
'''
x = df['姓名'].head()
y = df['交易额'].head()
# x,y 的值
plt.title('员工和营业额之间的柱状图')
# 设置标题
plt.bar(x, y,width = 0.3,bottom = 100,align = 'center',
edgecolor = 'y',linewidth = 3,color = ['c','r','g','k','y'],
label='营业额')
# 柱状图参数
plt.legend()
# 显示图例
plt.xlabel('员工姓名')
# 设置 x 轴标题
plt.xticks(rotation = 45)
# x 轴的字体倾斜
plt.ylabel('营业额(元)')
# 设置 y 轴
scatter_params = '''
参数 说明
x,y x轴 和 y轴对应的数据
c 散点标记的颜色,为指定的色彩、数值序列或者颜色序列。
'c', 'r', 'g', 'k', 'y', 'm', 'b'
marker 散点标记类型,默认为圆圈。
cmap 仅当c参数为颜色序列的时候使用。
alpha 透明图设置,取值范围[0,1]。0:透明,1:不透明。
norm 仅当c为数值序列的时候,通过colors.Normalize将值进行正则化。
linewidths 散点标记的边界的宽度。
edgecolors 散点标记的边界的颜色。
'''
x = range(len(df['交易额']))
y = df['交易额']
plt.title('员工和营业额之间的散点图')
# 设置标题
plt.scatter(x, y,s = 20,c = 'g',marker = '*',
alpha = 0.8,linewidths = 0.5,edgecolors = ['c', 'r', 'g', 'k', 'y', 'm', 'b'])
# 散点图参数
plt.xlabel('员工姓名')
# 设置 x 轴标题
plt.xticks(rotation = 45)
# x 轴的字体倾斜
plt.ylabel('营业额(元)')
# 设置 y 轴
pie_params = '''
参数 说明
x (每一块)的比例,如果sum(x) > 1会使用sum(x)归一化;
labels (每一块)饼图外侧显示的说明文字;
explode (每一块)离开中心距离;
startangle 起始绘制角度,默认图是从x轴正方向逆时针画起,如设定 =90 则从y轴正方向画起;
shadow 在饼图下面画一个阴影。默认值:False,没有阴影;
labeldistance label标记的绘制位置,相对于半径的比例,默认值为1.1, 如<1则绘制在饼图内侧;
autopct 控制饼图内百分比设置,可以使用format字符串或者format function
'%1.1f'指小数点前后位数(没有用空格补齐);
pctdistance 类似于 labeldistance,指定 autopct 的位置刻度,默认值为0.6
radius 控制饼图半径,默认值为1
counterclock 指定指针方向;布尔值,可选参数,默认为:True,逆时针
wedgeprops 字典类型,可选参数,默认值:None。参数字典传递给wedge对象用来画一个饼图。
例如:wedgeprops={'linewidth':3}设置wedge线宽为3。
textprops 设置标签(labels)和比例文字的格式;字典类型,可选参数,默认值为:None。
传递给text对象的字典参数。textprops={'fontsize':20,'color':'black'}
center 浮点类型的列表,可选参数,默认值:(0,0)。图标中心位置。
frame 布尔类型,可选参数,默认值:False。如果是True,绘制带有表的轴框架。
rotatelabels 布尔类型,可选参数,默认为:False。如果为True,旋转每个label到指定的角度。
'''
x = df.groupby(by = '姓名')['交易额'].sum()
plt.title('员工和营业额之间的饼图')
# 设置标题
plt.pie(x,labels = x.keys(),explode = [0,0.1,0,0.1,0.3,0.4],startangle = 30,
shadow = True,labeldistance = 1.3,autopct = '%1.1f',pctdistance = 0.5,
radius = 0.9,counterclock = True,wedgeprops = {'linewidth':3},
textprops = {'fontsize':14,'color':'black'},center = (2,2),frame = False,
rotatelabels = False
)
# 饼图参数
plt.xlabel('员工姓名')
# 设置 x 轴标题
plt.ylabel('营业额所占百分比')
# 设置 y 轴
legend_params = '''
参数 说明
loc = 'upper right' 位于右上角
bbox_to_anchor = [0.5, 0.5] 外边距 上边 右边
ncol = 2 分两列
borderaxespad = 0.3 图例的内边距
'''
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect(
"localhost",
"root",
"root",
"testdb",
charset = "utf8"
)
db
# 使用cursor()方法获取操作游标
cursor = db.cursor()
cursor
# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()
print("数据库版本:%s" % data)
# 如果数据表已经存在使用 execute() 方法删除表。
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
# 创建数据表SQL语句
sql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""
cursor.execute(sql)
# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Hany', 'Liu', 22, 'M', 9999)"""
cursor.execute(sql)
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误回滚
db.rollback()
# SQL 插入语句
sql = "INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES (%s, %s, %s, %s, %s )" %
('XiuW', 'Yin', 21, 'F', 7777)
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
select_operators = '''
fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
fetchall():接收全部的返回结果行.
rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
'''
# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE
WHERE INCOME > %s" % (8000)
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=%s,sex=%s,income=%s" % (fname, lname, age, sex, income))
except:
print("Error: unable to fecth data")
# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE < %s" % (22)
try:
# 执行SQL语句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 发生错误时回滚
db.rollback()
db.close()
# 导入numpy 并赋予别名 np
import numpy as np
# 列表方式
np.array([1,2,3,4])
# 元组方式
np.array((1,2,3,4))
# range 方式
np.array(range(4)) # 不包含终止数字
# 使用 arange(初始位置=0,末尾,步长=1)
np.arange(1,8,2)
np.arange(8)
# 生成等差数组,endpoint 为 True 则包含末尾数字
np.linspace(1,3,4,endpoint=False)
np.linspace(1,3,4,endpoint=True)
# 创建全为零的一维数组
np.zeros(3)
# 创建全为一的一维数组
np.ones(4)
# np.logspace(起始数字,终止数字,数字个数,base = 10) 对数数组
np.logspace(1,3,4)
np.logspace(1,3,4,base = 2)
# 2 的 linspace(1,3,4) 次方
# 创建二维数组(列表嵌套列表)
np.array([[1,2,3],[4,5,6]])
# 创建全为零的二维数组
# 两行两列
np.zeros((2,2))
# 三行两列
np.zeros((3,2))
# 创建一个单位数组
np.identity(3)
# 创建一个对角矩阵,(参数为对角线上的数字)
np.diag((1,2,3))
n = np.array(([1,2,3],[4,5,6],[7,8,9]))
n
# 第一行元素
n[0]
# 第一行第三列元素
# [行,列]
n[0,2]
# 第一行和第二行的元素
n[[0,1],]
# 第一行第三列,第三行第二列,第二行第一列
n[[0,2,1],[2,1,0]]
a = np.arange(8)
a
# 将数组倒序
a[::-1]
# 步长为 2
a[::2]
# 从 0 到 4 的元素
a[:5]
c = np.arange(16)
c.shape = 4,4
c
# 第一行,第三个元素到第五个元素(如果没有则输出到末尾截止)
c[0,2:5]
# 第二行元素
c[1]
# 第三行到第六行,第三列到第六列
c[2:5,2:5]
# 第二行第三列元素和第三行第四列元素
c[[1,2],[2,3]]
# 第一行和第三行的第二列到第三列的元素
c[[0,2],1:3]
# 第一列和第三列的所有横行元素
c[:,[0,2]]
# 第三列所有元素
c[:,2]
# 第二行和第四行的所有元素
c[[1,3],]
# 第一行和第三行
c[[0,3]]
# 第一行和第三行 的 第二列和第四列
c[[0,3]][:,[1,3]]
# 生成一个随机数组
np.random.randint(0,6,3)
# 生成一个随机数组(二维数组)
# randint 的 第三个参数为二元组
np.random.randint(0,6,(3,3))
# 生成四个随机数在[0,1)之间
np.random.rand(4)
# 从标准正态分布中随机抽选出3个数
np.random.standard_normal(3)
# 返回三页四行两列的标准正态分布数
np.random.standard_normal((3,4,2))
x = np.arange(8)
x
np.append(x,10)
# 在数组尾部追加多个元素,不修改 x 的值
np.append(x,[15,16,17])
# 使用 数组下标修改元素的值
x[0] = 99
x
# 在指定位置插入数据
np.insert(x,0,54)
# 创建一个多维数组
x = np.array([[1,2,3],[11,22,33],[111,222,333]])
x
# 修改第 0 行第 2 列的元素值
x[0,2] = 9
x
# 行数大于等于 1 的,列数大于等于 1 的置为 0
x[1:,1:] = 0
x
# 同时修改多个元素值
x[1:,1:] = [7,8]
x
x[1:,1:] = [[7,8],[9,10]]
x
# 对元素使用函数
def func(i,j):
return (i+1) * (j+1)
np.fromfunction(func,(9,9))
n = np.arange(10)
n
# 查看数组的大小
n.size
# 将数组分为两行五列
n.shape = 2,5
n
# 显示数组的维度
n.shape
# 设置数组的维度,-1 表示自动计算
n.shape = 5,-1
n
# 将新数组设置为调用数组的两行五列并返回
x = n.reshape(2,5)
x
x = np.arange(5)
# 将数组设置为两行,没有数的设置为 0
x.resize((2,10))
x
# 将 x 数组的两行五列形式显示,不改变 x 的值
np.resize(x,(2,5))
x = np.array([1,2,4,3])
x
# 返回排序后元素的原下标
np.argsort(x)
# 对数组进行排序
x.sort()
x
# 输出最大值的下标
x.argmax()
# 输出最小值的下标
x.argmin()
# 将 0~100 10等分
x = np.arange(0,100,10)
x
# 每个数组元素对应的正弦值
np.sin(x)
# 每个数组元素对应的余弦值
np.cos(x)
# 对参数进行四舍五入
np.round(np.cos(x))
# 对参数进行上入整数 3.3->4
x/3
np.ceil(x/3)
# 随机生成 2行10列 的随机数
x = np.random.randint(0,10,size=(2,10))
x
# 大于 4 的置为 0 , 小于等于 4 的置为 1
np.where(x > 4,0,1)
# 小于 5 的乘 2 ,大于等于 5 的除 2
np.piecewise(x,[x < 5,x >= 5],[lambda x:x * 2,lambda x:x / 2])
x = np.array((1,2,3,4,5))
x
# 使用 * 进行相乘
x*2
# 使用 / 进行相除
x / 2
2 / x
# 使用 // 进行整除
x//2
10//x
# 使用 ** 进行幂运算
x**3
2 ** x
# 使用 + 进行相加
x + 2
# 使用 % 进行取模
x % 3
# 使用 + 进行相加
np.array([1,2,3,4]) + np.array([11,22,33,44])
# 整体都加 3
np.array([1,2,3,4]) + np.array([3])
n = np.array((1,2,3))
n * n
# 二维数组相乘
n * np.array([[1],[2],[3]])
n * np.array(([1,2,3],[4,5,6],[7,8,9]))
# / 除法
n / n
# ** 幂运算
n ** n
x = np.array((1,2,3))
y = np.array((4,5,6))
# 数组的内积运算(对应位置上元素相乘)
# 4 + 10 + 18
np.dot(x,y)
sum(x*y)
# 布尔运算
n = np.random.rand(4)
n
n > 0.5
n[n > 0.5]
# 找到数组中 0.05 ~ 0.4 的元素总数
sum((n > 0.05)&(n < 0.4))
# 是否都大于 0.2
np.all(n > 0.2)
# 是否有元素小于 0.1
np.any(n < 0.1)
a = np.array([1,4,7])
# array([1, 4, 7])
b = np.array([4,3,7])
# array([4, 3, 7])
# 在 a 中是否有大于等于 b 的元素
a >= b
# 在 a 中是否有等于 b 的元素
a == b
# 显示 a 中 a 的元素等于 b 的元素
a[a == b]
# 显示 a 中的偶数且小于 5 的元素
a[(a % 2 == 0) & (a < 5)]
x = np.matrix([[1,2,3],[4,5,6]])
x
y = np.matrix([1,2,3,4,5,6])
y
# x 的第二行第二列元素
x[1,1]
y[:,:3]
x = np.matrix([[1,2,3],[4,5,6]])
x
y = np.matrix([[1,2],[4,5],[7,8]])
y
# 矩阵的乘法
x*y
# 相关系数矩阵,可使用在列表元素数组矩阵
# 负相关
np.corrcoef([1,2,3],[8,5,4])
# 正相关
np.corrcoef([1,2,3],[4,5,7])
# 矩阵的方差
np.cov([1,1,1,1,1])
# 矩阵的标准差
np.std([1,1,1,1,1])
x = [-2.1 , -1 , 4.3]
y = [3 , 1.1 , 0.12]
# 垂直堆叠矩阵
np.vstack((x,y))
# 水平堆叠矩阵
np.hstack((x,y))
# 矩阵的协方差
z = np.vstack((x,y))
np.cov(z)
np.cov(x,y)
# 标准差
np.std(z)
# 列向标准差
np.std(z,axis = 1)
# 方差
np.cov(x)
# 特征值和特征向量
A = np.array([[1,-3,3],[3,-5,3],[6,-6,4]])
A
e,v = np.linalg.eig(A)
# e 为特征值, v 为特征向量
e
v
# 矩阵与特征向量的乘积
np.dot(A,v)
# 特征值与特征向量的乘积
e * v
# 验证两个乘积是否相等
np.isclose(np.dot(A,v),(e * v))
# 行列式 |A - λE| 的值应为 0
np.linalg.det(A-np.eye(3,3)*e)
x = np.matrix([[1,2,3],[4,5,6],[7,8,0]])
x
# 逆矩阵
y = np.linalg.inv(x)
y
# 矩阵的乘法
x * y
y * x
# 求解线性方程组
a = np.array([[3,1],[1,2]])
b = np.array([9,8])
# 求解
x = np.linalg.solve(a,b)
x
# 验证
np.dot(a,x)
# 最小二乘解:返回解,余项,a 的秩,a 的奇异值
np.linalg.lstsq(a,b)
# 计算向量和矩阵的范数
x = np.matrix([[1,2],[3,-4]])
x
np.linalg.norm(x)
np.linalg.norm(x,-2)
np.linalg.norm(x,-1)
np.linalg.norm(x,1)
np.linalg.norm([1,2,0,3,4,0],0)
np.linalg.norm([1,2,0,3,4,0],2)
# 奇异值分解
a = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
u,s,v = np.linalg.svd(a)
u
s
v
# 验证
u * np.diag(s) * v
x = np.matrix([[1,2,3],[4,5,6]])
x
# 实现矩阵的转置
x.T
y = np.matrix([1,2,3,4,5,6])
y
y.T
# 元素平均值
x.mean()
# 纵向平均值
x.mean(axis = 0)
# 横向平均值
x.mean(axis = 1)
# 所有元素之和
x.sum()
# 横向最大值
x.max(axis = 1)
# 横向最大值的索引下标
x.argmax(axis = 1)
# 对角线元素
x.diagonal()
# 非零元素下标
x.nonzero()
import pandas as pd
import numpy as np
import copy
import matplotlib.pyplot as plt
# 设置输出结果列对齐
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)
# 创建 从 0 开始的非负整数索引
pd.Series(range(1,20,5))
# 使用字典创建 Series 字典的键作为索引
pd.Series({'语文':95,'数学':98,'Python':100,'物理':97,'化学':99})
# 使用索引下标进行修改 Series 对象的值
s1 = pd.Series(range(0,20,8))
s1[0] = -17
s1
# 查看 s1 的绝对值
abs(s1)
# 将 s1 所有的值都加 5、使用加法时,对所有元素都进行运算
s1 + 5
# 在 s1 的索引下标前加入参数值
s1.add_prefix('hany_')
# s1 数据的直方图
s1.hist()
# 每行索引后面加上 _hany
s1.add_suffix('_hany')
# 查看 s2 中最大值的索引
s1.argmax()
# 查看 s1 的值是否在指定区间内
s1.between(0,10,inclusive = True)
# 查看 s1 中 10以上的数据
s1[s1 > 10]
# 查看 s1 中大于中值的数据
s1[s1 > s1.median()]
# s1 与数字之间的运算,开平方 * 10 保留一位小数
# 16 -> 4 -> 40 -> 40.0
round((s1**0.5)*10,1)
# s1 的中值
s1.median()
# s1 中最小的两个数
s1.nsmallest(2)
# s1 中最大的两个数
s1.nlargest(2)
# Series 对象之间的运算,对相同索引进行计算
# 不是相同索引的使用 NaN , 0 + 5 , 1 + 6
pd.Series(range(5)) + pd.Series(range(5,10))
# 对 Series 对象使用匿名函数
s = pd.Series(range(5))
s
# x -> 0 1 2 3 4
# y -> 2
# z -> 5
# 0 ** 2 % 5 -> 0
# 3 ** 2 % 5 -> 4
s.pipe(lambda x,y,z:(x ** y) % z,2,5)
pd.Series(range(5)).pipe(lambda x:x*3)
# 使用两次 pipe 应用匿名函数
pd.Series(range(5)).pipe(lambda x:x*3).pipe(lambda x:x+3)
# 对 Series 对象使用匿名函数
pd.Series(range(5)).apply(lambda x:x+3)
# 查看标准差
pd.Series(range(0,5)).std()
# 查看无偏方差
pd.Series(range(0,5)).var()
# 查看无偏标准差
pd.Series(range(0,5)).sem()
# 查看是否存在等价于 True 的值
any(pd.Series([3,0,True]))
# 查看是否所有的值都等价于 True
all(pd.Series([3,0,True]))
# 创建一个 DataFrame 对象
pd.DataFrame(np.random.randint(1,20,(5,3)),
# 五行三列
index = range(5),
# 索引值
columns = ['A','B','C'])
# 列名
# 索引为时间序列
pd.DataFrame(np.random.randint(5,15,(9,3)),
index = pd.date_range(start = '202011081943',
end = '202011090400',
freq = 'H'),
columns = ['Pandas','爬虫','比赛'])
# 使用字典进行创建
pd.DataFrame({'语文':[87,79,67,92],
'数学':[93,89,80,77],
'英语':[88,95,76,77]},
index = ['张三','李四','王五','赵六'])
# 创建时自动扩充
pd.DataFrame({'A':range(5,10),'B':3})
data = pd.read_excel('超市营业额.xlsx',usecols = ['日期','交易额'])
data.head()
dff = copy.deepcopy(data)
# 查看周几
dff['日期'] = pd.to_datetime(data['日期']).dt.day_name()
dff.head()
# 按照周几进行分组,查看交易的平均值
dff = dff.groupby('日期').mean().apply(round)
dff.index.name = '周几'
dff.head()
dff = copy.deepcopy(data)
# 使用正则规则查看月份日期
dff['日期'] = dff.日期.str.extract(r'(d{4}-d{2})')
dff.head()
# 按照日 进行分组查看交易的平均值 -1 表示倒数第一个
data.groupby(data.日期.str.__getitem__(-1)).mean().apply(round)
# 查看日期尾数为 1 的数据
data[data.日期.str.endswith('1')][:12]
# 查看日期尾数为 12 的交易数据,slice 为切片 (-2) 表示倒数两个
data[data.日期.str.slice(-2) == '12']
# 查看日期中月份或天数包含 2 的交易数据
data[data.日期.str.slice(-5).str.contains('2')][1:9]
# 对姓名和日期进行分组,并进行求和
dataframe = pd.read_excel('超市营业额.xlsx')
dff = dataframe.groupby(by = ['姓名','日期'],as_index = False).sum()
dff.head()
# 将 dff 的索引,列 设置成透视表形式
dff = dff.pivot(index = '姓名',columns = '日期',values = '交易额')
dff.head()
# 查看前一天的数据
dff.iloc[:,:1]
# 交易总额小于 80000 的人的前三天业绩
dff[dff.sum(axis = 1) < 80000].iloc[:,:3]
# 工资总额大于 2900 元的员工的姓名
dff[dff.sum(axis = 1) > 2900].index.values
# 显示前两天每一天的交易总额以及每个人的交易金额
dataframe.pivot_table(values = '交易额',index = '姓名',
columns = '日期',aggfunc = 'sum',margins = True).iloc[:,:2]
# 显示每个人在每个柜台的交易总额
dff = dataframe.groupby(by = ['姓名','柜台'],as_index = False).sum()
dff.pivot(index = '姓名',columns = '柜台',values = '交易额')
# 查看每人每天的上班次数
dataframe.pivot_table(values = '交易额',index = '姓名',columns = '日期',aggfunc = 'count',margins = True).iloc[:,:1]
# 查看每个人每天购买的次数
dataframe.pivot_table(values = '交易额',index = '姓名',columns = '日期',aggfunc = 'count',margins = True)
# 每个人每天上过几次班
pd.crosstab(dataframe.姓名,dataframe.日期,margins = True).iloc[:,:2]
# 每个人每天去过几次柜台
pd.crosstab(dataframe.姓名,dataframe.柜台)
# 将每一个人在每一个柜台的交易总额显示出来
pd.crosstab(dataframe.姓名,dataframe.柜台,dataframe.交易额,aggfunc='sum')
# 每个人在每个柜台交易额的平均值,金额/天数
pd.crosstab(dataframe.姓名,dataframe.柜台,dataframe.交易额,aggfunc = 'mean').apply(lambda num:round(num,2))
# 读取工号姓名时段交易额,使用默认索引
dataframe = pd.read_excel('超市营业额.xlsx',
usecols = ['工号','姓名','时段','交易额','柜台'])
dataframe.head()
# 对 5 的余数进行分组
dataframe.groupby(by = lambda num:num % 5)['交易额'].sum()
# 查看索引为 7 15 的交易额
dataframe.groupby(by = {7:'索引为7的行',15:'索引为15的行'})['交易额'].sum()
# 查看不同时段的交易总额
dataframe.groupby(by = '时段')['交易额'].sum()
# 各柜台的销售总额
dataframe.groupby(by = '柜台')['交易额'].sum()
# 查看每个人在每个时段购买的次数
con = dataframe.groupby(by = '姓名')['时段'].count()
con
con.name = '交易人和次数'
con
# 每个人的交易额平均值并排序
dataframe.groupby(by = '姓名')['交易额'].mean().round(2).sort_values()
# 每个人的交易额,apply(int) 转换为整数
dataframe.groupby(by = '姓名').sum()['交易额'].apply(int)
# 每一个员工交易额的中值
data = dataframe.groupby(by = '姓名').median()
data.head()
data['交易额']
# 查看交易额对应的排名
data['排名'] = data['交易额'].rank(ascending = False)
data[['交易额','排名']]
# 每个人不同时段的交易额
dataframe.groupby(by = ['姓名','时段'])['交易额'].sum()
# 设置各时段累计
dataframe.groupby(by = ['姓名'])['时段','交易额'].aggregate({'交易额':np.sum,'时段':lambda x:'各时段累计'})
# 对指定列进行聚合,查看最大,最小,和,平均值,中值
dataframe.groupby(by = '姓名').agg(['max','min','sum','mean','median'])
# 查看部分聚合后的结果
dataframe.groupby(by = '姓名').agg(['max','min','sum','mean','median'])['交易额']
# 查看交易额低于 2000 的前五条数据
dataframe[dataframe.交易额 < 2000].head()
# 查看上浮了 50% 之后依旧低于 1500 的交易额,查看 5 条数据
dataframe.loc[dataframe.交易额 < 1500,'交易额'] = dataframe[dataframe.交易额 < 1500]['交易额'].map(lambda num:num*1.5)
dataframe[dataframe.交易额 < 1500].head()
# 查看交易额大于 2500 的数据
dataframe[dataframe.交易额 > 2500]
# 查看交易额低于 900 或 高于 1800 的数据
dataframe[(dataframe.交易额 < 900)|(dataframe.交易额 > 1800)]
# 将所有低于 200 的交易额都替换成 200
dataframe.loc[dataframe.交易额 < 200,'交易额'] = 200
# 查看低于 1500 的交易额个数
dataframe.loc[dataframe.交易额 < 1500,'交易额'].count()
# 将大于 3000 元的都替换为 3000 元
dataframe.loc[dataframe.交易额 > 3000,'交易额'] = 3000
# 查看有多少行数据
len(dataframe)
# 丢弃缺失值之后的行数
len(dataframe.dropna())
# 包含缺失值的行
dataframe[dataframe['交易额'].isnull()]
# 使用固定值替换缺失值
dff = copy.deepcopy(dataframe)
dff.loc[dff.交易额.isnull(),'交易额'] = 999
# 将缺失值设定为 999
dff.iloc[[110,124,168],:]
# 使用交易额的均值替换缺失值
dff = copy.deepcopy(dataframe)
for i in dff[dff.交易额.isnull()].index:
dff.loc[i,'交易额'] = round(dff.loc[dff.姓名 == dff.loc[i,'姓名'],'交易额'].mean())
dff.iloc[[110,124,168],:]
# 使用整体均值的 80% 填充缺失值
dataframe.fillna({
'交易额':round(dataframe['交易额'].mean() * 0.8)
},inplace = True)
dataframe.iloc[[110,124,168],:]
# 重复值
dataframe[dataframe.duplicated()]
# 丢弃重复行
dataframe = dataframe.drop_duplicates()
dataframe.head()
# 重复值
dataframe = pd.read_excel('超市营业额.xlsx')
df = dataframe[['工号','姓名','日期','交易额']]
dff = df[df.duplicated()]
for row in dff.values:
print(df[(df.工号 == row[0]) & (df.日期 == row[2]) &(df.交易额 == row[3])])
# 查看是否有录入错误的工号和姓名
dff = dataframe[['工号','姓名']]
dff.drop_duplicates()
# 数据差分
# 查看员工业绩波动情况(每一天和昨天的数据作比较)
dff = dataframe.groupby(by = '日期').sum()['交易额'].diff()
dff.head()
dff.map(lambda num:'%.2f'%(num)).head()
# 数据差分
# 查看张三的波动情况
dataframe[dataframe.姓名 == '张三'].groupby(by = '日期').sum()['交易额'].diff().head()
# 读取全部数据,使用默认索引
data = pd.read_excel('超市营业额.xlsx')
data.head()
# 修改异常值
data.loc[data.交易额 > 3000,'交易额'] = 3000
data.loc[data.交易额 < 200,'交易额'] = 200
# 删除重复值,inplace 表示对源数据也进行修改
data.drop_duplicates(inplace = True)
# 填充缺失值为交易额的平均值
data['交易额'].fillna(data['交易额'].mean(),inplace = True)
# 使用交叉表得到每人在各柜台交易额的平均值
data_group = pd.crosstab(data.姓名,data.柜台,data.交易额,aggfunc = 'mean').apply(round)
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# 绘制柱状图
data_group.plot(kind = 'bar')
# 数据的合并
data1 = pd.read_excel('超市营业额.xlsx')
data2 = pd.read_excel('超市营业额.xlsx',sheet_name = 'Sheet2')
df1 = data1.head()
df2 = data2.head()
df1
df2
# 使用 concat 连接两个相同结构的 DataFrame 对象
df3 = pd.concat([df1,df2])
df3
# 合并,忽略原来的索引 ignore_index
df4 = df3.append([df1,df2],ignore_index = True)
df4
# 按照列进行拆分
df5 = df4.loc[:,['姓名','柜台','交易额']]
# 查看前五条数据
df5.head()
# 合并 merge 、 join
# 按照工号进行合并,随机查看 3 条数据
rows = np.random.randint(0,len(df5),3)
pd.merge(df4,df5).iloc[rows,:]
# 按照工号进行合并,指定其他同名列的后缀
pd.merge(df1,df2,on = '工号',suffixes = ['_x','_y']).iloc[:,:]
# 两个表都设置工号为索引 set_index
df2.set_index('工号').join(df3.set_index('工号'),lsuffix = '_x',rsuffix = '_y').iloc[:]
dataframe = pd.read_excel('超市营业额.xlsx',
usecols = ['工号','姓名','时段','交易额','柜台'])
dataframe.head()
# 按照交易额和工号降序排序,查看五条数据
dataframe.sort_values(by = ['交易额','工号'],ascending = False).head()
# 按照交易额和工号升序排序,查看五条数据
dataframe.sort_values(by = ['交易额','工号']).head()
# 按照交易额降序和工号升序排序,查看五条数据
dataframe.sort_values(by = ['交易额','工号'],ascending = [False,True]).head()
# 按工号升序排序
dataframe.sort_values(by = ['工号']).head()
dataframe.sort_values(by = ['工号'],na_position = 'last').head()
# na_position -> nan排序的位置
# 按列名升序排序
dataframe.sort_index(axis = 1).head()
dataframe.sort_index(axis = 1,ascending = False).head()
# 时间序列
# 每隔五天--5D
pd.date_range(start = '20201109',end = '20201130',freq = '5D')
# 每隔一周--W
pd.date_range(start = '20201109',end = '20201201',freq = 'W')
# 间隔两天,五个数据
pd.date_range(start = '20201109',periods = 5,freq = '2D')
# periods 几个数据 ,freq 间隔时期,两天
# 间隔三小时,八个数据
pd.date_range(start = '20201109',periods = 8,freq = '3H')
# 三点开始,十二个数据,间隔一分钟
pd.date_range(start = '202011091227',periods = 12,freq = 'T')
# 每个月的最后一天
pd.date_range(start = '20201109',end = '20210103',freq = 'M')
# 间隔一年,六个数据,年末最后一天
pd.date_range(start = '20201109',periods = 6,freq = 'A')
# 间隔一年,六个数据,年初最后一天
pd.date_range(start = '20201109',periods = 6,freq = 'AS')
# 使用 Series 对象包含时间序列对象,使用特定索引
data = pd.Series(index = pd.date_range(start = '20200321',periods = 24,freq = 'H'),data = range(24))
data.head()
# 三小时重采样,计算均值
data.resample('3H').mean()
# 五小时重采样,求和
data.resample('5H').sum()
# 计算OHLC open,high,low,close
data.resample('5H').ohlc()
# 将日期替换为第二天
data.index = data.index + pd.Timedelta('1D')
data.head()
pd.Timestamp('20201109').day_name()
# 查看指定日期的年份是否是闰年
pd.Timestamp('20201109').is_leap_year
# 查看指定日期所在的季度和月份
day = pd.Timestamp('20201109')
# 查看日期的季度
day.quarter
# 查看日期所在的月份
day.month
# 转换为 python 的日期时间对象
day.to_pydatetime()
dataframe = pd.read_excel('超市营业额.xlsx')
dataframe.head()
# 查看所有的交易额信息
dataframe['交易额'].describe()
# 查看四分位数
dataframe['交易额'].quantile([0,0.25,0.5,0.75,1.0])
# 交易额中值
dataframe['交易额'].median()
# 交易额最小的三个数据
dataframe['交易额'].nsmallest(3)
dataframe.nsmallest(3,'交易额')
# 交易额最大的两个数据
dataframe['交易额'].nlargest(2)
# 查看最大的两个交易额数据
dataframe.nlargest(2,'交易额')
# 查看最后一个日期
dataframe['日期'].max()
# 查看最小的工号
dataframe['工号'].min()
# 第一个最小交易额的行下标
min_index = dataframe['交易额'].idxmin()
min_index
# 第一个最小交易额
dataframe.loc[min_index,'交易额']
# 最大交易额的行下标
max_index = dataframe['交易额'].idxmax()
max_index
dataframe.loc[max_index,'交易额']
# 读取工号姓名时段交易额,使用默认索引
dataframe = pd.read_excel('超市营业额.xlsx',
usecols = ['工号','姓名','时段','交易额'])
dataframe.head()
# 查看第 1 3 4 行的第 1 2 列
dataframe.iloc[[0,2,3],[0,1]]
# 跳过 1 2 4 行,以第一列姓名为索引
dataframe = pd.read_excel('超市营业额.xlsx',
skiprows = [1,2,4],
index_col = 1,
# header = 1,
)
dataframe.head()
dataframe = pd.read_excel('超市营业额.xlsx')
dataframe.head()
# 查看第 1 3 4 行的第 1 2 列
dataframe.iloc[[0,2,3],[0,1]]
# 查看前五行指定,姓名、时段和交易额的数据
dataframe[['姓名','时段','交易额']].head()
dataframe.head()[['姓名','时段','交易额']]
# 查看第 2 4 5 行 姓名,交易额 数据 loc 函数
dataframe.loc[[1,3,4],['姓名','交易额']]
# 查看第四行的姓名数据
dataframe.at[3,'姓名']
# 查看交易额大于 1700 的数据
dataframe[dataframe['交易额'] > 1700].head()
# 查看交易额总和
dataframe['交易额'].sum()
# 某一时段的交易总和
dataframe[dataframe['时段'] == '9:00-14:00']['交易额'].sum()
# 查看张三在9:00-14:00之间的交易情况
dataframe[(dataframe.姓名 == '张三') & (dataframe.时段 == '9:00-14:00')].head()
# 查看日用品的销售总额
dataframe[dataframe['柜台'] == '日用品']['交易额'].sum()
# 查看张三总共的交易额
dataframe[dataframe['姓名'].isin(['张三'])]['交易额'].sum()
# 查看交易额在 1500~1600 之间的记录
dataframe[dataframe['交易额'].between(1500,1600)].head()
data = pd.read_excel('超市营业额.xlsx')
data.head()
# 将日期设置为 python 中的日期类型
data.日期 = pd.to_datetime(data.日期)
data.head()
# 每七天营业的总额
data.resample('7D',on = '日期')['交易额'].sum()
# 每七天营业总额
data.resample('7D',on = '日期',label = 'right')['交易额'].sum()
# 删除工号这一列
data.drop('工号',axis = 1,inplace = True)
data.head()
# 按照姓名和柜台进行分组汇总
data = data.groupby(by = ['姓名','柜台']).sum()
data.head(4)
# 查看张三的汇总数据
data.loc['张三',:]
# 查看张三在蔬菜水果的交易数据
data.loc['张三','蔬菜水果']
# 多索引
# 重新读取,使用第二列和第六列作为索引,排在前面
data = pd.read_excel('超市营业额.xlsx',index_col = [1,5])
data.head()
# 按照柜台进行排序
dff = data.sort_index(level = '柜台',axis = 0)
dff
# 按照柜台进行分组求和
dff = data.groupby(level = '柜台').sum()['交易额']
dff.head()
data = pd.DataFrame({'A':[3,3,3,3,3],'B':[1,2,3,4,5],
'C':[-5,-4,1,4,5],'D':[-45,15,63,40,50]
})
data
#标准差
data.std()
# 平均值
data.mean()
# 标准差的平方
data.std()**2
# 协方差
data.cov()
# 指定索引为 姓名,日期,时段,柜台,交易额
data = pd.read_excel('超市营业额.xlsx',
usecols = ['姓名','日期','时段','柜台','交易额']
)
data.head()
# 删除缺失值和重复值,inplace = True 直接丢弃
data.dropna(inplace = True)
data.drop_duplicates(inplace = True)
# 处理异常值
data.loc[data.交易额 < 200,'交易额'] = 200
data.loc[data.交易额 > 3000,'交易额'] = 3000
# 使用交叉表得到不同员工在不同柜台的交易额平均值
pd.crosstab(data.姓名,data.柜台,data.交易额,aggfunc = 'mean')
# 查看数据的标准差
dff.std()
import random
# choice(seq)
# 从序列的元素中随机挑选一个元素
random.choice('Hany')
random.choice(['H','a','n','y'])
# randrange ([start,] stop [,step])
# 在指定范围内,从步长递增的集合中获取一个随机数,步长默认为 1
random.randrange(5)
random.randrange(1,5)
random.randrange(1,6,2)
# 随机生成一个实数,在 [0,1) 范围内
random.random()
# seed([x])
# 改变随机数生成器的种子seed,种子不同生成的随机数不同
random.seed(5)
numbers = [7,8,4,5,1,2,3,6,9]
# 将序列内的所有元素顺序打乱
random.shuffle(numbers)
numbers
# uniform(x, y)
# 随机生成一个实数,在[x,y]范围内
random.uniform(5,10)
# random.randint(x,y)
# 随机生成一个整数,在[x,y]范围内
random.randint(3,10)
# random.sample(seq,num)
# 从 seq 中随机选取 num 个数
random.sample(numbers,3)
import re
match_params = '''
参数 说明
pattern 匹配的正则表达式
string 匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式
如:是否区分大小写,多行匹配等
匹配成功 re.match方法返回一个匹配的对象,否则返回 None
'''
# 在起始位置匹配
re.match('abcd', 'abcdefg')
re.match('abcd', 'abcdefg').span()
re.match('efg', 'abcdefg') == None
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*',line,re.M|re.I)
group_methods = '''
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
'''
matchObj.group()
matchObj.group(1)
matchObj.group(2)
matchObj.groups()
search_params = '''
参数 说明
pattern 匹配的正则表达式
string 匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式
如:是否区分大小写,多行匹配等
匹配成功 re.search 方法返回一个匹配的对象,否则返回 None
'''
print(re.search('www', 'www.runoob.com')) # 在起始位置匹配
print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com'))
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
searchObj = re.search( r'(.*) are (.*?) .*', "Cats are smarter than dogs", re.M|re.I)
searchObj.group()
searchObj.group(1)
searchObj.group(2)
searchObj.groups()
import requests
requests.get('https://httpbin.org/get')
# 发送 get 请求
# 带有参数 , 使用 params 参数
data = {
'key':'value'
}
requests.get('https://httpbin.org/get',params = data)
# 发送 post 请求
data = {
'key':'value'
}
requests.post('https://httpbin.org/get',data = data)
# 405 表示请求的方式不对
# 定义请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36 Edg/86.0.622.58'
}
response = requests.get('https://httpbin.org/get',headers = headers)
# .content 响应内容的字节码,一般处理二进制文件
response.content
# 自动选择适当的编码,对 .content解码
response.text
eval(response.text)['origin']
# 使用 eval 将字符串转换为字典 , 提取数据
response.json()
# 解析json格式的数据,如果无法解析,则抛出异常
response.json()['url']
request_params = '''
requests 方法 请求参数
• url 请求的URL地址
• params GET请求参数
• data POST请求参数
• json 同样是POST请求参数,要求服务端接收json格式的数据
• headers 请求头字典
• cookies cookies信息(字典或CookieJar)
• files 上传文件
• auth HTTP鉴权信息
• timeout 等待响应时间,单位秒
• allow_redirects 是否允许重定向
• proxies 代理信息
• verify 是否校验证书
• stream 如果为False,则响应内容将直接全部下载
• cert 客户端证书地址
'''
Session = '''
Session可以持久化请求过程中的参数,以及cookie
需要登录的网页,使用session可以避免每次的登录操作
'''
s = requests.Session()
s.cookies
s.cookies = requests.cookies.cookiejar_from_dict({'key': 'value'})
# 修改 cookie 的信息
s.cookies
r = s.get('https://httpbin.org/cookies')
r.text
'''
Session 提供默认值
'''
s = requests.Session()
s.headers.update(
{'h1':'val1',
'h2':'val2'}
)
r = s.get('https://httpbin.org/headers', headers={'h2': 'val2_modify'})
r.text
Response = '''
字段
• cookies 返回CookieJar对象
• encoding 报文的编码
• headers 响应头
• history 重定向的历史记录
• status_code 响应状态码,如200
• elaspsed 发送请求到接收响应耗时
• text 解码后的报文主体
• content 字节码,可能在raw的基础上解压
方法
• json() 解析json格式的响应
• iter_content() 需配置stream=True,指定chunk_size大小
• iter_lines() 需配置stream=True,每次返回一行
• raise_for_status() 400-500之间将抛出异常
• close()
'''
import urllib.request
import urllib.parse
import urllib.error
import socket
response = urllib.request.urlopen('https://www.python.org')
response
# 返回网页内容
response.read().decode('utf-8')
#返回响应头中的server值
response.getheader('server')
#以列表元组对的形式返回响应头信息
response.getheaders()
response.version
# #返回版本信息
response.status
# #返回状态码200,404代表网页未找到
response.debuglevel
# 返回调试等级
response.closed
# 返回对象是否关闭
response.geturl()
# 返回当前 url
response.info()
# 返回网页的头信息
response.getcode()
# 返回响应的HTTP状态码
response.msg
# 访问成功返回 OK
response.reason
# 返回状态信息
urlopen_params = '''
urlopen()方法可传递参数
url:网站地址,str类型,也可以是一个request对象
data:data参数是可选的,内容为字节流编码格式的即bytes类
如果传递data参数,urlopen将使用Post方式请求
'''
data = bytes(
urllib.parse.urlencode(
{'word':'hello'}
),encoding = "utf-8"
)
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
response.read()
other_params = '''
timeout参数:用于设置超时时间,单位为秒,
如果请求超出了设置时间 还未得到响应则抛出异常,
支持HTTP,HTTPS,FTP请求
context参数:必须是ssl.SSLContext类型,用来指定SSL设置
cafile和capath这两个参数分别指定CA证书和它的路径,会在https链接时用到
'''
Requset_params = '''
url:请求的URL,必须传递的参数
data:上传的数据,必须传bytes字节流类型的数据
如果是字典,可以先用 urllib.parse 模块里的 urlencode() 编码
headers:字典,传递请求头数据,可以通过它构造请求头,也可以通过调用请求实例的方法 add_header() 添加
origin_req_host:指请求方的 host名称 或者 IP地址
unverifiable:表示这个请求是否是无法验证的,默认为False,
例如请求一张图片如果没有权限获取图片,则值为 True
method:是一个字符串,用来指示请求使用的方法,如:GET,POST,PUT 等
'''
url = 'http://httpbin.org/post'
# url
headers = {
'User-Agent':'Mozilla/5.0 (compatible; MSIE 5.5; Windows NT)',
'Host':'httpbin.org'
} #定义头信息
name_dict = {'name':'Hany'}
# 字典
data = bytes(urllib.parse.urlencode(name_dict),encoding='utf-8')
# 转化为 bytes 数据
req = urllib.request.Request(url=url,data=data,headers=headers,method='POST')
# 发送请求
response = urllib.request.urlopen(req)
# 打开请求
response.read()
# 获取内容
Base_Handler = '''
是所有其他 Handler 的父类
处理登录验证,处理cookies,代理设置,重定向等
提供了方法:
add_parent(director):添加director作为父类
close():关闭它的父类
parent():打开使用不同的协议或处理错误
defautl_open(req):捕获所有的URL及子类,在协议打开之前调用
Handler的子类包括:
HTTPDefaultErrorHandler:
用来处理http响应错误,错误会抛出HTTPError类的异常
HTTPRedirectHandler:
用于处理重定向
HTTPCookieProcessor:
用于处理cookies
ProxyHandler:
用于设置代理,默认代理为空
HTTPPasswordMgr:
永远管理密码,它维护用户名和密码表
HTTPBasicAuthHandler:
用户管理认证,如果一个链接打开时需要认证,可以使用它来实现验证功能
'''
Opener_Director = '''
它分三个阶段来打开URL:
调用方法的顺序是通过对处理程序实例 进行排序来确定的
每个使用此类方法的程序都会
1.调用 protocol_request()方法来预处理请求
2.然后调用 protocol_open() 来处理请求
3.最后调用 protocol_response() 方法来处理响应。
之前的 urlopen() 方法就是 urllib 提供的一个Opener
通过 Handler 处理器来构建 Opener 实现 Cookies 处理,代理设置,密码设置等
'''
Opener_method = '''
add_handler(handler):添加处理程序到链接中
open(url,data=None[,timeout]):打开给定的URL与urlopen()方法相同
error(proto,*args):处理给定协议的错误
'''
import wordcloud
import jieba
import pandas as pd
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
WordCloud_params = '''
参数 说明
background_color 背景颜色
max_words 最大词数
mask 以某种形状进行绘制词云
stopwords 添加屏蔽词
font_path 更改字体
random_state 为每一个词返回一个 PIL 颜色
width 图片的宽
height 图片的高
'''
df = pd.read_csv('GDP数据.csv')
# 删除空值
df.dropna(inplace=True)
# 清理重复值
df.duplicated()
df.describe()
city_name = ''
# 国家的名称
city_lst = list(df['国家'])
# 国家的集合
for i in range(len(df)):
city_name += city_lst[i]
ls = jieba.lcut(city_name)
txt = " ".join(ls)
w = wordcloud.WordCloud(
font_path=r'C:WindowsFontsSTXINWEI.TTF',
width = 1000,height = 700,background_color = "white",
)
w.generate(txt)
w.to_file("国家的词云图.png")
plt.imshow(w)
color_mask = np.array(Image.open("beijing.png"))
f = open('bookComments.txt','r',encoding ='gbk')
txt = f.read()
w = wordcloud.WordCloud(
font_path=" C:\Windows\Fonts\STXINGKA.TTF",
background_color="white",
width=800,
height=600,
max_words=200,
max_font_size=80,
mask=color_mask,
).generate(txt)
w.to_file('京东词云.png')
plt.imshow(w)
2021-03-10