作为简单易学的编程语言,想要入门还是比较容易的,今天我们来一篇超级长文,一次性扫盲Python、NumPy 和 Pandas,文末提供Python 技术交流群,欢迎加入,喜欢本文,点赞、收藏。

搭建语言环境

我们首先来了解下如何安装和搭建 Python 语言环境

Python 版本的选择

当前流行的 Python 版本有两个,2.X 和 3.X,由于 2.X 即将不再维护,所以我建议直接使用 3.X 版本作为你的主要版本。

IDE 的选择

目前市面上流行着很多的 Python 编辑器,比如 Sublime,Notebook++ 等,不过我还是推荐如下两个

PyCharm:这是一个跨平台的 Python 开发工具,不但拥有常规的调试、语法高亮,智能提示等功能外,还自带多个数据库连接器,使你在调试数据库的时候也能得心应手,不再忙于到处下载各种数据库客户端。

Jupyter:这个是一个 web 式的在线编辑器,每次运行一行代码,你都可以立即得到结果,非常方便,在代码调试阶段,用处无限。

Python 软件的安装

如果你是 Linux 或者 MacOS 操作系统,那么一般会自带 Python2.6 的版本。如果想要安装 3.X 的版本,需要自行编译安装,如果没有 Linux 操作基础的话,建议还是使用 Windows。

如果是 Windows 操作系统,可以直接到 Python 官网下载 .exe 安装包,一路下一步即可完成安装。

Python 基础语法

Hello World

相信大家都有这种经验,学习任何一门语言时,入门的都是输出 Hello World,下面我们就来看看如何使用 Python 来输入 Hello World

print("Hello World")
sum = 1 + 2
print("sum = %d" %sum)
>>>
Hello World
sum = 3

print 函数,用来在控制台打印输出,sum = 语法是声明变量并赋值,%d 是用来做字符串替换。

数据类型和变量

列表

list1 = ["1", "2", "test"]
print(list1)
list1.append("hello")
print(lists)
>>>
['1', '2', 'test']
['1', '2', 'test', 'hello']

list 是 Python 内置的一种数据类型,是一种有序的集合,可以随时添加和删除其中的元素。

元组

tuple1 = ("zhangsan", "lisi")
print(tuple1[0])
>>>
zhangsan

tuple 和 list 非常类似,但是 tuple 一旦初始化就不能修改.

字典

dict1 = {"name1": "zhangsan", "name2": "lisi", "name3": "wangwu"}
dict1["name1"]
>>>
'zhangsan'

Python 内置了字典:dict 全称 dictionary,在其他语言中也称为 map,使用键-值(key-value)存储,具有极快的查找速度。

集合

s = set([1, 2, 3])
print(s)
>>>
{1, 2, 3}

set 和 dict 类似,也是一组 key 的集合,但不存储 value。由于 key 不能重复,所以,在 set 中,没有重复的 key。

变量

变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型。

a = 1
a = 3
print(a)
>>>
3

条件判断

age = 30
if age >= 18:print('your age is', age)print('good')
else:Print('your are not belong here')
>>>
your age is 30
good

if … else… 是非常经典的条件判断语句,if 后面接条件表达式,如果成立,则执行下面的语句,否则执行 else 后面的语句。同时还要注意,Python 语言是采用代码缩进的方式来判断代码块的,一般是四个空格或者一个 tab,两者不要混用。

循环语句

names = {"zhangsan", "lisi", "wangwu"}
for name in names:print(name)
>>>
lisi
zhangsan
wangwu

names 是一个集合,为可迭代对象,使用 for 循环,name 会依次被赋值给 names 中的元素值。

sum = 0
n = 99
while n > 0:sum = sum + nn = n - 2
print(sum)
>>>
2500

在循环内部变量 n不断自减,直到变为-1时,不再满足 while 条件,循环退出。

高级特性

切片

L = ['zhangsan', 'lisi', 'wangwu', 'zhaoliu']
print(L[1])
print(L[1:3])
>>>
lisi
['lisi', 'wangwu']

Python 中,下标都是从 0 开始的,且都是左闭右开区间

迭代

对于列表、元组和字典,都是可迭代对象,可以使用 for 来进行迭代取值

L = ['zhangsan', 'lisi', 'wangwu', 'zhaoliu']
D = {"zhangsan":1, "lisi": 2, "wangwu": 3, "zhaoliu": 4}
for l in L:print(l)
print('\n')
for k,v in D.items():print("键:", k, ",", "值", v)
>>>
zhangsan
lisi
wangwu
zhaoliu键: zhangsan , 值 1
键: lisi , 值 2
键: wangwu , 值 3
键: zhaoliu , 值 4

对于字典,使用 items(),可是同时遍历键值对

函数

调用函数

Python 内置了很多有用的函数,我们可以直接调用。

>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
>>> max(1, 2)
2
>>> max(2, 3, 1, -5)
3

在调用函数时,如果传入的参数有问题,程序会抛出异常。
这里包含了 Python 中所有的内置函数:
https://docs.python.org/zh-cn/3/library/functions.html

定义函数

在 Python 中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

def add(num1, num2):return num1 + num2result = add(1,2)
print(result)
>>>
3

在代码中,定义了一个叫做 add 的函数,它会接收两个参数,并且会返回他们之和。函数定义之后,可以使用函数名称后面跟()来调用,如果函数有返回值,可以赋给一个变量来接收。

模块

调用模块

Python 本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用。

import time
def sayTime():now = time.time()return nownowtime = sayTime()
print(nowtime)
>>>
1566550687.642805

使用 import 来导入模块,之后就可以调用该模块为我们提供的各种方法变量等。

模块说白了就是一组工具的集合,我们当然可以自己编写一些工具,然后组成自己的模块,供后面编程使用。

我们自己编写模块,一般目录结构如下

mytest
├─ __init__.py
├─ test1.py
└─ test2.py

现在我们就可以在其他的文件中引用并调用这两个 test 工具文件了

import mytest
mytest.test1

你应该注意到了 __init__.py 文件,这个文件可以是空文件,包含了 __init__.py 文件的文件夹就是一个”包“(Package)。如果我们需要像上面那样引用文件,就必须包含 __init__.py 文件。
安装第三方模块

在 Python 中,安装第三方模块,是通过包管理工具 pip 完成的。

一般来说,第三方库都会在 Python 官方的pypi.python.org网站注册,要安装一个第三方库,必须先知道该库的名称,可以在官网或者 pypi 上搜索,比如 Pillow 的名称叫Pillow,因此,安装 Pillow 的命令就是:

pip install Pillow

面向对象编程

类和实例

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如 Student 类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

在 Python 中,使用 class 关键字来定义类

class Student(object):pass

定义好类之后,就可以实例化该类了

zhangsan = Student()
zhangsan.age = 20
print(Student)
print(zhangsan)
print(zhangsan.age)
>>>
<class '__main__.Student'>
<__main__.Student object at 0x00EA7350>
20

此时,变量 zhangsan 就是类 Student 的一个实例了。同时我们还给 zhangsan 绑定了一个属性 age 并赋值。

请谨记面向对象三大基本要素:抽象,封装,继承。如果你当前对这些还没有太多的概念的话,也不要紧,你可以在后面的学习中慢慢体会。

IO 编程

读取文件,是后面要经常用到的操作,在 Python 中,使用 open 函数可以非常方便的打开一个文件

f = open('/Users/tanxin/test.txt', 'r')
f.read()
f.close()

标示符 ‘r’ 表示读,这样,我们就成功地打开了一个文件,然后使用 read 函数来读取文件内容,最后用 close 来关闭文件。
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的

使用 with 来方便的打开文件

with open('/Users/tanxin/test.txt', 'r') as f:print(f.read())

with 语句帮助我们完成了 close 的过程

文件读取还有 readline() 和 readlins() 两个函数。readline() 一次读取一行数据,readlines() 一次读取所有内容并按行返回一个列表。

正则表达式

正则表达式是一个很大的学科,其中的内容是完全可以单独写满一本书的,我们这里只做些简单的介绍。

Python 中提供了 re 模块来做正则

import re
str1 = "010-56765"
res = re.match(r'(\d{3})-(\d{5})', str1)
print(res)
print(res.group(0))
print(res.group(1))
print(res.group(2))
>>>
<re.Match object; span=(0, 9), match='010-56765'>
010-56765
010
56765

match() 方法判断是否匹配,如果匹配成功,返回一个 Match 对象,否则返回 None
配合 group 方法,可以有效的提取出字字符串。

requests 库简介

requests 库,是一个非常常用的 HTTP 网络请求库,后面的爬虫课程,我们会大量的使用它。

import requests
r = requests.get('https://www.baidu.com')
r = requests.post('http://test.com/post', data = {'key':'value'})
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://test.com/get", params=payload)

此时的 r 是一个 response 对象,我们可以从中获取到相关信息

r.text  # 获取响应内容
r.content  # 以字节的方式读取响应信息
response.encoding = "utf-8"  # 改变其编码
html = response.text  # 获得网页内容
binary__content = response.content  # 获得二进制数据
raw = requests.get(url, stream=True)  # 获得原始响应内容
headers = {'user-agent': 'my-test/0.1.1'}  # 定制请求头
r = requests.get(url, headers=headers)
cookies = {"cookie": "# your cookie"}  # cookie 的使用
r = requests.get(url, cookies=cookies)

这里只是简单介绍了 Python 的语法,如果要深入学习,你还需要花费更多的精力。不过世上无难事,只怕肯攀登。不要一直停留在入门的阶段,平时多找些刷题的网站,比如 Leetcode,online Judge 等等,在刷题的同时,更能锻炼自己的编程思维和算法能力。

NunmPy

NumPy 不仅仅是 Python 科学计算中使用最多的库,还是 SciPy,Pandas 等库的基础,它提供了更加高级有效的数据结构,是专门为科学计算而生的库。

NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用, 这种组合广泛用于替代 MatLab,是一个强大的科学计算环境,有助于我们通过 Python 学习数据科学或者机器学习。

ndarray 对象

NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。

ndarray 内部组成

  • 一个指向数据(内存或内存映射文件中的一块数据)的指针

  • 数据类型或 dtype,描述在数组中固定大小值的格子

  • 一个表示数组形状(shape)的元组,表示各维度大小的元组

  • 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要”跨过“的字节数

以上的概念,你可以在后面的学习中慢慢体会。

创建一个 ndarray 只需要调用 NumPy 的 array 函数即可

import numpy as np
a = np.array([1, 2, 2])
b = np.array([[1, 2], [5, 5], [7, 8]])
b[1,1]=10
print(a.shape)
print(b.shape)
print(a.dtype)
print(b)
>>>
(3,)
(3, 2)
int32
[[ 1  2][ 5 10][ 7  8]]

引用 numpy 库,调用 array 函数即可创建 ndarray。
创建一维数组只需要传入一个 list,创建多维数组,需要先把一个数组作为一个元素嵌套起来,再放入另一个数组当中。
提取 array 中的元素,可以使用切片的操作,b[1,1]。
使用 shape 属性来获取数组的形状(大小),如 b 数组为一个三行两列的数组。
使用 dtype 属性来获取数组中的数据类型。

数据类型

NumPy 支持的数据类型比 Python 内置的类型要多,下面罗列了一些常见类型

名称 描述
bool_ 布尔型数据类型(True 或者 False)
int_ 默认的整数类型
int32 整数(-2147483648 to 2147483647)
uint32 无符号整数(0 to 4294967295)
float32 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位

数据类型对象(dtype)

数据类型对象可以用来创建符合我们期望数据结构的数组

numpy.dtype(object, align, copy)
  • object:要转换的数据类型对象

  • align:如果为 True,填充字段使其类似 C 的结构体

  • copy:复制 dtype 对象,如果为 False,则是对内置数据类型对象的引用

使用 dtype 创建结构数组

mydtype = np.dtype({'names': ['name', 'age', 'sex'],'formats': ['S32', 'i4', 'S32']})
persons = np.array([('zhangsan', 20, 'man'),('lisi', 18, 'woman'),('wangwu', 30, 'man')],dtype=mydtype)
print(persons)
>>>
[(b'zhangsan', 20, b'man') (b'lisi', 18, b'woman') (b'wangwu', 30, b'man')]

首先通过 dtype 函数定义一个结构类型,然后再使用 array 函数构建数组,dtype 参数使用我们定义的即可。

数组属性

NumPy 数组的维数称为秩(rank),一维数组的秩为 1,二维数组的秩为 2,以此类推。

在 NumPy 中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。

很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。

下面罗列了比较重要的 ndarray 对象属性

属性 说明
ndim 秩,即轴的数量或维度的数量
shape 数组的维度
size 数组元素的总个数
dtype 元素的类型
itemsize 每个元素的大小,以字节为单位

创建特殊数组

空数组

x = np.empty([3,2], dtype=int)
print(x)
>>>
[[0 0][0 0][0 0]]

numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组

0 数组

zero1 = np.zeros(5)
zero2 = np.zeros(4, dtype=int)
print(zero1)
print(zero2)
>>>
[0. 0. 0. 0. 0.]
[0 0 0 0]

1 数组

one1 = np.ones(3)
one2 = np.ones(4, dtype=float)
print(one1)
print(one2)
>>>
[1. 1. 1.]
[1. 1. 1. 1.]

从已有数组创建数组

numpy.asarray,从列表,元组,多维数组创建数组

list1 = [1, 3, 5]
tuple1 = (1, 2, 3)
one = np.ones((2,3), dtype=int)
array1 = np.asarray(list1)
array2 = np.asarray(tuple1)
array3 = np.asarray(one)
print(array1)
print(array2)
print(array3)
>>>
[1 3 5]
[1 2 3]
[[1 1 1][1 1 1]]

numpy.frombuffer,以流的形式读入转化成数组

str1 = b"Hello world"
buffer1 = np.frombuffer(str1, dtype='S1')
print(buffer1)
>>>
[b'H' b'e' b'l' b'l' b'o' b' ' b'w' b'o' b'r' b'l' b'd']

numpy.fromiter,可以从可迭代对象中建立数组

range1 = range(5)
iter1 = np.fromiter(range1, dtype=int)
print(iter1)
>>>
[0 1 2 3 4]

numpy.arange,从数值范围创建数组

myarray1 = np.arange(5)
print(myarray1)
>>>
[0 1 2 3 4]

numpy.linspace,建立一个等差数列的数组

myarray2 = np.linspace(1,9,5)
print(myarray2)
>>>
[1. 3. 5. 7. 9.]

数组操作

切片和索引

ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。

ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
a = np.arange(10)
print(a)
s = slice(2,7,2)   # 从索引 2 开始到索引 7 停止,间隔为2
print (a[s])
>>>
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]

也可以使用冒号(:)来做切片

a = np.arange(10)
print(a)
b = a[2:7:2]   # 从索引 2 开始到索引 7 停止,间隔为 2
print(b)
>>>
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]

修改数组形状

nunpy.reshape,可以在不改变数据的条件下修改数组形状

a = np.arange(6)
print("原始数组:", a)
b = a.reshape(3, 2)
print("变换后数组:", b)
>>>
原始数组: [0 1 2 3 4 5]
变换后数组: [[0 1][2 3][4 5]]

numpy.ndarray.flat,是一个数组元素迭代器,可以依次处理每个元素

a = np.arange(9).reshape(3,3)
print ('原始数组:')
for row in a:print (row)#对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print ('迭代后的数组:')
for element in a.flat:print (element)
>>>
原始数组:
[0 1 2]
[3 4 5]
[6 7 8]
迭代后的数组:
0
1
2
3
4
5
6
7
8

翻转数组

numpy.transpose,可以对换数组的维度

a = np.arange(10).reshape(2, 5)
print(a)
b = a.transpose()
print(b)
>>>
[[0 1 2 3 4][5 6 7 8 9]]
[[0 5][1 6][2 7][3 8][4 9]]

连接数组

numpy.concatenate,用于连接相同形状的两个或多个数组

a = np.array([[1,2],[3,4]])print ('第一个数组:')
print (a)b = np.array([[5,6],[7,8]])print ('第二个数组:')
print (b)# 两个数组的维度相同print ('沿轴 0 连接两个数组:')
print (np.concatenate((a,b)))print ('沿轴 1 连接两个数组:')
print (np.concatenate((a,b),axis = 1))
>>>
第一个数组:
[[1 2][3 4]]
第二个数组:
[[5 6][7 8]]
沿轴 0 连接两个数组:
[[1 2][3 4][5 6][7 8]]
沿轴 1 连接两个数组:
[[1 2 5 6][3 4 7 8]]

分割数组

numpy.split,可以将数组分割为子数组

a = np.arange(9)print ('第一个数组:')
print (a)print ('将数组分为三个大小相等的子数组:')
b = np.split(a,3)
print (b)print ('将数组在一维数组中表明的位置分割:')
b = np.split(a,[4,7])
print (b)
>>>
第一个数组:
[0 1 2 3 4 5 6 7 8]将数组分为三个大小相等的子数组:
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]将数组在一维数组中表明的位置分割:
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]

另外还有对于数组元素的添加与删除操作

函数 描述
resize 返回指定形式的新数组
append 将值添加到数组末尾
insert 延指定轴将数值插入到指定下标之前
delete 删掉某个轴的子数组,返回删除后的新数组
unique 查找数组内的唯一元素

NumPy 统计运算

计算最大最小值

numpy.amin(),计算数组中延指定轴的最小值

numpy.amax(),计算数组中延指定轴的最大值

a = np.array([[3,7,5],[8,4,3],[2,4,9]])
print ('数组是:')
print (a)
print ('调用 amin() 函数:')
print (np.amin(a,1))
print ('再次调用 amin() 函数:')
print (np.amin(a,0))
print ('调用 amax() 函数:')
print (np.amax(a))
print ('再次调用 amax() 函数:')
print (np.amax(a, axis =  0))
>>>
数组是:
[[3 7 5][8 4 3][2 4 9]]
调用 amin() 函数:
[3 3 2]
再次调用 amin() 函数:
[2 4 3]
调用 amax() 函数:
9
再次调用 amax() 函数:
[8 7 9]

不指定 axis 时,会在整个数组中查找最大或最小。
axis = 0,是对每一列进行操作,即把数组看成 [3, 8, 2],[7, 4, 4],[5, 3, 9],从中选出最大或最小
axis = 1,是对每一行进行操作,即把数组看成 [3, 7, 5],[8, 4, 3],[2, 4, 9]。

这里的 axis 不是很容易理解,还希望你能在这里多花费些时间,去实践,去领悟。

numpy.ptp,可以计算数组元素中最大值与最小值之差

a = np.array([[3,7,5],[8,4,3],[2,4,9]])
print ('我们的数组是:')
print (a)
print ('调用 ptp() 函数:')
print (np.ptp(a))
print ('沿轴 1 调用 ptp() 函数:')
print (np.ptp(a, axis =  1))
print ('沿轴 0 调用 ptp() 函数:')
print (np.ptp(a, axis =  0))
>>>
我们的数组是:
[[3 7 5][8 4 3][2 4 9]]
调用 ptp() 函数:
7
沿轴 1 调用 ptp() 函数:
[4 5 7]
沿轴 0 调用 ptp() 函数:
[6 3 6]

numpy.percentile,计算百分位数,表示小于这个值的观察值的百分比

理解百分位数:第 p 个百分位数表示,它使得至少有 p% 的数据项小于等于这个值,且至少有 (100 - p)% 的数据项大于等于这个值。

例如:某个同学语文考试分数为 80,如果这个分数正好位于所有学生成绩的第 80 百分位数,那么即可知该成绩大于约 80% 人,约 20% 人的成绩高于该同学。

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)print ('调用 percentile() 函数:')
# 50% 的分位数,就是 a 里排序之后的中位数
print (np.percentile(a, 50)) # axis 为 0,在纵列上求
print (np.percentile(a, 50, axis=0)) # axis 为 1,在横行上求
print (np.percentile(a, 50, axis=1)) # 保持维度不变
print (np.percentile(a, 50, axis=1, keepdims=True))
>>>
数组是:
[[10  7  4][ 3  2  1]]
调用 percentile() 函数:
3.5
[6.5 4.5 2.5]
[7. 2.]
[[7.][2.]]

numpy.median,计算数组元素的中位数

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)
print(np.median(a))
>>>
3.5

可以看出,percentile 中 p 等于 50 时,就是中位数

numpy.mean,平均数

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)
print(np.mean(a))
>>>
4.5

numpy.average,计算加权平均值

a = np.array([1,2,3,4])
print ('数组是:')
print (a)
print ('调用 average() 函数:')
print (np.average(a))
wts = np.array([4,3,2,1])
print ('再次调用 average() 函数:')
print (np.average(a,weights = wts))
>>>
数组是:
[1 2 3 4]
调用 average() 函数:
2.5
再次调用 average() 函数:
2.0

标准差和方差

标准差是一组数据平均值分散程度的一种度量,是方差的算术平方根。

方差是每个样本值与全体样本值的平均数之差的平方值的平均数。

print (np.std([1,2,3,4]))
print (np.var([1,2,3,4]))
>>>
1.118033988749895
1.25

NumPy 排序

在 numpy 中排序一行代码就可以完成,直接调用 sort 函数即可。

numpy.sort(a, axis, kind, order)

默认情况下,使用的是快速排序算法;在 kind 里,可以指定 quicksort、mergesort 和 heapsort,分别表示快速排序、合并排序和堆排序;axis 默认是 -1,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序;对于 order 字段,如果数值包含字段,可以填写要排序的字段。

a = np.array([[3,7],[9,1]])
print ('数组是:')
print (a)
print ('调用 sort() 函数:')
print (np.sort(a))
print ('按列排序:')
print (np.sort(a, axis =  0))
print ('按行排序:')
print (np.sort(a, axis =  1))
>>>
数组是:
[[3 7][9 1]]
调用 sort() 函数:
[[3 7][1 9]]
按列排序:
[[3 1][9 7]]
按行排序:
[[3 7][1 9]]

Pandas

在数据分析当中,我们通常使用 Pandas 来做数据清理的工作。在真实的工作生活中,我们拿到的数据往往都是不整洁的,空值、重复值、无效值等等信息都会干扰我们的分析,此时我们就需要按部就班的完成数据的清理。数据清理是数据分析中非常重要的一步,也是非常繁琐的一步,当然,在你掌握了 Pandas 库之后,你就好像是得到了一把削铁如泥的宝剑,数据清理工作的效率会大大提高。

数据结构

Pandas 主要有两种数据结构,分别是 Series 和 DataFrame,他们分别表示一维的序列和二维的表结构。

维数 名称 描述
1 Series 可以看做有标签(默认是整数序列 RangeIndex;可以重复)的一维数组(同类型)。是 scalars(标量) 的集合,同时也是 DataFrame 的元素。
2 DataFrame 一般是二维标签,尺寸可变的表格结构,具有潜在的异质型列。

Series

Series 是一个定长的字典序列。它相当于是两个 ndarray,一个代表 index,一个代表 values。

import pandas as pd
s = pd.Series(data, index=index)

此处的 data,可以是如下的数据类型:

  • Python 中的 dict

  • 一个 ndarray

  • 一个标量,比如:4

而 index 的默认值是 0,1,2… 递增的整数序列。

指定 index

s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
print(s)
>>>
a   -0.595567
b   -0.201314
c    1.516812
d    0.102395
e   -1.009924
dtype: float64

不指定 index

s1 = pd.Series(['a', 'b', 'c', 'd'])
print(s1)
>>>
0    a
1    b
2    c
3    d
dtype: object

通过字典来创建 Series

d= {'a': 1, 'b': 2, 'c': 3}
s2 = pd.Series(d)
print(s2)
>>>
a    1
b    2
c    3
dtype: int64

DataFrame

DataFrame 是一个二维的数据结构,可以把它理解为数据表格或者是 SQL 表,或者是由 Series 对象组成的字典。

d = {"Chinese": [80, 85, 90], "Math": [85, 70, 95], "English": [90, 95, 90]}
df1 = pd.DataFrame(d)
print(df1)
df2 = pd.DataFrame(d, index=['zhangsan', 'lisi', 'wangwu'])
print(df2)
print(df2.columns, df2.index)
>>>Chinese  Math  English
0       80    85       90
1       85    70       95
2       90    95       90Chinese  Math  English
zhangsan       80    85       90
lisi           85    70       95
wangwu         90    95       90
Index(['Chinese', 'Math', 'English'], dtype='object') Index(['zhangsan', 'lisi', 'wangwu'], dtype='object')

通过 index 选择 DataFrame 中的数据

操作 语法 结果类型
选择某一列 df[col] Series
通过标签选择某一行 df.loc[label] Series
通过标签位置选择某一行 df.iloc[loc] Series
切片获取某些行 df[5:10] DataFrame
通过布尔向量获取某些行 df[bool_vec] DataFrame

代码

print(df2['Chinese'], '\n')
print(df2.loc['zhangsan'], '\n')
print(df2.iloc[-1], '\n')
print(df2[0:2], '\n')
print(df2[df2>85], '\n')
>>>
zhangsan    80
lisi        85
wangwu      90
Name: Chinese, dtype: int64 Chinese    80
Math       85
English    90
Name: zhangsan, dtype: int64 Chinese    90
Math       95
English    90
Name: wangwu, dtype: int64           Chinese  Math  English
zhangsan       80    85       90
lisi           85    70       95           Chinese  Math  English
zhangsan      NaN   NaN       90
lisi          NaN   NaN       95
wangwu       90.0  95.0       90

基本使用

读取/保存数据

读取数据

df = pd.read_csv("test.csv")
print(df.head())
print('\n')
print(type(df))
>>>name   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0       NaN
2    wangwu  25.0  100000.0
3   zhaoliu   NaN      32.0
4      maqi  33.0      60.0
<class 'pandas.core.frame.DataFrame'>

保存数据

df.to_csv('my.csv')
df.to_excel('my.xlsx')

查看数据

print(df.index, '\n')
print(df.columns, '\n')
print(df.to_numpy(), '\n')
print(df.describe())
>>>
RangeIndex(start=0, stop=5, step=1) Index(['name', 'age', 'score'], dtype='object') [['zhangsan' 30.0 80.0]['lisi' 20.0 nan]['wangwu' 25.0 100000.0]['zhaoliu' nan 32.0]['maqi' 33.0 60.0]]              age          score
count   4.000000       4.000000
mean   27.000000   25043.000000
std     5.715476   49971.337211
min    20.000000      32.000000
25%    23.750000      53.000000
50%    27.500000      70.000000
75%    30.750000   25060.000000
max    33.000000  100000.000000

describe 是非常常用的函数,可以通过它来在整体上查看数据的全貌,有助于了解数据。

排序

按轴排序

print(df.sort_index(axis=1, ascending=False))
>>>score      name   age
0      80.0  zhangsan  30.0
1       NaN      lisi  20.0
2  100000.0    wangwu  25.0
3      32.0   zhaoliu   NaN
4      60.0      maqi  33.0

按数值排序

print(df.sort_values(by='score'))
>>>name   age     score
3   zhaoliu   NaN      32.0
4      maqi  33.0      60.0
0  zhangsan  30.0      80.0
2    wangwu  25.0  100000.0
1      lisi  20.0       NaN

缺失值

查看缺失值

print(df.isnull(),'\n')
print(df.isnull().any())
>>>name    age  score
0  False  False  False
1  False  False   True
2  False  False  False
3  False   True  False
4  False  False  False name     False
age       True
score     True
dtype: bool

可以方便的看出数据中,哪些列是存在空值的。

删除/填充空值

df1 = df.copy()
print(df1, '\n')
print(df1.dropna(how='any'), '\n')
print(df1.fillna(value=50))
>>>name   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0       NaN
2    wangwu  25.0  100000.0
3   zhaoliu   NaN      32.0
4      maqi  33.0      60.0        name   age     score
0  zhangsan  30.0      80.0
2    wangwu  25.0  100000.0
4      maqi  33.0      60.0        name   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0      50.0
2    wangwu  25.0  100000.0
3   zhaoliu  50.0      32.0
4      maqi  33.0      60.0

常用操作

重命名列

df1.rename(columns={'name': 'student'}, inplace = True)
print(df1)
>>>student   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0       NaN
2    wangwu  25.0  100000.0
3   zhaoliu   NaN      32.0
4      maqi  33.0      60.0

删除列/行

df1 = df1.drop(columns=['age'])
print(df1, '\n')
df1 = df1.drop(index=[1])
print(df1)
>>>student     score
0  zhangsan      80.0
1      lisi       NaN
2    wangwu  100000.0
3   zhaoliu      32.0
4      maqi      60.0     student     score
0  zhangsan      80.0
2    wangwu  100000.0
3   zhaoliu      32.0
4      maqi      60.0

去除重复值

df = df.drop_duplicates() # 去除重复行

修改数据格式

df1['score'].astype('str')

apply 函数的应用
apply 用来将函数应用到数据上。

df2 = df1['score'].apply(lambda x: x * 2)
print(df2)
>>>
0       160.0
2    200000.0
3        64.0
4       120.0
Name: score, dtype: float64

以上代码等价于

list(map(lambda x: x*2, df1['score']))
>>>
[160.0, 200000.0, 64.0, 120.0]

由此可以看出,apply 是一个高效且简洁的函数,可以快速把函数作用到每个元素之上。

直方图化

所谓的直方图化,就是函数 value_counts,该函数可以查看数据中,每列中有多少不同值,且各个不同值出现的次数

print(df, '\n')
df3 = df.fillna(60)
df3.loc[5] = ['qianba', 20, 80]  # 新增一行
print(df3['score'].value_counts())
>>>name   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0       NaN
2    wangwu  25.0  100000.0
3   zhaoliu   NaN      32.0
4      maqi  33.0      60.0 60.0        2
80.0        2
32.0        1
100000.0    1
Name: score, dtype: int64

表格合并及分组

合并

1、使用 concat 连接两个 Pandas 对象

print(df3, '\n')
df4 = df3.copy()
df3 = pd.concat([df3, df4], ignore_index=True)
print(df3)
>>>name   age     score
0  zhangsan  30.0      80.0
1      lisi  20.0      60.0
2    wangwu  25.0  100000.0
3   zhaoliu  60.0      32.0
4      maqi  33.0      60.0
5    qianba  20.0      80.0         name   age     score
0   zhangsan  30.0      80.0
1       lisi  20.0      60.0
2     wangwu  25.0  100000.0
3    zhaoliu  60.0      32.0
4       maqi  33.0      60.0
5     qianba  20.0      80.0
6   zhangsan  30.0      80.0
7       lisi  20.0      60.0
8     wangwu  25.0  100000.0
9    zhaoliu  60.0      32.0
10      maqi  33.0      60.0
11    qianba  20.0      80.0

2、使用 merge 函数

基于某一列进行连接

left = pd.DataFrame({'key': ['foo', 'bar', 'loo'], 'lval': [1, 2, 3]})
right = pd.DataFrame({'key': ['foo', 'bar', 'roo'], 'rval': [3, 4, 5]})
print(left, '\n')
print(right, '\n')
print(pd.merge(left, right, on='key'))
>>>key  lval
0  foo     1
1  bar     2
2  loo     3 key  rval
0  foo     3
1  bar     4
2  roo     5 key  lval  rval
0  foo     1     3
1  bar     2     4

内连接(innert),取键的交集

print(pd.merge(left, right, how='inner'))
>>>key  lval  rval
0  foo     1     3
1  bar     2     4

还有左连接、右连接和外连接,你可以自己尝试下,看看有什么区别。

分组

所谓的分组,就是根据一些标准,将数据分解成一些组,将函数独立的应用到每个组上,最后将结果组合成数据结构。

df = pd.DataFrame({'A': ['foo', 'bar', 'bar', 'foo', 'foo', 'foo'],
'B': ['one', 'two', 'three', 'one', 'two', 'two'],
'C':[1, 2, 3, 4, 5, 6]})
print(df, '\n')
print(df.groupby('A').sum(), '\n')
print(df.groupby('B').sum())
>>>A      B  C
0  foo    one  1
1  bar    two  2
2  bar  three  3
3  foo    one  4
4  foo    two  5
5  foo    two  6       C
A
bar   5
foo  16         C
B
one     5
three   3
two    13

也可以按照多列分组

print(df.groupby(['A', 'B']).sum())
>>>C
A   B
bar three   3two     2
foo one     5two    11

绘制简单图表

Pandas 同样提供绘制图表的功能

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2018', periods=1000))
print(ts, '\n')
ts = ts.cumsum()  # 返回累计值
ts.plot()
>>>
2018-01-01    1.055229
2018-01-02    0.101467
2018-01-03   -2.083537
2018-01-04    1.178102
2018-01-05   -0.084247...
2020-09-22   -4.316770
2020-09-23   -0.823494
2020-09-24    0.215199
2020-09-25    1.094516
2020-09-26    0.285788
Freq: D, Length: 1000, dtype: float64 Out[94]:
<matplotlib.axes._subplots.AxesSubplot at 0x4742270>

好了,今天的分享就到这里,是不是够长啊!原创不易,给个“赞”


技术交流

欢迎转载、收藏、有所收获点赞支持一下!

目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

  • 方式①、发送如下图片至微信,长按识别,后台回复:加群;
  • 方式②、添加微信号:dkl88191,备注:来自CSDN
  • 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

2w+字长文,一篇文章扫盲Python、NumPy 和 Pandas,建议收藏!相关推荐

  1. 长文预警,一篇文章扫盲Python、NumPy 和 Pandas,建议收藏慢慢看

    大家好,我是辰哥~ 今天我们来一篇超级长文,一次性扫盲Python.NumPy 和 Pandas Python 作为简单易学的编程语言,想要入门还是比较容易的 搭建语言环境 我们首先来了解下如何安装和 ...

  2. 2W字 0-1 讲解数仓(附软硬件架构图)(建议收藏)

    大数据篇:一文读懂@数据仓库 1 网络词汇总结 人工智能层的:智慧地球.智慧城市.智慧社会 企业层面的:数字互联网,数字经济.数字平台.数字城市.数字政府: 平台层面的:物联网,云计算,大数据,5G, ...

  3. MySQL优化-一篇文章就够了(转发加收藏吧)

    关注我,一个仍存梦想的屌丝程序员,每天为你分享高质量编程博客. 回复 "代金券"  免费获取腾讯云和阿里云代金券 前言 说起MySQL的查询优化,相信大家收藏了一堆:不能使用SEL ...

  4. python用于统计学_R 和 Python (numpy scipy pandas) 用于统计学分析,哪个更好?

    用R做过Python擅长的,也用Python做过R擅长的.有一天,打开官网,看到两句话,豁然开朗. R:R is a free software environment for statistical ...

  5. python对象编程例子-这是我见过最详细的Python面向对象编程!建议收藏!

    原标题:这是我见过最详细的Python面向对象编程!建议收藏! 面向对象编程和函数式编程(面向过程编程)都是程序设计的方法,不过稍有区别. 面向过程编程: 1. 导入各种外部库 2. 设计各种全局变量 ...

  6. python 的库如何开发_一篇文章入门Python生态系统

    译者按:原文写于2011年末,虽然文中关于Python 3的一些说法可以说已经不成立了,但是作为一篇面向从其他语言转型到Python的程序员来说,本文对Python的生态系统还是做了较为全面的介绍.文 ...

  7. 一篇文章学习Python中的多进程

    基本知识: 一.什么是多进程 Multiprocessing 二.添加多进程 Process 三.存储进程输出 Queue 四.效率对比 threading & multiprocessing ...

  8. 一篇文章入门Python生态系统

    开发者从PHP.Ruby或其他语言转到Python时,最常碰到的第一个障碍,就是缺乏对Python生态系统的全面了解.开发者经常希望能有一个教程或是资源,向他们介绍如何以大致标准的方式完成大部分的任务 ...

  9. 一篇文章汇总Python装饰器全知识图谱(使用场景,基本用法,参数传递,闭包操作,类装饰器和AOP)

    装饰器,是将Python代码变得低耦合,简洁优美的必经之路,同时也是实现闭包操作,AOP编程的基础.这一篇博客从装饰器的产生原因,基本使用,延伸到参数传递,闭包操作,最后到类装饰器和AOP,希望能用我 ...

最新文章

  1. 撩课-Web大前端每天5道面试题-Day7
  2. 北斗导航 | GNSS技术在自动驾驶中的作用
  3. [python学习笔记] pyinstaller打包pyqt5程序无法运行
  4. golang 数组组合成最小的整数_golang数组-----寻找数组中缺失的整数方法
  5. Python获取类属性及其它(vim看源码常用、__dict__)
  6. AS报Failed to resolve: junit:junit:4.12错误正确的解决方法
  7. 美团点评:摩拜贡献收入15亿元 同期亏损45.5亿元
  8. KubeSphere对于已经部署的服务进行修改后重新进行部署
  9. 决定成败的人生细节(转)
  10. jQuery源码06-jQuery = function(){};给JQ对象,添加一些方法和属性,extend : JQ的继承方法,jQuery.extend()...
  11. php rsa加密demo,php实现RSA加密类实例_PHP
  12. 禁止在计算机上玩电子游戏,如何禁止孩子玩电脑游戏防止过度沉迷影响学习成绩...
  13. WIN10安装cad2006提示无权限安装的解决办法
  14. centos 6.5 mysql 5.5 安装,centos6.5 安装mysql-5.5
  15. Unity制作AR图片和视频展示
  16. ble 读写特征值特征值_BLE添加特征值
  17. V语言(Vlang)初探
  18. 应用PCA算法提取特征脸,重构人脸图像,并利用SVM算法进行人脸识别
  19. GMT绘制子图、指北针、图例、比例尺
  20. 算法的最坏情况与最佳情况

热门文章

  1. vivoY73s和vivoS7哪个好?
  2. 上门洗车小程序功能有哪些?
  3. 这个工具你不安装,我都觉得亏!!!
  4. 多对一和一对多的处理P21,P22
  5. java表示语句结束的符号_JAVA-运算符及流程控制语句
  6. 正确使用苹果手机技巧的3个方法,你知道吗?
  7. 删除桌面的“回收站”图标
  8. BricsCAD 19 for Mac(CAD建模软件)
  9. 拼多多商品上货助理是什么呢?怎么操作商品上货?
  10. [数据结构、读书笔记、C++] 并查集详解