pokemonlei

陈磊的博客 | pokemonlei

python数据分析基础

前言

  • Python VS R 语言(原文:https://mp.weixin.qq.com/s/CAsVeEJlgru85NUHcUKv6A):
    • 什么是R语言?
      R语言,一种自由软件编程语言与操作环境,主要用于统计分析、绘图、数据挖掘。R基于S语言的一个GNU计划项目,所以也可以当作S语言的一种实现。
    • Python与R语言共同特点
    • Python和R在数据分析和数据挖掘方面都有比较专业和全面的模块,很多常用的功能,比如矩阵运算、向量运算等都有比较高级的用法
    • Python和R两门语言有多平台适应性,linux、window都可以使用,并且代码可移植性强
    • Python和R比较贴近MATLAB以及minitab等常用的数学工具
    • Python与R语言区别
    • 数据结构方面,由于是从科学计算的角度出发,R中的数据结构非常的简单,主要包括向量(一维)、多维数组(二维时为矩阵)、列表(非结构化数据)、数据框(结构化数据)。而 Python 则包含更丰富的数据结构来实现数据更精准的访问和内存控制,多维数组(可读写、有序)、元组(只读、有序)、集合(唯一、无序)、字典(Key-Value)等等。
    • Python与R相比速度要快。Python可以直接处理上G的数据;R不行,R分析数据时需要先通过数据库把大数据转化为小数据(通过groupby)才能交给R做分析,因此R不可能直接分析行为详单,只能分析统计结果。
    • Python是一套比较平衡的语言,各方面都可以,无论是对其他语言的调用,和数据源的连接、读取,对系统的操作,还是正则表达和文字处理,Python都有着明显优势。 而R是在统计方面比较突出。
    • 总结
      总的来说,Python 的 pandas 借鉴了R的dataframes,R 中的 rvest 则参考了 Python的BeautifulSoup,两种语言在一定程度上存在互补性,通常,我们认为 Python 比 R 在计算机编程、网络爬虫上更有优势,而 R 在统计分析上是一种更高效的独立数据分析工具。所以说,同时学会Python和R这两把刷子才是数据科学的王道。

python其实是可以直接调用R语言的函数的,只需要安装rpy2模块即可。

matplotlib

提到数据分析,就不得不考虑到数据分析后的展示,Matplotlib是一个Python 2D绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形。
至于matplotlib的安装,可以通过 Anaconda来安装,相关操作不多赘述。

折线图示例

相关api在代码中都有注释
代码如下:

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
40
41
42
43
44
45
46
47
48
49
50
51
# coding=utf-8
# 折线图
from matplotlib import pyplot as plt
import matplotlib

# 注:matplotlib默认时不支持中文的,可通过rc修改
font = {'family': 'SimHei',
'weight': 'bold',
'size': '16'}
matplotlib.rc('font', **font)

x = range(2, 26, 2)
y = [15, 13, 12, 11, 15, 3, 20, 22, 14.5, 6.3, 21.2, 10]
# 要在一个图形上绘制多个曲线,可直接设置另一个列表然后通过plot来绘制
another_y = [10, 10, 22, 15, 13, 5, 6, 8, 11.5, 20, 21.2, 20]

# 设置图片大小
# plt.figure(figsize=(20, 8), dpi=80)

# 绘图,label为折线名字,需要在后面添加legend方法才能显示在图形上,还可设置线条颜色和style等
plt.plot(x, y, label="第一条")
# 绘制另一条曲线
plt.plot(x, another_y, label="第二条")

# 绘制x轴的刻度,根据列表参数的值展示刻度
# plt.xticks(x)
# plt.xticks(range(2,25))
# x轴刻度显示字符串, 需要构造一个和xticks第一个参数一一对应的字符串列表,这也可以解决xy轴刻度对不准问题,自定义在哪里显示刻度和显示什么
_xstring_labels = ["string{}".format(i) for i in x]
plt.xticks(x, _xstring_labels, rotation=90) # rotation可以让x刻度旋转一定角度

# 展示y轴刻度
plt.yticks(range(min(y), max(y)))

# 添加图形和坐标轴的描述信息
plt.xlabel("x轴信息")
plt.ylabel("y轴信息")
plt.title("图形名字")

# 绘制网格,参数alpha可以设置透明度
plt.grid()

# 添加图例,loc参数可设置图例位置
plt.legend()

# 展示图形
plt.show()

# 保存图形,后缀为svg可以保存为矢量图
# plt.savefig("./testone.png")

其他图形示例

绘制其他图形的api和折线图几乎相同,程序参考上面就可以,下面列举一下api以供参考
其中 x,y为x和y轴的列表

  • 散点图
    • plt.scatter(x,y)
  • 条形图
    • plt.bar(x,y,width=’0.3’) #width为设置线条的粗细
    • plt.hbar(x,y,height=’0.3’) #绘制横向的条形图,height为横向线条的粗细
    • 通过设置 xticks可以实现数字和字符串的相对应
  • 直方图
    • plt.hist(a,num_bins,normed = True) #a为数据列表,num_bins为数据分为多少组,normed用来设置是否是频率直方图。
      • 组数 = 极差/组距 = (max(a) - min(a))/自己设置的组距,注:最大值-最小值的结果一定要能被组距整除,不然图像会出现偏差
    • 当组距不均匀时,plt.hist(a,[min(a)+i*组距 for i in range(组数)]),也就是可以传入一个列表,长度为组数,值为分组的依据
    • 小技巧,设置x轴刻度:plt.xticks(range(min(a),man(a)+d,d)) ,因为range是去[),所以最后不加d的话会导致最后一个刻度丢失
  • more

其他的一些绘制工具

Numpy

什么是Numpy

NumPy系统是Python的一种开源的数值计算扩展,是python科学计算的基础包。这种工具可用来存储和处理大型矩阵,具有快速高效的多维数组对象ndarray,比Python自身的嵌套列表(nested list structure)结构要高效的多。NumPy(Numeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。可以用来处理线性代数运算、傅里叶变换以及随机数生成等。

下面列出了一些列numpy常用的API可供参考:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# coding = utf-8
import numpy
import random

# numpy 创建数组
t1 = numpy.array([1, 2, 3]) # [1,2,3]
t2 = numpy.array(range(1, 6)) # [1,2,3,4,5]
t3 = numpy.arange(4, 10, 2) # [4,6,8]

print(t3.dtype) # int32 与平台有关,还可能是int64,float32等
t4 = numpy.arange(4, 10, 2, dtype="int64") # 可以手动指定数值类型
# 调整数据类型
t5 = t4.astype("float32")
print(t5.dtype)

t6 = random.random()
t6 = numpy.round(t6, 2) # round保留两位小数
print(t6)

'''
numpy读取本地CSV文件
api:numpy.loadtxt(fname, dtype=, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0)
fname :文件或字符串
dtype : 数据类型
comments :用于指示注释开头的字符,默认值为 : '#'.
delimiter :用于分隔值的字符,缺省值为任何空白字符,如空格 ,制表符
converters : dict字典 ,用来定义将对应的列转换为浮点数的函数。列入:0列是日期字符串:"converters={0:datestr2num}".convertes 同时也能够为丢失的数据设置缺省值:"convertes={3:lambda s:float(s.strip() or 0)}"
skiprows:跳过开头的行数
usecols : 确定那几列被读取
unpack :是否进行转置
'''
# n1 = numpy.loadtxt("test.csv",delimiter=",",dtype="int") # t1= [ [0行0列 0行1列 0行2列] [1行0列 1行1列 1行2列] [2行0列 2行1列 2行2列] ]

n2 = numpy.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
])
# 索引和切片
# print(n2[行,列]) ‘:’表所有
# 取一行
print(n2[1]) # [5 6 7 8]
# 取连续多行
print(n2[1:]) # [[5 6 7 8] [9 10 11 12]]
# 取不连续多行
print(n2[[0, 2]]) # [ [1 2 3 4] [9 10 11 12]]

# 取列
print(n2[:, 0]) # [1 5 9]
# 连续多列
print(n2[:, 2:]) # [ [3 4] [7 8 ] [11 12]]
# 不连续的列
print(n2[:, [0, 2]]) # [ [1 3][5 7][9 11] ]

# 取单行单列和多行多列
print(n2[[0, 1], [1, 2]]) # 注意,这里是 [2 7]
print(n2[1, 2]) # [7]
print(n2[0:2, 0:3]) # [[1 2 3][5 6 7]] ,这里的多行多列,‘:’的区间是[)

# 数据拼接
n3 = numpy.array([
[1, 2, 3, 4],
[5, 6, 7, 8]
])
n4 = numpy.array([
[9, 10, 11, 12],
[11, 12, 13, 14]
])
# 横向和竖向拼接
numpy.vstack((n3, n4)) # [[1 2 3 4] [5 6 7 8] [9 10 11 12] [...]]
numpy.hstack((n3, n4)) # [ [1 2 3 4 9 10 11 12] [5 6 7 8 11 12 13 14]]
# numpy数组可以支持 a b = b a语法来换行或者换列,如
n2[[1, 2], :] = n2[[2, 1], :] # 行交换
n2[:, [0, 1]] = n2[:, [1, 0]] # 列交换

pandas

为什么需要pandas?

numpy能够帮我们处理数值型数据,但这样还不足以满足需求,有时候还需要处理字符串、时间序列等。不过pandas的数值处理模块也是基于numpy的。

什么是pandas?

pandas 是是python的一个数据分析包、基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。对于金融行业的用户,pandas提供了大量适用于金融数据的高性能时间序列功能和工具。

pandas的数据结构:

  • Series:带标签(索引)的一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
  • Time- Series:以时间为索引的Series。
  • DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。
  • Panel :三维的数组,可以理解为DataFrame的容器。

pandas的相关用法如下:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# coding = 'utf-8'
import pandas as pd
import numpy as np

# Series相关

t1 = pd.Series([1, 2, 33, 44, 5])
t2 = pd.Series([1, 2, 3, 4, 5], index=list("abcde")) # 此时 1的索引为a,2的索引为b,以此类推
print(t2.dtype) # int64
temp_list = {"name": "q", "age": 26, "tel": "10086"}
t3 = pd.Series(temp_list) # 此时索引为字典的键,值为字典对应键的值
# tip:对一个series重新指定索引后,如果能够对应上,就取其值,如果不能,则为Nan
print(t3.dtype) # object

# Series的切片和索引
print(t3[:2]) # 取前3行
print(t3[["name", "age"]]) # 取name和age
print(t1[t1 > 2]) # 取值大于2的
print(t3.index) # 获取索引列表,类型为Index,可以使用list(t3.index) 强制转换为列表
print(t3.values) # 获取值的列表,类型为numpy.ndarry,其实就是一个数组
# tips:ndarry中很多方法在pandas中都可以用。但pandas中的where是不同的,可以用来查找符合条件的数值,而不符合的显示为指定的值,不指定则为Nan
print('*' * 20)

# DataFrame相关

p1 = pd.DataFrame(np.arange(12).reshape(3, 4))
print(p1)
# 带索引的创建,指定行索引和列索引
p2 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("abc"), columns=list("WXYZ"))
print(p2)
# 传入字典创建,键为列名,每一行为具体的值,值可以对应一个列表,列表内有多少数据就有多少行。也可以传入一个内容是字典的列表,有几个字典就有几行。没有的数据为NaN
d1 = {"name": ["q1", "q2"], "age": [25, 26], "tel": [10086, 10010]}
p3 = pd.DataFrame(d1)
print(p3)
d2 = [{"name": "q1", "age": 25, "tel": 10010}, {"name": "q2", "tel": 10000}, {"name": "q3", "age": 22, "tel": 10086}]
p4 = pd.DataFrame(d2)
print(p4)
# 前几行,tail为尾几行。info可以查看DataFrame的内存情况,多少行多少列占用多少内存等
p4.head(1)

# DataFrame取行取列,方括号内写数组,表示取行,写字符串,表示取列的索引
p5 = pd.DataFrame(np.arange(100).reshape(10, 10), index=["r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"],
columns=["c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10"])
# 取前5行
print(p5[:5])
# 取固定列
print(p5["c2"])
# 通过pandas优化过的选择方式:
# loc通过标签索引行数据,loc中冒号两边的数据取的方式是闭合区间[],而不是[)
# iloc通过位置获取行数据
print(p5.loc["r4", "c5"]) # 取r4行r5列
print(p5.loc["r4"]) # 取r4行
print(p5.loc[["r1", "r3"]]) # 取多行多列语法 如r1行和r3行
print(p5.iloc[:, 2]) # 取第2列,索引从0开始
print(p5.iloc[5:, 3:]) #取第6行以后和第3列以后的数据
print(p5[p5["c7"]>70]) #取c7列大于70的所有行

#缺失数据NaN的处理
p6 = pd.DataFrame(np.array([0,1,np.NaN,3,4,5,6,7,8,np.NaN,10,11]).reshape(3, 4), index=list("abc"), columns=list("WXYZ"))
print(p6)
print(pd.notnull(p6)) #p6中,不为NaN的值显示为true,为NaN的值显示为false
print(p6[pd.notnull(p6["X"])]) #选取p6的X列中的值不为NaN的所有行
print(p6.dropna(axis=0,how="any")) #删除DataFrame中值为NaN的axis,axis=0为行,1为列。how的值为“any”表示这个轴只要有NaN就删,值为“all”表示所有值都为NaN才删
#填充NaN为指定数据
print(p6.fillna(0)) # 将NaN填充为0
# 不过为了数据完整性,一般不会填充为0或者随便填一个数值,而是会填充为均值,Pandas计算均值的时候不会算上NaN值
print(p6.mean()) #此时mean算的均值是每一列的均值
print(p6.fillna(p6.mean()))
print(p6["X"].fillna(p6["X"].mean())) #只填充某一列的NaN值,如果要改变原数据,可以前面添加 p6["X"] =

# pandas读取外部数据
# csv文件
# result = pd.read_csv("./test.csv")
# 读取sql,传入sql语句和connection
# pd.read_sql(sql_sentence,connection)

写到这里

先上一张python数据分析的知识框架

其中有一些还没有写到,也不打算继续挖坑了,暂且记录在下面:

这段时间大概了解了一下python数据分析的知识框架,写的不是很详细,这里有一篇更详细的文章写得不错先mark一下:https://www.cnblogs.com/nxld/p/6058998.html