Python第三方库 -> 由于是ipynb格式,所以没有对应的输出结果

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} \t\t start: {1} \t\t end: {2}".format(tk[0],tk[1],tk[2]))

result = jieba.tokenize(u'上海益民食品一厂有限公司', mode='search')
print("【搜索模式】")
for tk in result:
    print("word: {0} \t\t start: {1} \t\t 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:\Windows\Fonts\STXINWEI.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

posted @ 2021-03-10 11:13  CodeYaSuo  阅读(294)  评论(0编辑  收藏  举报