Python入门笔记(三)


前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转:人工智能从入门到精通教程




第十二章 异常处理

程序将停止,并显示一个traceback。

12.1 常见异常

AssertionError断言语句(assert)失败
AttributeError尝试访问未知的对象属性
EOFError用户输入文件末尾标志EOF(Ctrl+d)
FloatingPointError浮点计算错误
GeneratorExitgenerator.close()方法被调用的时候
ImportError导入模块失败的时候
IndexError索引超出序列的范围
KeyError字典中查找一个不存在的关键字
KeyboardInterrupt用户输入中断键(Ctrl+c)
MemoryError内存溢出(可通过删除对象释放内存)
NameError尝试访问一个不存在的变量
NotImplementedError尚未实现的方法
OSError操作系统产生的异常(例如打开一个不存在的文件)
OverflowError数值运算超出最大限制
ReferenceError弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError一般的运行时错误
StopIteration迭代器没有更多的值
SyntaxErrorPython的语法错误
IndentationError缩进错误
TabErrorTab和空格混合使用
SystemErrorPython编译器系统错误
SystemExitPython编译器进程被关闭
TypeError不同类型间的无效操作
UnboundLocalError访问一个未初始化的本地变量(NameError的子类)
UnicodeErrorUnicode相关的错误(ValueError的子类)
UnicodeEncodeErrorUnicode编码时的错误(UnicodeError的子类)
UnicodeDecodeErrorUnicode解码时的错误(UnicodeError的子类)
UnicodeTranslateErrorUnicode转换时的错误(UnicodeError的子类)
ValueError传入无效的参数
ZeroDivisionError除数为零

TypeError:类型错误
不同类型间的操作出现的错误

1 + '1'
TypeError: unsupported operand type(s) for +: 'int' and 'str'

例2

age = input('请输入你的年龄')
if age >= 18:
    print('成年人...')

在这里插入图片描述
SyntaxError:语法错误

print'zdb'
SyntaxError: invalid syntax

IndexError: 索引错误
索引超出序列的范围

my_list = [1, 2, 3]   # 这里是0到2的索引
my_list[3]
IndexError: list index out of range

NameError :尝试访问一个不存在的变量

fishc
NameError: name 'fishc' is not defined

AssertionError :断言语句(assert)失败

my_list = ['zdb']
assert len(my_list) > 0
my_list.pop()         #列表只有一个元素,删除了就为0
assert len(my_list) > 0
Traceback (most recent call last):
  File "C:/Users/zdb/PycharmProjects/untitled/temp.py", line 4, in <module>
    assert len(my_list) > 0
AssertionError

AttributeError :尝试访问未知的对象属性

my_list = ['zdb']
assert len(my_list) > 0
my_list.fishc     #fishc不知道是什么,访问失败
AttributeError: 'list' object has no attribute 'fishc'

KeyError 字典中查找一个不存在的关键字

my_dict = {'one':1, 'two':2, 'three':3}
my_dict['one']
my_dict['four']
KeyError: 'four'

不报错解决方法: get()

my_dict = {'one':1, 'two':2, 'three':3}
print(my_dict.get('four'))
None

ZeroDivisionError :除数为零

5 / 0
ZeroDivisionError: division by zero



12.2 处理异常:try-- except

例:代码出错,程序终止

f = open('我为什么是一个文件.txt')    #没有这个文件
print(f.read())       #输出文件里面的内容
f.close()             #关闭文件
FileNotFoundError: [Errno 2] No such file or directory: '我为什么是一个文件.txt'

为了解决上述代码终止运行的问题,这里进行异常处理
try—except

try:
    f = open('我为什么是一个文件.txt')
    print(f.read())
    f.close()
    
except OSError:    # 如果上面代码出现这个异常
    print('文件出错了')
文件出错了

try–except----except—except…
如果可能出现多个异常,可以使用多个except
在这里插入图片描述
例:
在这里插入图片描述

try—except ----as —

try:
    f = open('我为什么是一个文件.txt')
    print(f.read())
    f.close()
except OSError as reason:   # 出现这个异常,执行下面语句
    print('文件出错了\n错误的原因是:' + str(reason))
文件出错了
错误的原因是:[Errno 2] No such file or directory: '我为什么是一个文件.txt'

try:
    sum = 1+'1'
except TypeError as reason:
    print('类型出错了\n错误的原因是:' + str(reason))
类型出错了
错误的原因是:unsupported operand type(s) for +: 'int' and 'str'

try----except----else—

try:
    int('123')
except ValueError as reason:
    print('出错了!' + str(raeson))   # 出现valueerror异常输出这个
else:
    print('没有任何异常!')           #没有异常输出这句
没有任何异常!

try----except----else----finally
finally后面的语句是无论try里面的代码出不出错都会执行的

try:
    f = open('data.txt', 'w')     #写入的方式打开
    for each_line in f:
        print(each_line)          #输出内容
except OSError as reason:
    print('出错了:' + str(reason))
finally:                        #finally定会执行
    f.close()
出错了:not readable

例2

try:
    with open('data.txt', 'w') as f:    #相当于f=open()
        for each_line in f:
            print(each_line)
except OSError as reason:              #打开一个不存在的文件
    print('出错了:' + str(reason))
finally:
    f.close()
出错了:not readable



12.3 创建异常类型:raise语句

raise ZeroDivisionError('除数为零的异常')
    raise ZeroDivisionError('除数为零的异常')
ZeroDivisionError: 除数为零的异常

def triangle(a, b, c):
    if (a+b<=c)|(a+c<=b)|(b+c<=a):
        raise Exception('不满足两边之和大于第三边!')
    else:
        print('是三角形!')

try:
    triangle(1,2,3)
except Exception as error:
    print('错误:' + str(error))
错误:不满足两边之和大于第三边!



12.4 断言:assert

  • 断言是一个完整性的检查,确保代码没有做什么明显错误的事情。这些完整的检查由assert语句执行。如果检查失败,就会抛出异常。

assert语句包含以下部分:

  • assert关键字
  • 条件(即求值为True或False的表达式)
  • 逗号
  • 当条件为False时显示的字符串
assert 3<4, '正确'
assert 3>4, '错误'

在这里插入图片描述



12.5 存储数据:json.dump()和json.load()

  • 模块json让你能够将简单的python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。还可以在python程序之间分享数据,在其它语言之间也能分享。

1、函数json.dump()接受两个参数:要存储的数据、存储数据的文件对象。

import json

numbers = [2, 3, 5, 7, 11, 13]

filename = 'numbers.json'
with open(filename, 'w') as f_obj:   #写入的方式打开,用f_obj表示
    json.dump(numbers,f_obj)        #两个参数,存储的数据,文件对象

在这里插入图片描述
2、使用json.load()将这个列表读取到内存中

import json

filename = 'numbers.json'
with open(filename) as f_obj:   #写入的方式打开,用f_obj表示
    numbers = json.load(f_obj)
    print(numbers)

在这里插入图片描述


第十三章 测试代码

13.1 测试函数

1、编写name_function.py模块

def get_formatted_name(first, last):
    """生成整洁的姓名"""
    full_name = first + ' ' + last
    return full_name.title()

2、在names.py中测试

from name_function import get_formatted_name

print("Enter 'q' at any time to quit.")
while True:
    first = input("\nPlease give me a first name: ")
    if first == 'q':
        break
    last = input("Please give me a last name: ")
    if last == 'q':
        break

    formatted_name = get_formatted_name(first, last)    #创建实例
    print("\tNeatly formatted name: " + formatted_name + '.')

3、输出

Enter 'q' at any time to quit.

Please give me a first name: z
Please give me a last name: db
	Neatly formatted name: z db.

Please give me a first name: z
Please give me a last name: q

可以发现我们每次修改name_function.py,都要重新运行names.py,然后重新输入姓名,这样太繁琐了。Python标准库中的模块unittest提供了代码测试工具。

(1)可通过的测试
先导入模块unittest以及要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。
1、在test_name_function.py中测试name_function.py里面的get-formatted_name()

#导入unittest模块
import unittest
#导入要测试的模块函数
from name_function import get_formatted_name

#创建NameTestCase类,继承unittest.TestCase父类
class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""

    #定义方法
    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        #创建实例,存储在formatted_name中
        formatted_name = get_formatted_name('janis', 'joplin')
        #断言方法,用来核实得到的结果是否和期望的结果一致
        #两个参数进行比较
        self.assertEqual(formatted_name, "Janis Joplin")

unittest.main()

在这里插入图片描述
这样测试是不是比上面的方法要方便很多

(2)不能通过的测试
1、修改name_function.py,使其包含中间名
在这里插入图片描述
2、运行test_name_function.py,输出

E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
能够正确地处理像Janis Joplin这样的姓名吗?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:/Users/zdb/PycharmProjects/untitled/temp.py", line 14, in test_first_last_name
    formatted_name = get_formatted_name('janis', 'joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

(3)测试未通过怎么办
测试未通过时,不要修改测试,而应修复导致测试不能通过的代码
1、使中间名变设置成可选的

def get_formatted_name(first, last, middle=''):
    """生成整洁的姓名"""
    if middle:
        full_name = first + ' ' + middle + ' ' + last
    else:
        full_name = first + ' ' + last
    return full_name.title()

2、运行test_name_function.py,输出
在这里插入图片描述

(4)添加新测试
例:添加一个包含中间名的测试
1、在NamesTestCase类中再添加一个方法:

#导入unittest模块
import unittest
#导入要测试的模块函数
from name_function import get_formatted_name

#创建NameTestCase类,继承unittest.TestCase父类
class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""

    #定义方法
    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        #创建实例,存储在formatted_name中
        formatted_name = get_formatted_name('janis', 'joplin')
        #断言方法,用来核实得到的结果是否和期望的结果一致
        #两个参数进行比较
        self.assertEqual(formatted_name, "Janis Joplin")

    def test_first_last_middle_name(self):
        """能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?"""
        formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, "Wolfgang Amadeus Mozart")

unittest.main()

在这里插入图片描述

13.2 测试类

各种断言方法

方法用途
assertEqual核实a == b
assertNotEqual核实a != b
assertTrue(x)核实x为True
assertFalse(x)核实x为False
assertIn(item, list)核实item在list中
assertNotIn(item, list)核实item不在list中

(1)一个要测试的类
1、创建survey.py

class AnonymousSurvey():
    """收集匿名调查问卷的答案"""

    def __init__(self, question):
        """存储一个问题,并为存储答案做准备"""
        self.question = question
        self.responses = []   #答案设置空列表

    def show_question(self):
        """显示调查问卷"""
        print(self.question)

    def store_response(self, new_response):
        """存储单份调查问卷"""
        self.responses.append(new_response)

    def show_results(self):
        """显示搜集到的所有问卷"""
        print("Survey results:")
        for response in self.responses:
            print('- ' + response)

2、在language_survey.py中测试

from survey import AnonymousSurvey

#定义一个问题,并创建一个表示调查的AnonymousSurvey对象
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)

#显示问题并存储答案
my_survey.show_question()
print("Enter 'q' at any time to quit.\n")
while True:    #一直循环,直到输入q跳出
    response = input("Language: ")
    if response == 'q':
        break
    my_survey.store_response(response)

#显示调查结果
print("\nThank youto everyone who participated in the survey!")
my_survey.show_results()

3、输出

What language did you first learn to speak?
Enter 'q' at any time to quit.

Language: English
Language: python
Language: math
Language: q

Thank youto everyone who participated in the survey!
Survey results:
- English
- python
- math

(2)测试AnonymousSurvey类

import unittest      
from survey import AnonymousSurvey    #导入要测试的类

class TestAnonymousSurvey(unittest.TestCase):   #继承了父类
    """针对AnonymousSurvey类的测试"""

    def test_store_single_response(self):
        """测试单个答案会被妥善地存储"""
        question = "What language did you first learn to speak?"
        my_survey= AnonymousSurvey(question)   #创建实例
        my_survey.store_response('English')

        self.assertIn('English', my_survey.responses)

unittest.main()

在这里插入图片描述

测试三个

import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    """针对AnonymousSurvey类的测试"""

    def test_store_single_response(self):
        """测试单个答案会被妥善地存储"""
        question = "What language did you first learn to speak?"
        my_survey= AnonymousSurvey(question)
        my_survey.store_response('English')

        self.assertIn('English', my_survey.responses)


    def test_store_three_responses(self):
        """测试三个答案会被妥善地存储"""
        question = "What language did you first learn to speak?"
        my_survey = AnonymousSurvey(question)
        responses = ['English', 'python', 'C']
        for response in responses:
            my_survey.store_response(response)

        for response in responses:
            self.assertIn(response, my_survey.responses)  #核实response在my_survey.responses中

unittest.main()

输出
在这里插入图片描述

(3)方法setUp()
上面每个测试方法都创建了一个AnonymousSurvey实例,并在每个方法中都创建了一个答案。setUp()方法可以让我们只创建这些对象一次,并在每个测试方法中使用它们。

import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    """针对AnonymousSurvey类的测试"""

    def setUp(self):
        """创建一个调查对象和一组答案,供使用的测试方法使用"""
        question = "What language did you first learn to speak?"
        self.my_survey = AnonymousSurvey(question)      #创建一个调查对象
        self.responses = ['English', 'python', 'C']     #创建一个答案列表,存储在属性中,有self

    def test_store_single_response(self):
        """测试单个答案会被妥善地存储"""
        self.my_survey.store_response(self.responses[0])
        self.assertIn(self.responses[0], self.my_survey.responses)

    def test_store_three_responses(self):
        """测试三个答案会被妥善地存储"""
        for response in self.responses:
            self.my_survey.store_response(response)

        for response in self.responses:
            self.assertIn(response, self.my_survey.responses)

unittest.main()

在这里插入图片描述


第十四章. matplotlib

win10安装matplotlib:pip install matplotlib

14.1 折线图

例1:绘制简单的折线
需要导入matplotlib模块里面的pyplot

import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]
plt.plot(squares)
plt.show()   # 打开matplotlib查看器,并显示绘制的图形

在这里插入图片描述

例2:修改标签文字和线条粗细
linewidth=5决定线的粗细

import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]
plt.plot(squares, linewidth=5)  # linediwth决定了绘制线条的粗细

# 设置图表标题,并给坐标轴加上标签
plt.title("Square Numbers", fontsize=24)   # title指明标题
plt.xlabel("Value", fontsize=14)
plt.ylabel("Square of Value", fontsize=14)

# 设置刻度标记的大小
plt.tick_params(axis='both', labelsize=14)  # 设置刻度,刻度字号14
plt.show()

在这里插入图片描述

例3:设置x轴正确刻度,校正图形

import matplotlib.pyplot as plt

input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
plt.plot(input_values, squares, linewidth=5)  # linediwth决定了绘制线条的粗细

# 设置图表标题,并给坐标轴加上标签
plt.title("Square Numbers", fontsize=24)   # title指明标题
plt.xlabel("Value", fontsize=14)
plt.ylabel("Square of Value", fontsize=14)

# 设置刻度标记的大小
plt.tick_params(axis='both', labelsize=14)  # 设置刻度,刻度字号14
plt.show()

可见前后两图x轴不同了
在这里插入图片描述

14.2 散点图

例1:画一个点

import matplotlib.pyplot as plt

plt.scatter(2, 4)
plt.show()

在这里插入图片描述

例2:设置刻度坐标

import matplotlib.pyplot as plt

plt.scatter(2, 4, s=200)  # s为尺寸

# 设置图表标题并给坐标轴加上标签
plt.title("Square Number", fontsize=24)
plt.xlabel("Value", fontsize=24)
plt.ylabel("Square of Value", fontsize=24)

# 设置刻度标记的大小
plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()

在这里插入图片描述

例3:绘制一系列点

import matplotlib.pyplot as plt

x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]

plt.scatter(x_values, y_values, s=100)  # s为尺寸

# 设置图表标题并给坐标轴加上标签
plt.title("Square Number", fontsize=24)
plt.xlabel("Value", fontsize=24)
plt.ylabel("Square of Value", fontsize=24)

# 设置刻度标记的大小
plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()

在这里插入图片描述

例4:绘制1000个点

import matplotlib.pyplot as plt

x_values = list(range(1, 1001))
y_values = [x**2 for x in x_values]

plt.scatter(x_values, y_values, s=40)  # s为尺寸

# 设置图表标题并给坐标轴加上标签
plt.title("Square Number", fontsize=24)
plt.xlabel("Value", fontsize=24)
plt.ylabel("Square of Value", fontsize=24)

# 设置刻度标记的大小
plt.tick_params(axis='both', which='major', labelsize=14)

# 设置每个坐标轴的取值范围
plt.axis([0, 1100, 0, 1100000])

plt.show()

在这里插入图片描述

例5:删除数据点的轮廓
绘制的点默认为蓝色点和黑色轮廓;但绘制多个点时,黑色轮廓可能粘连在一起,这里可以删除轮廓。

plt.scatter(x_values, y_values, edgecolor='none', s=40)  

注意:2.0.2版本的matplotlib, edgecolor默认为’none’,所以这里根本不需要这句话

例6:自定义颜色
可以使用RGB颜色模式自定义颜色,要指定自定义颜色,可传递参数c,并设置为一个元组,其中包含三个0~1之间的小数值,分别为红,绿,蓝分量。
如下,显示为深蓝色。

plt.scatter(x_values, y_values, c=(0, 0, 0.8), edgecolor='none', s=40)  

在这里插入图片描述
例:使用颜色映射,根据y值的不同,设置不同程度的颜色

import matplotlib.pyplot as plt

x_values = list(range(1, 1001))
y_values = [x**2 for x in x_values]

plt.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues, edgecolors='none', s=40)

# 设置图表标题并给坐标轴加上标签
plt.title("Square Number", fontsize=24)
plt.xlabel("Value", fontsize=24)
plt.ylabel("Square of Value", fontsize=24)

# 设置刻度标记的大小
plt.tick_params(axis='both', which='major', labelsize=14)

# 设置每个坐标轴的取值范围
plt.axis([0, 1100, 0, 1100000])

plt.show()

在这里插入图片描述

14.3 保存图表

可将plt.show()的调用替换为plt.savefig()的调用

plt.savefig('squares_plot.png', bbox_inches='tight')

第一个实参指定要与什么样的文件名保存图表,存储在.py文件的当前目录中
第二个实参指定将图表多余的空白区域裁剪掉

14.4 绘制随机漫步图

from random import choice
import matplotlib.pyplot as plt

class RandomWalk():
    """一个生成随机漫步数据的类"""

    def __init__(self, num_points=5000):                # 5000个点
        """初始化随机漫步的属性"""
        self.num_points = num_points

        # 所有随机漫步都始于(0,0)
        self.x_values = [0]
        self.y_values = [0]

    def fill_walk(self):
        """计算随机漫步包含的所有点"""
        while len(self.x_values) < self.num_points:    # 不断漫步,直到列表达到指定的长度
            # 决定前进方向以及沿这个方向前进的距离
            x_direction = choice([1, -1])              # x方向,1为右,-1为左
            x_distance = choice([0, 1, 2, 3, 4])       # 距离
            x_step = x_direction * x_distance          # 带方向的距离

            y_direction = choice([1, -1])
            y_distance = choice([0, 1, 2, 3, 4])
            y_step = y_direction * y_distance

            # 拒绝原地踏步
            if x_step == 0 and y_step == 0:
                continue

            # 计算下一个点的x和y值
            next_x = self.x_values[-1] + x_step       # 最后的一个值生成最新的值
            next_y = self.y_values[-1] + y_step

            self.x_values.append(next_x)
            self.y_values.append(next_y)


# 创建实例,并将其包含的点都绘制出来
rw = RandomWalk()
rw.fill_walk()
plt.scatter(rw.x_values, rw.y_values, s=15)
plt.show()

在这里插入图片描述
例2:绘制多次随机漫步
只需要修改实例化那里,RandomWalk的类不变

# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk()
    rw.fill_walk()
    plt.scatter(rw.x_values, rw.y_values, s=15)
    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

例3:给点着色
颜色由浅入深

# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk()
    rw.fill_walk()

    point_numbers = list(range(rw.num_points))
    plt.scatter(rw.x_values, rw.y_values, c=point_numbers,
                cmap=plt.cm.Blues, edgecolors='none', s=15)
    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

在这里插入图片描述
例4:绘制起点和终点

# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk()
    rw.fill_walk()

    point_numbers = list(range(rw.num_points))
    plt.scatter(rw.x_values, rw.y_values, c=point_numbers,
                cmap=plt.cm.Blues, edgecolors='none', s=15)

    # 突出起点和终点
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)  # 起点绿色
    plt.scatter(rw.x_values[-1], rw.y_values[-1],
                c='red', edgecolors='none', s=100)          # 终点红色

    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

在这里插入图片描述

例5:隐藏坐标轴

# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk()
    rw.fill_walk()

    point_numbers = list(range(rw.num_points))
    plt.scatter(rw.x_values, rw.y_values, c=point_numbers,
                cmap=plt.cm.Blues, edgecolors='none', s=15)

    # 突出起点和终点
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)  # 起点绿色
    plt.scatter(rw.x_values[-1], rw.y_values[-1],
                c='red', edgecolors='none', s=100)          # 终点红色

    # 隐藏坐标轴
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)

    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

在这里插入图片描述

例6:增加点到50000,减小点的大小从15到1

# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk(50000)
    rw.fill_walk()

    point_numbers = list(range(rw.num_points))
    plt.scatter(rw.x_values, rw.y_values, c=point_numbers,
                cmap=plt.cm.Blues, edgecolors='none', s=1)

    # 突出起点和终点
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)  # 起点绿色
    plt.scatter(rw.x_values[-1], rw.y_values[-1],
                c='red', edgecolors='none', s=100)          # 终点红色

    # 隐藏坐标轴
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)

    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

在这里插入图片描述

例7:调整尺寸以适合屏幕
最终所有代码如下:

from random import choice
import matplotlib.pyplot as plt


class RandomWalk():
    """一个生成随机漫步数据的类"""

    def __init__(self, num_points=5000):               # 5000个点
        """初始化随机漫步的属性"""
        self.num_points = num_points

        # 所有随机漫步都始于(0,0)
        self.x_values = [0]
        self.y_values = [0]

    def fill_walk(self):
        """计算随机漫步包含的所有点"""
        while len(self.x_values) < self.num_points:    # 不断漫步,直到列表达到指定的长度
            # 决定前进方向以及沿这个方向前进的距离
            x_direction = choice([1, -1])              # x方向,1为右,-1为左
            x_distance = choice([0, 1, 2, 3, 4])       # 距离
            x_step = x_direction * x_distance          # 带方向的距离

            y_direction = choice([1, -1])
            y_distance = choice([0, 1, 2, 3, 4])
            y_step = y_direction * y_distance

            # 拒绝原地踏步
            if x_step == 0 and y_step == 0:
                continue

            # 计算下一个点的x和y值
            next_x = self.x_values[-1] + x_step       # 最后的一个值生成最新的值
            next_y = self.y_values[-1] + y_step

            self.x_values.append(next_x)
            self.y_values.append(next_y)


# 只要程序处于活动状态,并将其包含的点都绘制出来
while True:
    # 创建一个RandomWalk实例,并将其的点都绘制出来
    rw = RandomWalk(50000)
    rw.fill_walk()

    # 6.设置绘图窗口的尺寸
    plt.figure(figsize=(10, 6))

    point_numbers = list(range(rw.num_points))
    plt.scatter(rw.x_values, rw.y_values, c=point_numbers,
                cmap=plt.cm.Blues, edgecolors='none', s=1)

    # 突出起点和终点
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)  # 起点绿色
    plt.scatter(rw.x_values[-1], rw.y_values[-1],
                c='red', edgecolors='none', s=100)          # 终点红色

    # 隐藏坐标轴
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)

    plt.show()

    keep_running = input("是否绘制下幅图(y/n):")
    if keep_running == 'n':
        break

在这里插入图片描述
如果上述代码指定的图表尺寸不合适,可根据需要调整其中的数字。如果你知道自己的系统的分辨率,可使用形参dip向figure()传递该分辨率,以有效的利用可用的屏幕空间

plt.figure(dpi=128, figsize=(10,6))

14.5 使用Pygal模拟掷骰子

pip install pygal==1.7

例1:创建一个掷骰子的类,先来100次

from random import randint

class Die():
    """表示一个骰子的类"""

    def __init__(self, num_sides=6):
        """骰子默认为6面"""
        self.num_sides = num_sides

    def roll(self):
        """返回一个位于1和骰子面数之间的随机值"""
        return randint(1, self.num_sides)


# 创建一个D6
die = Die()

# 掷几次骰子,并将结果存储在一个列表中
results = []
for roll_num in range(10):    # 掷骰子10次
    result = die.roll()
    results.append(result)

print(results)

结果随机:

[4, 5, 2, 1, 2, 3, 6, 3, 6, 3]

例2:统计结果

# 创建一个D6
die = Die()

# 掷几次骰子,并将结果存储在一个列表中
results = []
for roll_num in range(1000):    # 掷骰子1000次
    result = die.roll()
    results.append(result)

# 分析结果
frequencies = []
for value in range(1, die.num_sides+1):  # 遍历1到6
    frequency = results.count(value)     # 计算出现每个点的次数
    frequencies.append(frequency)        # 添加到列表中

print(frequencies)
[163, 157, 161, 182, 178, 159]

例3:将结果绘制成直方图

from random import randint
import pygal

class Die():
    """表示一个骰子的类"""

    def __init__(self, num_sides=6):
        """骰子默认为6面"""
        self.num_sides = num_sides

    def roll(self):
        """返回一个位于1和骰子面数之间的随机值"""
        return randint(1, self.num_sides)

# 创建一个D6
die = Die()

# 掷几次骰子,并将结果存储在一个列表中
results = []
for roll_num in range(1000):             # 掷骰子1000次
    result = die.roll()
    results.append(result)

# 分析结果
frequencies = []
for value in range(1, die.num_sides+1):  # 遍历1到6
    frequency = results.count(value)     # 计算次数
    frequencies.append(frequency)        # 添加到列表中
print(frequencies)

# 对结果进行可视化
hist = pygal.Bar()                                   # 创建实例,存储在hist中

hist.title = "一个骰子掷1000次的结果"  # 标题
hist.x_labels = ['1', '2', '3', '4', '5', '6']       # x轴标签
hist.x_title = "结果"
hist.y_title = "统计的次数"

hist.add('D6', frequencies)                          # 传递要添加的值指定的标签
hist.render_to_file('die_visual.svg')                # 将图表渲染成.svg文件

在这里插入图片描述
要查看生成的直方图,需要用Web浏览器打开,生成的.svg文件在代码所在文件夹下

例4:同时掷两个骰子

from random import randint
import pygal


class Die():
    """表示一个骰子的类"""
    def __init__(self, num_sides=6):
        """骰子默认为6面"""
        self.num_sides = num_sides

    def roll(self):
        """返回一个位于1和骰子面数之间的随机值"""
        return randint(1, self.num_sides)


# 创建两个D6骰子
die_1 = Die()
die_2 = Die()

# 掷几次骰子,并将结果存储在一个列表中
results = []
for roll_num in range(1000):              # 掷骰子1000次
    result = die_1.roll() + die_2.roll()  # 两个骰子结果相加
    results.append(result)

# 分析结果
frequencies = []
sum_result = die_1.num_sides + die_2.num_sides
for value in range(2, sum_result+1):     # 遍历2到12
    frequency = results.count(value)     # 计算每个点出现的次数
    frequencies.append(frequency)        # 添加到列表中
print(frequencies)

# 对结果进行可视化
hist = pygal.Bar()                                   # 创建实例,存储在hist中

hist.title = "两个骰子掷1000次的结果"  # 标题
hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']       # x轴标签
hist.x_title = "结果"
hist.y_title = "次数统计"

hist.add('D6 + D6', frequencies)                   # 传递要添加的值指定的标签
hist.render_to_file('die_visual.svg')                # 将图表渲染成.svg文件

在这里插入图片描述
例5:同时掷两个面数不同的骰子

from random import randint
import pygal


class Die():
    """表示一个骰子的类"""
    def __init__(self, num_sides=6):
        """骰子默认为6面"""
        self.num_sides = num_sides

    def roll(self):
        """返回一个位于1和骰子面数之间的随机值"""
        return randint(1, self.num_sides)


# 创建两个骰子
die_1 = Die()    # 6面的骰子
die_2 = Die(10)  # 10面的骰子

# 掷几次骰子,并将结果存储在一个列表中
results = []
for roll_num in range(50000):
    result = die_1.roll() + die_2.roll()  # 两个骰子结果相加
    results.append(result)

# 分析结果
frequencies = []
sum_result = die_1.num_sides + die_2.num_sides
for value in range(2, sum_result+1):     # 遍历每个可能出现的点数
    frequency = results.count(value)     # 计算该点数出现的次数
    frequencies.append(frequency)        # 添加到列表中
print(frequencies)

# 对结果进行可视化
hist = pygal.Bar()                                   # 创建实例,存储在hist中

hist.title = "两个不同面的骰子掷50000次的结果"  # 标题
hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10',
                 '11', '12', '13', '14', '15', '16']       # x轴标签
hist.x_title = "结果"
hist.y_title = "次数统计"

hist.add('D6 + D10', frequencies)                   # 传递要添加的值指定的标签
hist.render_to_file('die_visual.svg')               # 将图表渲染成.svg文件

在这里插入图片描述


第十五章. 下载数据

15.1 csv文件

例1:分析CSV文件头
CSV文件其文件以纯文本的形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。
在这里插入图片描述
next()返回文件的下一行

import csv                              # 用于分析CSV文件中的数据行

filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行
    print(header_row)                   # 输出显示第一行

数据太多这里剪切一部分
在这里插入图片描述
reader处理文件以逗号分隔第一行数据,并存储在列表中。

例2:打印文件头及其位置
为让文件头数据更容易理解,将列表中的每个文件头及其位置打印出来。
调用enumerate()来获取每个元素的索引及其值

import csv                              # 用于分析CSV文件中的数据行

filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    for index, column_header in enumerate(header_row):  # 调用enumerate()来获取每个元素的索引及其值
        print(index, column_header)

这里截取一部分图
在这里插入图片描述

例3:提取并读取数据
阅读器对象从其停留的地方继续往下读取CSV文件,每次都自动返回当前所处位置的下一行,由于我们已经读取了文件头行,这个循环将从第二行开始,这行便是数据。

import csv                              # 用于分析CSV文件中的数据行

filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    highs = []                          # 空列表
    for row in reader:                  # 遍历每行
        high = int(row[1])              # str转int
        highs.append(high)              # 每行的第1个元素,从第0个开始

    print(highs)

在这里插入图片描述
在这里插入图片描述

例:绘制气温图表

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要

# 从文件中获取最高气温
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    highs = []                          # 空列表
    for row in reader:                  # 遍历每行
        high = int(row[1])
        highs.append(high)              # 每行的第1个元素,从第0个开始

    print(highs)

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))  #设置图像大小尺寸
plt.plot(highs, c='red')

# 设置图形的格式
plt.title("Daily high temperatures, July 2014", fontsize=24)  # 标题
plt.xlabel('', fontsize=16)                                   # x轴
plt.ylabel("Temperature(F)", fontsize=16)                     # y轴
plt.tick_params(axis='both', which='major', labelsize=16)     # 刻度标记大小

plt.show()

在这里插入图片描述


datetime模块

from datetime import datetime

first_date = datetime.strptime('2014-7-1', '%Y-%m-%d')  # 第一个参数传入实参,第二个给设置的格式
print(first_date)
2014-07-01 00:00:00

‘%Y-’ 让python将字符串中第一个连字符前面的部分视为四位的年份;
‘%m-’ 让python将第二个连字符前面的部分视为表示月份的数字;
‘%d’ 让python将字符串的最后一部分视为月份中的一天

方法strptime()可接受各种实参,并根据它们来决定如何解读时期,下表列出这些实参:

实参含义
%A星期的名称,如Monday
%B月份名,如January
%m用数字表示的月份(01~12)
%d用数字表示的月份的一天(01~31)
%Y四位的年份,如2020
%y两位的年份,如20
%H24小时制的小时数(00~23)
%I12小时制的小时数(01~12)
%pam或pm
%M分钟数(00~59)
%S秒数(00~61)

例2:在图表中添加日期

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要
from datetime import datetime           # 将字符串转换为对应日期需要

# 从文件中获取最高气温和日期
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)         

    dates, highs = [], []               # 日期,最高温度初始化为空列表
    for row in reader:                  # 遍历每行
        current_date = datetime.strptime(row[0], "%Y-%m-%d")  # 每行第零个元素
        dates.append(current_date)      # 添加日期

        high = int(row[1])              # 最高温度转化为整型
        highs.append(high)              # 添加温度

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')

# 设置图形的格式
plt.title("Daily high temperatures, July 2014", fontsize=24)  # 标题
plt.xlabel('', fontsize=16)                                   # x轴
fig.autofmt_xdate()                                           # 绘制斜的x轴标签
plt.ylabel("Temperature(F)", fontsize=16)                     # y轴
plt.tick_params(axis='both', which='major', labelsize=16)     # 刻度标记大小

plt.show()

在这里插入图片描述


例3:添加更多数据,涵盖更长的时间
这里只是换了一个数据更多的文件,改了一个标题

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要
from datetime import datetime           # 将字符串转换为对应日期需要

# 从文件中获取最高气温和日期
filename = 'sitka_weather_2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    dates, highs = [], []               # 日期,最高温度初始化为空列表
    for row in reader:                  # 遍历每行
        current_date = datetime.strptime(row[0], "%Y-%m-%d")  # 每行第零个元素
        dates.append(current_date)      # 添加日期

        high = int(row[1])              # 最高温度转化为整型
        highs.append(high)              # 添加温度

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')

# 设置图形的格式
plt.title("Daily high temperatures - 2014", fontsize=24)      # 标题
plt.xlabel('', fontsize=16)                                   # x轴
fig.autofmt_xdate()                                           # 绘制斜的x轴标签
plt.ylabel("Temperature(F)", fontsize=16)                     # y轴
plt.tick_params(axis='both', which='major', labelsize=16)     # 刻度标记大小

plt.show()

在这里插入图片描述


例4:再绘制一个数据系列
这里多绘制了一个最低温度

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要
from datetime import datetime           # 将字符串转换为对应日期需要

# 从文件中获取最高气温,最低温度和日期
filename = 'sitka_weather_2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    dates, highs, lows = [], [], []     # 日期,最高温度初始化为空列表
    for row in reader:                  # 遍历每行
        current_date = datetime.strptime(row[0], "%Y-%m-%d")  # 每行第零个元素
        dates.append(current_date)      # 添加日期

        high = int(row[1])              # 最高温度转化为整型
        highs.append(high)              # 添加温度

        low = int(row[3])
        lows.append(low)

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')
plt.plot(dates, lows, c='blue')

# 设置图形的格式
plt.title("Daily high and low temperatures - 2014", fontsize=24)  # 标题
plt.xlabel('', fontsize=16)                                       # x轴
fig.autofmt_xdate()                                               # 绘制斜的x轴标签
plt.ylabel("Temperature(F)", fontsize=16)                         # y轴
plt.tick_params(axis='both', which='major', labelsize=16)         # 刻度标记大小

plt.show()

在这里插入图片描述


例5:给图表区域着色

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要
from datetime import datetime           # 将字符串转换为对应日期需要

# 从文件中获取最高气温,最低温度和日期
filename = 'sitka_weather_2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    dates, highs, lows = [], [], []     # 日期,最高温度初始化为空列表
    for row in reader:                  # 遍历每行
        current_date = datetime.strptime(row[0], "%Y-%m-%d")  # 每行第零个元素
        dates.append(current_date)      # 添加日期

        high = int(row[1])              # 最高温度转化为整型
        highs.append(high)              # 添加温度

        low = int(row[3])
        lows.append(low)

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red', alpha=0.5)   # alpha指定颜色的透明度,使得红色和蓝色折线看起来更浅
plt.plot(dates, lows, c='blue', alpha=0.5)
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)  # 两条线之间填充蓝色,透明度0.1

# 设置图形的格式
plt.title("Daily high and low temperatures - 2014", fontsize=24)  # 标题
plt.xlabel('', fontsize=16)                                       # x轴
fig.autofmt_xdate()                                               # 绘制斜的x轴标签
plt.ylabel("Temperature(F)", fontsize=16)                         # y轴
plt.tick_params(axis='both', which='major', labelsize=16)         # 刻度标记大小

plt.show()

在这里插入图片描述


例6:错误检查
有些文档可能数据不全,缺失数据可能引起异常
例如换这个文档
在这里插入图片描述
这个文档数据不全
在这里插入图片描述
这里就需要修改代码,如下:

import csv                              # 用于分析CSV文件中的数据行
from matplotlib import pyplot as plt    # 画图需要
from datetime import datetime           # 将字符串转换为对应日期需要

# 从文件中获取最高气温,最低温度和日期
filename = 'death_valley_2014.csv'
with open(filename) as f:               # 打开文件,并将结果文件对象存储在f中
    reader = csv.reader(f)              # 创建与该文件相关联的阅读器对象,并存储在reader中
    header_row = next(reader)           # 第一行

    dates, highs, lows = [], [], []     # 日期,最高温度初始化为空列表
    for row in reader:                  # 遍历每行
        try:
            current_date = datetime.strptime(row[0], "%Y-%m-%d")  # 每行第零个元素
            high = int(row[1])  # 最高温度转化为整型
            low = int(row[3])
        except ValueError:
            print(current_date, 'missing data')
        else:
            dates.append(current_date)      # 添加日期
            highs.append(high)              # 添加温度
            lows.append(low)

# 根据数据绘制图像
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red', alpha=0.5)   # alpha指定颜色的透明度,使得红色和蓝色折线看起来更浅
plt.plot(dates, lows, c='blue', alpha=0.5)
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)  # 两条线之间填充蓝色,透明度0.1

# 设置图形的格式
title = 'Daily high and low temperatures - 2014\nDeath Valley, CA'
plt.title(title, fontsize=20)  # 标题
plt.xlabel('', fontsize=16)                                       # x轴
fig.autofmt_xdate()                                               # 绘制斜的x轴标签
plt.ylabel("Temperature(F)", fontsize=16)                         # y轴
plt.tick_params(axis='both', which='major', labelsize=16)         # 刻度标记大小

plt.show()

在这里插入图片描述
在这里插入图片描述


15.2 json文件

例:存

import json

numbers = [1, 3, 5, 7, 9]

filename = "numbers.json"
with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)

例:取

import json

filename = "numbers.json"
with open(filename) as f_obj:
    numbers = json.load(f_obj)

print(numbers)
[1, 3, 5, 7, 9]

例1:从数据地址下载json文件,这里从GitHub上下载

from __future__ import (absolute_import, division, print_function, unicode_literals)
from urllib.request import urlopen
import json

# 网址:the url
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
response = urlopen(json_url)
req = response.read()                                # 读取数据
with open('btc_close_2017_urllib.json', 'wb') as f:  # 将数据写入文件
    f.write(req)
file_urllib = json.loads(req)                        # 加载json格式
print(file_urllib)

下载得到的数据:
在这里插入图片描述
例2:第二种下载方法requests

import requests

# 网址:the url
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
req = requests.get(json_url)                           # 读取数据
with open('btc_close_2017_urllib.json', 'w') as f:     # 将数据写入文件
    f.write(req.text)
file_requests = req.json()

例3:从下载得到的文件中提取数据

import json

"""文件中的数据是多个字典,字典都包含相同的键,对应不同的值,这里遍历所有字典,输出每个字典里键对应的值"""
# 将数据加载到一个列表中
filename = 'btc_close_2017_urllib.json'  # 文件
with open(filename) as f:                # 打开文件
    btc_data = json.load(f)              # 加载文件
# 打印每一天的信息
for btc_dict in btc_data:                # 遍历字典
    date = btc_dict['date']              # 每个字典中都有,日期
    month = btc_dict['month']            # 月份
    week = btc_dict['week']              # 周
    weekday = btc_dict['weekday']        # 周末
    close = btc_dict['close']            # 收盘价
    print("{} 是 {} 月, 第 {} 周, 星期{}, 收盘价是 {} RMB".format(date, month, week, weekday, close))

数据太多,部分如下
在这里插入图片描述

例4:收盘价

import json
import pygal

"""文件中的数据是多个字典,字典都包含相同的键,对应不同的值,这里遍历所有字典,输出每个字典里键对应的值"""
# 将数据加载到一个列表中
filename = 'btc_close_2017_urllib.json'  # 文件
with open(filename) as f:                # 打开文件
    btc_data = json.load(f)              # 加载文件
# 打印每一天的信息
for btc_dict in btc_data:                # 遍历字典
    date = btc_dict['date']              # 每个字典中都有,日期
    month = int(btc_dict['month'])            # 月份
    week = int(btc_dict['week'])              # 周
    weekday = btc_dict['weekday']             # 周末
    close = int(float(btc_dict['close']))     # 收盘价
    print("{} 是 {} 月, 第 {} 周, 星期{}, 收盘价是 {} RMB".format(date, month, week, weekday, close))

# 创建5个列表,分别存储日期和收盘价
dates = []
months = []
weeks = []
weekdays = []
close = []
# 每一天的信息
for btc_dict in btc_data:
    dates.append(btc_dict['date'])
    months.append(int(btc_dict['month']))
    weeks.append(int(btc_dict['week']))
    weekdays.append(btc_dict['weekday'])
    close.append(int(float(btc_dict['close'])))

line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', close)
line_chart.render_to_file('收盘价折线图($).svg')

在这里插入图片描述
例5:收盘价对数变换折线图

import json
import pygal
import math
from itertools import groupby

"""文件中的数据是多个字典,字典都包含相同的键,对应不同的值,这里遍历所有字典,输出每个字典里键对应的值"""
# 将数据加载到一个列表中
filename = 'btc_close_2017_urllib.json'  # 文件
with open(filename) as f:                # 打开文件
    btc_data = json.load(f)              # 加载文件
# 打印每一天的信息
for btc_dict in btc_data:                # 遍历字典
    date = btc_dict['date']              # 每个字典中都有,日期
    month = int(btc_dict['month'])            # 月份
    week = int(btc_dict['week'])              # 周
    weekday = btc_dict['weekday']             # 周末
    close = int(float(btc_dict['close']))     # 收盘价
    print("{} 是 {} 月, 第 {} 周, 星期{}, 收盘价是 {} RMB".format(date, month, week, weekday, close))

# 创建5个列表,分别存储日期和收盘价
dates = []
months = []
weeks = []
weekdays = []
close = []
# 每一天的信息
for btc_dict in btc_data:
    dates.append(btc_dict['date'])
    months.append(int(btc_dict['month']))
    weeks.append(int(btc_dict['week']))
    weekdays.append(btc_dict['weekday'])
    close.append(int(float(btc_dict['close'])))

"""收盘价折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', close)
line_chart.render_to_file('收盘价折线图($).svg')

"""收盘价对数变换折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价对数变换($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
close_log = [math.log10(_) for _ in close]    # 这里不一样
line_chart.add('log收盘价', close_log)
line_chart.render_to_file('收盘价对数变换折线图($).svg')

在这里插入图片描述
例6:收盘价周日均值和收盘价星期均值

import json
import pygal
import math
from itertools import groupby

"""文件中的数据是多个字典,字典都包含相同的键,对应不同的值,这里遍历所有字典,输出每个字典里键对应的值"""
# 将数据加载到一个列表中
filename = 'btc_close_2017_urllib.json'  # 文件
with open(filename) as f:                # 打开文件
    btc_data = json.load(f)              # 加载文件
# 打印每一天的信息
for btc_dict in btc_data:                # 遍历字典
    date = btc_dict['date']              # 每个字典中都有,日期
    month = int(btc_dict['month'])            # 月份
    week = int(btc_dict['week'])              # 周
    weekday = btc_dict['weekday']             # 周末
    close = int(float(btc_dict['close']))     # 收盘价
    print("{} 是 {} 月, 第 {} 周, 星期{}, 收盘价是 {} RMB".format(date, month, week, weekday, close))

# 创建5个列表,分别存储日期和收盘价
dates = []
months = []
weeks = []
weekdays = []
close = []
# 每一天的信息
for btc_dict in btc_data:
    dates.append(btc_dict['date'])
    months.append(int(btc_dict['month']))
    weeks.append(int(btc_dict['week']))
    weekdays.append(btc_dict['weekday'])
    close.append(int(float(btc_dict['close'])))

"""收盘价折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', close)
line_chart.render_to_file('收盘价折线图($).svg')

"""收盘价对数变换折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价对数变换($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
close_log = [math.log10(_) for _ in close]
line_chart.add('log收盘价', close_log)
line_chart.render_to_file('收盘价对数变换折线图($).svg')


def draw_line(x_data, y_data, title, y_legend):
    xy_map = []
    for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0]):
        y_list = [v for _, v in y]
        xy_map.append([x, sum(y_list) / len(y_list)])
    x_unique, y_mean = [*zip(*xy_map)]
    line_chart = pygal.Line()           # 画图
    line_chart.title = title            # 设置标题
    line_chart.x_labels = x_unique
    line_chart.add(y_legend, y_mean)    # 添加了Y轴标签
    line_chart.render_to_file(title+'.svg')  # 保存为.svg文件
    return line_chart


idx_month = dates.index('2017-12-01')
line_chart_month = draw_line(months[:idx_month], close[:idx_month],
                             '收盘价月日均值($)', '月日均值')
line_chart_month

inx_week = dates.index('2017-12-01')
line_chart_week = draw_line(weeks[:idx_month], close[1:idx_month],
                            '收盘价周日均值($)', '周日均值')
line_chart_week


idx_week = dates.index('2017-12-11')
wd = ['Monday', 'Tuesday', 'Wednesday',
      'Thursday', 'Friday', 'Saturday', 'Sunday']
weekdays_int = [wd.index(w) + 1 for w in weekdays[1:idx_week]]
line_chart_weekday = draw_line(
    weekdays_int, close[1:idx_week], '收盘价星期均值($)', '星期均值')
line_chart_weekday.x_labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
line_chart_weekday.render_to_file('收盘价星期均值($).svg')
line_chart_weekday

这里图就不贴了

最后:收盘价数据仪表盘

import json
import pygal
import math
from itertools import groupby

"""文件中的数据是多个字典,字典都包含相同的键,对应不同的值,这里遍历所有字典,输出每个字典里键对应的值"""
# 将数据加载到一个列表中
filename = 'btc_close_2017_urllib.json'  # 文件
with open(filename) as f:                # 打开文件
    btc_data = json.load(f)              # 加载文件
# 打印每一天的信息
for btc_dict in btc_data:                # 遍历字典
    date = btc_dict['date']              # 每个字典中都有,日期
    month = int(btc_dict['month'])            # 月份
    week = int(btc_dict['week'])              # 周
    weekday = btc_dict['weekday']             # 周末
    close = int(float(btc_dict['close']))     # 收盘价
    print("{} 是 {} 月, 第 {} 周, 星期{}, 收盘价是 {} RMB".format(date, month, week, weekday, close))

# 创建5个列表,分别存储日期和收盘价
dates = []
months = []
weeks = []
weekdays = []
close = []
# 每一天的信息
for btc_dict in btc_data:
    dates.append(btc_dict['date'])
    months.append(int(btc_dict['month']))
    weeks.append(int(btc_dict['week']))
    weekdays.append(btc_dict['weekday'])
    close.append(int(float(btc_dict['close'])))


"""收盘价折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', close)
line_chart.render_to_file('收盘价折线图($).svg')

"""收盘价对数变换折线图"""
line_chart = pygal.Line(x_label_rotation=20, show_minoe_x_labels=False)
line_chart.title = '收盘价对数变换($)'
line_chart.x_labels = dates
N = 20   # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
close_log = [math.log10(_) for _ in close]
line_chart.add('log收盘价', close_log)
line_chart.render_to_file('收盘价对数变换折线图($).svg')


def draw_line(x_data, y_data, title, y_legend):
    xy_map = []
    for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0]):
        y_list = [v for _, v in y]
        xy_map.append([x, sum(y_list) / len(y_list)])
    x_unique, y_mean = [*zip(*xy_map)]
    line_chart = pygal.Line()           # 画图
    line_chart.title = title            # 设置标题
    line_chart.x_labels = x_unique
    line_chart.add(y_legend, y_mean)    # 添加了Y轴标签
    line_chart.render_to_file(title+'.svg')  # 保存为.svg文件
    return line_chart


idx_month = dates.index('2017-12-01')
line_chart_month = draw_line(months[:idx_month], close[:idx_month],
                             '收盘价月日均值($)', '月日均值')
line_chart_month

inx_week = dates.index('2017-12-01')
line_chart_week = draw_line(weeks[:idx_month], close[1:idx_month],
                            '收盘价周日均值($)', '周日均值')
line_chart_week


idx_week = dates.index('2017-12-11')
wd = ['Monday', 'Tuesday', 'Wednesday',
      'Thursday', 'Friday', 'Saturday', 'Sunday']
weekdays_int = [wd.index(w) + 1 for w in weekdays[1:idx_week]]
line_chart_weekday = draw_line(
    weekdays_int, close[1:idx_week], '收盘价星期均值($)', '星期均值')
line_chart_weekday.x_labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
line_chart_weekday.render_to_file('收盘价星期均值($).svg')
line_chart_weekday

with open('收盘价Dashboard.html', 'w', encoding='utf8') as html_file:
    html_file.write(
        '<html><head><title>收盘价Dashboard</title><meta charset="utf-8"></head><body>\n')
    for svg in [
            '收盘价折线图($).svg', '收盘价对数变换折线图($).svg', '收盘价月日均值($).svg',
            '收盘价周日均值($).svg', '收盘价星期均值($).svg'
    ]:
        html_file.write(
            '    <object type="image/svg+xml" data="{0}" height=500></object>\n'.format(svg))  # 1
    html_file.write('</body></html>')

相当于把上面得到的五张图放在一个HTML文件中
在这里插入图片描述


第十六章. 使用API

16.1 requests

例:找出GitHub中星级最高的python项目
1、先查看能否成功响应

import requests

# 执行API调用并存储响应
url = "https://api.github.com/search/repositories?q=language:python&sort=stars"
r = requests.get(url)
print("Status code:", r.status_code)  # 状态码

# 将API响应存储在一个变量中
response_dict = r.json()

# 处理结果
print(response_dict.keys())
Status code: 200
dict_keys(['total_count', 'incomplete_results', 'items'])

2、处理响应字典

import requests

# 执行API调用并存储响应
url = "https://api.github.com/search/repositories?q=language:python&sort=stars"
r = requests.get(url)
print("Status code:", r.status_code)  # 状态码

# 将API响应存储在一个变量中
response_dict = r.json()
print("Total repositories:", response_dict['total_count'])

# 探索有关仓库的信息
repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))  # 打印有多少个仓库数,也就是python项目数

# 研究第一个仓库
repo_dict = repo_dicts[0]
print("\nKeys:", len(repo_dict))
for key in sorted(repo_dict.keys()):  # 排序打印
    print(key)

在这里插入图片描述
3、继续研究第一个项目

# 研究第一个仓库
repo_dict = repo_dicts[0]
print("\nSelected information about first repository:")
print("Name:", repo_dict['name'])                # 项目名字
print("Owner:", repo_dict['owner']['login'])     # 所有者
print("Stars:", repo_dict['stargazers_count'])   # 星数
print("Repository:", repo_dict['html_url'])      # 地址
print("Created:", repo_dict['created_at'])       # 创建时间
print("Updated:", repo_dict['updated_at'])       # 修改时间
print("Description:", repo_dict['description'])  # 项目描述
Status code: 200
Total repositories: 8901091
Repositories returned: 30

Selected information about first repository:
Name: public-apis
Owner: public-apis
Stars: 213233
Repository: https://github.com/public-apis/public-apis
Created: 2016-03-20T23:49:42Z
Updated: 2022-10-28T02:38:42Z
Description: A collective list of free APIs

4、使用Pygal可视化仓库

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

# 执行API调用并存储响应
url = "https://api.github.com/search/repositories?q=language:python&sort=stars"
r = requests.get(url)
print("Status code:", r.status_code)  # 状态码

# 将API响应存储在一个变量中
response_dict = r.json()
print("Total repositories:", response_dict['total_count'])

# 探索有关仓库的信息
repo_dicts = response_dict['items']

names, stars = [], []
for repo_dict in repo_dicts:
    names.append(repo_dict['name'])
    stars.append(repo_dict['stargazers_count'])

# 可视化
my_style = LS('#333366', base_style=LCS)
chart = pygal.Bar(style=my_style, x_label_rotation=45, show_legend=False) # 第二参数标签旋转,第三参数隐藏图例
chart.title = "Most-Starred Python Projects on GitHub"
chart.x_labels = names

chart.add('', stars)
chart.render_to_file('python_repos.svg')

在这里插入图片描述
5、调整图像

# 可视化
my_style = LS('#333366', base_style=LCS)

my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_legend = False
my_config.title_font_size = 24
my_config.label_font_size = 14
my_config.major_label_font_size = 18
my_config.truncate_label = 15
my_config.show_y_guides = False
my_config.width = 1000

chart = pygal.Bar(my_config, style=my_style)
chart.title = "Most-Starred Python Projects on GitHub"
chart.x_labels = names

chart.add('', stars)
chart.render_to_file('python_repos.svg')

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zdb呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值