Python绘图库的封装与学习

matplotlib是Python常用的绘图库,在ipython notebook中结合matplotlib来进行交互绘图做数据分析非常方便。
matplotlib提供的原始API已经非常方便,但是我个人的需求需要更加简便化,所以针对个人进行再一次封装,以便进行傻瓜式调用。

1
2
3
4
# coding=utf-8
import matplotlib.pyplot as plt
import matplotlib.pylab as mlab
import numpy as np

1.封装散点图接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def scatterplot(ax,
x_data_list,
y_data_list,
color_list,
x_label="",
y_label="",
title="",
yscale_log=False):
"""绘制散点图
封装matplotlib提供的原始scatter接口,使其可以对一组会多组数据的输入进行绘制。
Args:
ax: plt.subplot(), 一个子图
x_data_list: [[], []], 二维list
y_data_list: [[], []], 二维list
color_list: ["r", "b"], 颜色list
x_label: str, 横坐标名称
y_label: str, 纵坐标名称
title: str, 当前子图的名称
Returns:
None
"""
# Plot the data, set the size (s), color and transparency (alpha)
# of the points
for i in range(len(x_data_list)):
ax.scatter(x_data_list[i],
y_data_list[i],
s=10,
color=color_list[i],
alpha=0.75)
if yscale_log == True:
ax.set_yscale('log')
# Label the axes and provide a title
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)

对于上面封装好的接口,模拟三组输入数据看看效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ax = plt.subplot()
x_data_list = [np.random.randn(100) for i in range(3)]
y_data_list = [np.random.randn(100) for i in range(3)]
color_list = ["r", "g", "b"]
x_label = "X axis"
y_label = "Y axis"
title = "X-Y scatterploter"
scatterplot(ax,
x_data_list,
y_data_list,
color_list,
x_label,
y_label,
title,
yscale_log=False)

png

2. 封装折线图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def lineplot(ax,
x_data_list,
y_data_list,
color_list,
x_label="",
y_label="",
title=""):
"""绘制散点图
封装matplotlib提供的原始scatter接口,使其可以对一组会多组数据的输入进行绘制。
Args:
ax: plt.subplot(), 一个子图
x_data_list: [[], []], 二维list
y_data_list: [[], []], 二维list
color_list: ["r", "b"], 颜色list
x_label: str, 横坐标名称
y_label: str, 纵坐标名称
title: str, 当前子图的名称
Returns:
None
"""
# Plot the best fit line, set the linewidth (lw), color and
# transparency (alpha) of the line
for i in range(len(x_data_list)):
ax.plot(x_data_list[i],
y_data_list[i],
lw=2,
color=color_list[i],
alpha=1)
# Label the axes and provide a title
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)

对于上面封装好的接口,模拟两组数据模拟y=x*x的效果.

1
2
3
4
5
6
7
8
9
10
import math
ax = plt.subplot()
x_data_list = [[i for i in range(-100, 100)] for j in range(2)]
y_data_list = [[math.pow(i, j + 1) for i in range(-100, 100)]
for j in range(2)]
color_list = ['r', 'g']
x_label = 'X axis'
y_label = 'Y axis'
title = 'X & Y'
lineplot(ax, x_data_list, y_data_list, color_list, x_label, y_label, title)

png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def histplot(ax,
x_data_list,
num_bins,
color_list,
alpha_list=[1.0, 0.5],
x_label="",
y_label="",
title="",
cumulative=False,
normed=1):
"""绘制直方图
Args:
ax: plt.subplot(),子图
x_data_list: list, n组数据
num_bins: int, 直方图的区间数
color_list: list(str), 颜色
alpha_list: list(float), 透明度
x_label: str,x轴信息
y_label: str, y轴信息
title: 当前子图的名称
cumulative: bool, 是否采用累积方式
normed: 总的概率值
Return:
None
"""
for i in range(len(x_data_list)):
ax.hist(x_data_list[i],
50,
cumulative=False,
normed=1,
facecolor=color_list[i],
alpha=alpha_list[i])
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.title(title)

模拟两组正太分布数据:

1
2
3
4
5
6
7
8
9
10
11
12
x_data_list = [
100 + 15 * np.random.randn(10000), 100 + 10 * np.random.randn(10000)
]
ax = plt.subplot()
histplot(ax=ax,
x_data_list=x_data_list,
num_bins=50,
color_list=["r", "g"],
x_label="X axis",
y_label="Y axis",
title="X & Y")
plt.show()

png

4.柱状图接口

4.1 堆叠柱状图

1
2
3
4
5
6
7
8
9
10
11
12
name_list = ['Monday', 'Tuesday', 'Friday', 'Sunday']
num_list = [1.5, 0.6, 7.8, 6]
num_list1 = [1, 2, 3, 1]
plt.bar(range(len(num_list)), num_list, label='boy', fc='y')
plt.bar(range(len(num_list)),
num_list1,
bottom=num_list,
label='girl',
tick_label=name_list,
fc='r')
plt.legend()
plt.show()

png

4.2 并列柱状图

1
2
3
4
5
6
7
8
9
10
11
12
13
name_list = ['Monday','Tuesday','Friday','Sunday']
num_list = [1.5,0.6,7.8,6]
num_list1 = [1,2,3,1]
x =list(range(len(num_list)))
total_width, n = 0.8, 2
width = total_width / n
plt.bar(x, num_list, width=width, label='boy',fc = 'y')
for i in range(len(x)):
x[i] = x[i] + width
plt.bar(x, num_list1, width=width, label='girl',tick_label = name_list,fc = 'r')
plt.legend()
plt.show()

png

python 对象

1.创建python类

python类要注意驼峰式命名。

添加属性

可以通过点记法对空类进行后创建属性😅,这个真的是太神奇了。

1
2
3
4
5
class Point:
Pass
p = Point()
p.x = 1
p.y = 2

2.初始化函数和构造函数

1
2
3
4
5
6
7
class Point:
def __init__(self, x = 0, y = 0):#在这里可以设置一个默认值
self.move(x, y)
def move(self, x, y):
self.x = x
self.y = y

3.解释自己

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Point:
'This is a new class by yelin'
def __init__(self, x = 0, y = 0):
"""
This is a function, it move center of the
class to a new place
"""
self.move(0, 0)
def move(self, x, y):
"I want to add some comment."
self.x = x
self.y = y

4.模块

千万不要使用如下写法, 因为它为导致命名空间的混乱,不利于查看源文件,代码维护变成噩梦,import * 会破坏代码补全:

1
from database import *

4.1 组织模块

一个package就是放到一个文件夹里的模块集合,

1
2
3
4
5
6
7
8
9
10
11
12
```python
parent_directory/
main.py
ecommerce/
__init__.py
database.py
products.py
payments/
__init__.py
paypal.py
authorizenet.py

5.数据访问

双下划线开头的变量并不是不可被访问的, 被”命名改编“后,只需要调用改编之后的变量名就可以调用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SecretString:
'''A not-at-all secure way to store a secret string.'''
def __init__(self, plain_string, pass_phrase):
self.__plain_string = plain_string
self.__pass_phrase = pass_phrase
def decrypt(self, pass_phrase):
'''Only show the string if the pass_phrase is correct'''
if pass_phrase == self.__pass_phrase:
return self.__plain_string
else:
return
secret_string = SecretString("ACME: Top Secret", "antwerp")
print(secret_string._SecretString__plain_string)

6.重载

1
2
3
4
class Friend(Concat):
def __init__(self, name, email, phone):
super().__init__(name, email)
self.phone = phone

开发环境搭建

  • Ubuntu上的开发环境
    • git server
    • zsh
    • vim
    • xrdp远程桌面连接
    • 开发工具
      • pycharm
  • Windows上的开发环境
  • MacOX上的开发环境

1. Ubuntu上的开发环境

1.1 git server

1
2
3
4
5
6
7
8
9
10
sudo apt-get install git
sudo adduser git
su git
cd ~
mkdir sample.git
cd sample.git
git --bare init

1.2 zsh

如果你之前已经有一台ubuntu的服务器上安装了zsh,那么只需要把.oh-my-zsh.zshrc文件拷贝过去。

1
2
scp -r .oh-my-zsh [email protected]:/folder/
scp -r .zshrc [email protected]:/folder/

如果是第一次使用zsh

1
2
3
4
5
sudo apt-get install zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
sudo chsh -s /bin/zsh

LeetCode_35 Contains Duplicate

题目描述:

1
2
3
Given an array of integers, find if the array contains any duplicates.
Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

输入样例:

1
2
3
4
5
6
7
8
Input: [1,2,3,1]
Output: true
Input: [1,2,3,4]
Output: false
Input: [1,1,1,3,3,4,3,2,4,2]
Output: true

Code:

1
2
def containsDuplicate(self, nums):
return len(nums) != len(set(nums))

LeetCode_35 Rotate Array

题目描述:

1
Given an array, rotate the array to the right by k steps, where k is non-negative.

输入样例:

1
2
3
4
5
6
7
8
9
10
11
12
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]

Code:

1
2
3
4
5
6
7
8
9
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: void Do not return anything, modify nums in-place instead.
"""
k = k % len(nums)
for i in range(-k, 0):
nums.insert(k + i, nums.pop(i))

LeetCode_35 Move Zeroes

题目描述:

1
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.

输入样例:

1
2
3
4
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]

Code:
方法一:统计0的个数—>前边删除0后边添加0

1
2
3
4
5
6
7
8
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
for i in range(nums.count(0)):
nums.remove(0)
nums.append(0)

方法二:这个方法比上面复杂一些,因为这个方法还可以保证被删掉的0这个node被移到list后面,因此可以保证指针和0的相对位置也不变。因为在python的list里面,0是一个Node对象形式存储的。PS:对于这道题,倒是没必要考虑这么复杂。

1
2
3
4
5
6
7
8
9
10
11
12
13
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
i, nums_len = 0, len(nums)
while i < nums_len:
if nums[i] == 0:
tmp = nums.pop(i)
nums.append(tmp)
nums_len -= 1
else:
i += 1

LeetCode_35 Remove Duplicates from Sorted Array

题目描述:

1
2
3
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory

输入样例:

1
2
3
4
5
Example 1:
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.

1
2
3
4
5
Example 2:
Given nums = [0,0,1,1,1,2,2,3,3,4],
Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.
It doesn't matter what values are set beyond the returned length.

思路和code
这道题的题意非常地费解,简单理解为数组去重,但是要求只对原数组去重,给入的是nums,去重后的也必须是这个nums,也就是说指针必须不变。因此,重新开辟新的数组来寸去重后的数,最后虽然返回的值一样,但是会报错,因为不是之前的那个nums了。

1
2
3
4
5
6
7
8
# 错误的做法
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
return len(set(nums)) #set是比较好用的去重函数,但是内部实现过程不是删除nums中的重复数,
#而是新开的一个数组来存,返回新开的数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 正确的做法
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums or len(nums) == 0:
return 0
if len(nums) == 1:
return len(nums)
num_len, i = len(nums) - 1, 0
while i < num_len - 1:
if(nums[i] == nums[i + 1]):
nums.pop(i + 1)
num_len -= 1
else:
i += 1
if nums[-1] == nums[-2]:
nums.pop(-1)
return len(nums)

LeetCode_35 Reverse Integer

题目描述:

1
Given a 32-bit signed integer, reverse digits of an integer.

输入样例:

1
2
3
4
5
6
7
8
9
10
11
Example 1:
Input: 123
Output: 321
Example 2:
Input: -123
Output: -321
Example 3:
Input: 120
Output: 21

提醒:

1
2
Note:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

code:

1
2
3
4
5
6
7
8
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
sign = [1,-1][x < 0]
res = sign * int(str(abs(x))[::-1])
return res if -(2**31)-1 < res < 2**31 else 0

LeetCode_35 Two Sum

题目描述:

1
2
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.

输入样例:

1
2
3
4
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

解法一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype
for i in range(len(nums)):
num_find = target - nums[i]
try:
index_find = nums.index(num_find)
if index_find != i:
return [i, index_find]
else:
pass
except:
pass

解法二:

1
2
3
4
5
6
7
8
9
10
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype
tmp = {}
for i in range(len(nums)):
if target - nums[i] in tmp:
return [i, tmp[target-nums[i]]]
tmp[nums[i]] = i