数据分析基础
目录
- 一.matplotlib
- 1.1 matplotlib基本命令
- 1.1.1实现一个简单的matplotlib画图
- 1.1.2 拓展知识
- 1.2 折线图
- 1.2.1 折线图绘制和保存图片
- 1.2.2 完善原始折线图(辅助显示层)
- 1.2.3 字体问题
- 1.2.4 完善原始折线图(图像层)
- 1.2.5 多个坐标系显示
- 1.2.6 绘制数学图像
- 1.3 散点图
- 1.3.1常见图形种类和意义
- 1.3.2
- 1.4 柱状图
- 1.4.1 柱状图的绘制
- 1.5 直方图
- 1.5.1 直方图绘制
- 1.6 饼图
- 1.6.1 饼图绘制
- 1.1 matplotlib基本命令
- 二.numpy
- 2.1 numpy的优势
- 2.1.1 numpy测试
- 2.1.2 numpy优势
- 2.2 认识n维数组-ndarry属性
- 2.2.1 ndarray常用属性
- 2.2.2 ndarray形状
- 2.2.3 ndarray类型
- 2.3 基本操作
- 2.3.1 生成数组的方法
- 2.3.2 数组的索引和切片
- 2.3.3 形状修改
- 2.3.4 类型修改
- 2.3.5 数组的去重
- 2.4 ndarray运算
- 2.4.1 逻辑运算
- 2.4.2 通用判断函数
- 2.4.3 np.where(三元运算符)
- 2.4.4 统计运算
- 2.5 数组间的运算
- 2.5.1 数组与数的运算
- 2.5.2 数组与数组的运算
- 2.5.3 广播机制
- 2.5.4 矩阵运算
- 2.6 合并,分割
- 2.6.1 合并
- 2.6.2 分割
- 2.7 IO操作与数据处理
- 2.1 numpy的优势
- 三.pandas
- 3.1 基本数据操作
- 3.1.1 DataFrame的属性和方法
- 3.1.2 DataFrame的索引设置
- 3.1.3 Multilndex 与 Panel
- 3.1.4 Series
- 3.1.5 索引操作
- 3.1.6 赋值操作
- 3.1.7 排序
- 3.2 DataFrame运算
- 3.2.1 算术运算
- 3.2.2 逻辑运算
- 3.2.3 逻辑运算函数
- 3.2.4 统计运算
- 3.2.5 统计函数
- 3.2.6 自定义运算
- 3.3 pandas画图
- 3.4 文件读取与存储
- 3.4.1 CSV
- 3.4.2 HDF5
- 3.4.3 json
- 3.5 高级处理-缺失值处理
- 3.6 高级处理-合并
- 3.6.1 pd.concat实现合并
- 3.6.2 pd.merge实现合并
- 3.7 高级处理-数据离散化
- 3.8 高级处理-交叉表和透视表
- 3.9 分组与联合
- 3.1 基本数据操作
一.matplotlib
1.1 matplotlib基本命令
1.1.1实现一个简单的matplotlib画图
import matplotlib.pyplot as plt
plt.figure()
plt.plot([1, 0, 9], [4, 5, 6])
plt.show()
1.1.2 拓展知识
- canvas位于最顶层,用户一般接触不到
- figure 建立在canvas之上
- axes 建立在figure之上
- 坐标轴(axis),图例(legend)等辅助显示层都是建立在axes
1.2 折线图
1.2.1 折线图绘制和保存图片
import matplotlib.pyplot as plt
# 创建画布
plt.figure(figsize=(20, 8), dpi=80)
#绘制图像
plt.plot(range(10), range(10))
#保存图片
plt.savefig('test.png')
#显示图例
plt.show()
#plt.show()会释放资源,如果在显示图像之后再进行保存,只能保存空图片
1.2.2 完善原始折线图(辅助显示层)
#需求:画出某城市11点到12 点的温度变化情况,温度范围在15~18
#准备数据
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
#创建画布
plt.figure(figsize=(20, 8), api = 80)
#绘制图像
plt.plot(x, y)
#显示图像
plt.show()
#添加x,y的刻度
plt.yticks(range(40, 5))
x_label = ['11点{}分'.format(i) for i in x]
plt.xticks(x[::5], x_label[::5])
#添加网格
plt.grid(True, linestyle='--', alpha=0.5)
#添加描述信息
plt.xlabel('时间变化')
plt.ylabel("温度变化")
plt.title("某城市11点到12点每分钟的温度变化情况")
1.2.3 字体问题
1)安装字体
2)删除matplotllib缓存文件
3)修改配置文件 matplotlibrc
1.2.4 完善原始折线图(图像层)
#需求,在上面的基础上,再添加北京的温度变化情况
y_beijing = [random.uniform(1, 3) for i in x]
y_shanghai = [random.uniform(15, 18) for i in x]
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(x, y_shanghai, color='r')
plt.plot(x, y_beijing, color='g')
plt.legend()
#添加x,y的刻度
plt.yticks(range(40, 5))
x_label = ['11点{}分'.format(i) for i in x]
plt.xticks(x[::5], x_label[::5])
#添加网格
plt.grid(True, linestyle='--', alpha=0.5)
#添加描述信息
plt.xlabel('时间变化')
plt.ylabel("温度变化")
plt.title("某城市11点到12点每分钟的温度变化情况")
plt.show
1.2.5 多个坐标系显示
plt.函数名()相当于面向过程的画图方法,axes.set_方法名()相当于面向对象的画图方法
y_beijing = [random.uniform(1, 3) for i in x]
y_shanghai = [random.uniform(15, 18) for i in x]
#创建画布
figure, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 8), dpi=80)
#绘制图像
axes[0].plot(x, y_shanghai, color='r', linestyle='-', label='上海')
axes[1].plot(x, y_beijing, color='b', label='北京')
axes[0].legend()
axes[1].legend()
#添加x,y的刻度
axes[0].set_yticks(range(40, 5))
x_label = ['11点{}分'.format(i) for i in x]
axes[1].set_xticks(x[::5], x_label[::5])
#添加网格
axes[0].grid(True, linestyle='--', alpha=0.5)
axes[1].grid(True, alpha=0.5)
#添加描述信息
axes[0].set_xlabel('时间变化')
axes[0].set_ylabel("温度变化")
axes[1].set_xlabel("时间变化")
axes[1].set_ylabel("温度变化")
axes[0].set_title("某城市11点到12点每分钟的温度变化情况")
plt.show()
1.2.6 绘制数学图像
import numpy as np
#准备数据
x = np.linespace(-10, 10, 1000)
y = np.sin(x)
#创建画布
plt.figure(figsize=(20, 8), dpi=80)
#绘制函数图像
plt.plot(x, y)
#添加网格
plt.grid(linestyle='-', alpha=0.5)
#显示图像
plt.show()
1.3 散点图
1.3.1常见图形种类和意义
- 折线图:plot
- 散点图:scatter:关系/规律
- 柱状图:bar:统计/对比
- 直方图:histogram:分布状况
- 饼图:占比
1.3.2
x = linespace(-100, 100, 1000)
y = linespace(100, 200, 1000)
#创建画布
plt.figure(figsize=(20, 8), dpi=80)
#绘制图像
plt.scatter(x, y)
#显示图像
plt.show()
1.4 柱状图
1.4.1 柱状图的绘制
需求一:对比每部电影的票房收入
#对比每部电影的票房收入
#准备数据
movie_names = ['电影%d'%x for x in range(1, 11)]
tickets =[random.uniform(70000, 80000) for i in range(10)]
#创建画布
plt.figure(figsize=(20, 8), dpi=80)
#绘制柱状图
plt.bar(range(len(movie_names)), tickets, color = [np.random.uniform(['r', 'g', 'b', 'w']) for i in range(10)])
#修改x刻度
plt.xticks(range(len(movie_names)), movie_names)
#添加标题
plt.title("电影票房收入对比")
#添加网格
plt.grid(linestyle='--', alpha=0.5)
#显示图像
plt.show()
需求二:如何对比点引发票房收入才更加有说服力
#按照上映的时间对比票房
#准备数据
movie_names = ['电影%d'%x for x in range(1, 5)]
first_day = [np.random.uniform(1000, 10000) for i in range(4)]
second_day = [np.random.uniform(1000, 10000)]
#创建画布
plt.figure(figsize(20, 8), dpi=80)
#绘制柱状图
plt.bar(range(4), first_day, width=0.2, label="首日票房")
plt.bar([0.2, 1.2, 2.2, 3.2], second_day, width=0.2, label="首周票房")
#添加图例
plt.legend()
#修改刻度
plt.xticks([0.1, 1.1, 2.1, 3.1], movie_names)
#显示图像
plt.show()
1.5 直方图
1.5.1 直方图绘制
#电影时长分布状况
#准备数据
time = [random.randint(90, 140) for i in range(30)]
#创建画布
plt.figure(figsize(20, 8), dpi=80)
#绘制直方图
#bins表示组,bin = (max(time) - min(time)) // 组距
distance = 2
goup_num = int((max(time) - min(time)) // distance)
#density=True表示纵坐标表示的是频率
plt.hist(time, bins = goup_num, density=True)
#修改x轴刻度
plt.xticks(range(min(time), max(time, distance))
#显示图像
plt.show()
1.6 饼图
1.6.1 饼图绘制
#准备数据
movie_names = ['电影%d'%x for x in range(1, 11)]
place_count =[random.randint(7000, 8000) for i in range(10)]
#创建画布
plt.figure(figsize=(20, 8), dpi=80)
#绘制图像
plt.pie(place_count, labels=movie_names, color = [np.random.uniform(['r', 'g', 'b', 'w']) for i in range(10)])
#为了显示的饼图保持圆形,需要添加axes保证长宽一样
plt.axis('equal')
#显示图像
plt.show()
二.numpy
2.1 numpy的优势
2.1.1 numpy测试
存储的是类型一致的数据
import numpy as np
#创建ndarray
score = np.array([np.random.randint(80, 100) for i in range(5)], [np.random.randint(80, 100) for i in range(5)])
2.1.2 numpy优势
import random
import time
import numpy as np
a = []
for i in range(1000000):
a.append(random.random())
t1 = time.time()
sum1 = sum(a)
t2 = time.time()
b = np.array(a)
t4 = time.time()
sum3 = np.sum(b)
t5 = time.time()
print(t2 - t1, t5 - t4)
2.2 认识n维数组-ndarry属性
2.2.1 ndarray常用属性
| 属性名字 | 属性解释 |
|---|---|
| ndarray.shape | 数组维度的元组 |
| ndarray.ndim | 数组维数 |
| ndarray.size | 数组中的元素数量 |
| ndarray.itemsize | 一个数组元素的 长度 |
| ndarray.dtype | 数组元素的类型 |
2.2.2 ndarray形状
a = np.array([1, 2, 3], [4, 5, 6])
b = np.array([1, 2, 3, 4])
c = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
# a(2, 3)
# b(4, )
# c(2, 3, 3)
print(c.shape)
2.2.3 ndarray类型
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)
#等价于
a = np.array([[1, 2, 3], [4, 5, 6]], dtype='float32')
a.dtype
# 如果不指定,整数默认为int64,浮点数默认为float64
2.3 基本操作
2.3.1 生成数组的方法
- 生成0和1
- 从现有数组中生成
- 生成固定范围的数组
- 生成随机数组
import numpy as np
#生成0和1的数组
np.zeros(shape=(3, 4), dtype="float32")
np.ones(shape=(3, 4), dtype=np.int32)
#从现有数组生成
list = []
for i in range(10):
for j in range(10):
a = []
a.append(i * j)
list.append(a)
score = np.array(list)
data1 = np.asarray(score)
data2 = np.copy(score)
score[3, 1] = 10000
print(score)
print(data1)
print(data2)
# np.array() np.copy为深拷贝
# np.asarray()浅拷贝
#生成固定范围的数组
np.linspace(0, 10, 100) #生成从0 ~ 10 等距离的100个数
np.arange(0, 10, 2) #生成从0 ~ 10 步长为2 的数
#生成随机的数组
#均匀分布
data = np.random.uniform(low=-1, high=1, size=10000)
import matplotlib.pyplot as plt
plt.figure()
plt.hist(data, 1000)
plt.show()
#正态分布
data2 = np.random.normal(loc=1.75, scale=0.1, size = 10000)
2.3.2 数组的索引和切片
#随机生成8只股票两周的交易日涨幅数据
stock_change = np.random.normal(loc=0, scale=1, size=(8, 10))
#获取第一个股票的前三个交易日的涨跌幅数据
stock_change[0, :3]
#如何获取三维数组的信息
a1 = np.array([[[1, 2, 3], [4, 5, 6]],[[1, 2, 3], [4, 5, 6]] ]) #(2, 2, 3)三维数组有两个二维数组,二维数组有两个一维数组,一个一维数组由三个元素
#获取34
a1[1, 0, 2]
2.3.3 形状修改
#需求:进行转置
stock_change = np.random.normal(loc=0, scale=1, size=(8, 10))
#ndarray.reshape() 返回了新的ndarray
stock_changre.reshape((10, 8))
#ndarray.T
stock_change.T
#ndarray.resize在原始的ndarray进行修改
stock_change.resize((10, 8))
2.3.4 类型修改
#ndarray.astype(type)
#ndarray序列化到本地 ndarray.tostring()
stock_change.astype('int32')
2.3.5 数组的去重
temp= np.array([[1, 2, 3, 4], [3, 4, 5, 6]])
np.unique(temp)
set(temp.flatten())
2.4 ndarray运算
2.4.1 逻辑运算
stock_change = np.random.normal(0, 1, (8, 10))stock_change = stock_change(0:5, 0:5)stock_change > 0.5#bool赋值,将满足条件的设定为指定的值stock_change[stock_change > 0.5] = 1
2.4.2 通用判断函数
- np.all
#判断stock_change[0:2,0:5]是否全是上涨的np.all(stock_change[0:2, 0:5] > 0)
- np.any
#判断是否存在上涨np.any(stock_change[0:5, :] > 0)
2.4.3 np.where(三元运算符)
通过np.where可以进行更加复杂的运算
- np.where
#判断前四只股票前四天中涨幅大于0的赋值为1,否则为0temp = stock_change[:4, :4]np.where(temp > 0, 1, 0)
- 复合逻辑运算要结合np.logical_and 和np.logical_or使用
#判断前四个股票前四天的涨跌幅大于0.5但是小于1的换为1,否则为0#判断前四个股票前四天涨跌幅大于0.5或者小于-0.5 的换为1 , 否则为0np.where(np.logical_and(temp>0.5, temp<1), 1, 0)np.where(np.logical_or(temp>0.5, temp < -0.5, 1, 0)
2.4.4 统计运算
在这里,axis0代表列,axis1代表行
stock_change = np.random.normal(0, 1, (8, 10))temp = stock_change[:4, :4]#前四只股票前四天的最大涨幅temp.max()np.max(temp)#前四只股票每一天的最大值temp.max(axis=1)
统计出哪一只股票在某个交易日的涨幅最大或者最小
- np.argmax(temp, axis=)
- np.argmin(temp, axis=)
np.argmax(temp, axis=1)
2.5 数组间的运算
2.5.1 数组与数的运算
arr = np.array([[1, 2, 3, 4 ,5], [5, 6, 7, 8, 9]])arr + 1
2.5.2 数组与数组的运算
arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])arr2 = np.array([[1, 2, 3, 4 ,5, 1], [2, 3, 4, 5 ,6, 4]])#不可以进行运算
2.5.3 广播机制
可以进行运算的数组,要么形状相等,要么shape( 其中相对应的一个地方为1)
2.5.4 矩阵运算
- np.mat() 将数组转化为矩阵
- np.matmul() 乘法
- np.dot()
a = np.array([[80, 98], [34, 45]])
b = np.mat(a)
#矩阵乘法
2.6 合并,分割
2.6.1 合并
- np.hstack() 水平
- np.vstack() 垂直
- np.concatenate(, axis =)
# np.hstack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.hstack(a, b)
#np.vstack()
np.vstack(a, b)
#np.concatenate()
a = np.array([[1, 2], [3, 4]])
b = np.array([5, 6])
np.concatenate(a, b.T, axis=1) #水平
np.concatenate(a, b, axis=0) #垂直
2.6.2 分割
x = np.arange(9)np.split(x, 3)x = np.arange(8)np.split(x, [3, 5, 6, 10])
2.7 IO操作与数据处理
#numpy读取data = np.genfromtxt('test.csv', delimiter=',')type(data[2,2]) # np.nan为numpy.float64#缺失值处理 用pandas比较方便
三.pandas
3.1 基本数据操作
3.1.1 DataFrame的属性和方法
import numpy as npimport pandas as pdstock_change = np.random.normal(0, 1, (10, 5))pd.DataFrame(stock_change)#添加行索引stock = ['股票{}'.format(i) for i in range(10)]data = pd.DateFrame(stock_change, index=stock)#添加列索引date = pd.date_range(start="20180101", periods=5, freq='B')data = pd.DataFrame(stock_change, index=stock, columns=date)#DataFrame的属性print(data.index)print(data.T)print(data.shape)#DataFrame的方法data.head() #默认前五行data.tail() #默认后五行
3.1.2 DataFrame的索引设置
- 修改行列索引值
#错误的修改方式data.index[3] = '股票_3'#正确的方式stock_code = ['股票_' + str(i) for i in range(stock_change.shape)]#必须整体修改data.index = stock_code
- 重设索引
- reset_index(drop=True)
- 设置新的下标索引
- drop:默认为False,不删除原来的索引,如果为True,删除原来的索引值
- reset_index(drop=True)
data.reset_index()
- 设置新的索引
- set_index(keys, drop=True)
- keys:列索引名或者列索引名称的列表
- drop:boolean, default True,当做新的索引,删除原来的列
- set_index(keys, drop=True)
df = pd.DataFrame({'month':[1, 4, 7, 10],
'year':[2012, 2014, 2015, 2016]},
'sale':[23,45, 453, 21])
# 重设新的索引
df.set_index(month)
new_df = df.set_index(['year', 'month'])
3.1.3 Multilndex 与 Panel
- Multilndex
# 多级或分层索引对象
# index属性
# names:levels的名称
# levels:每个levels的元组值
new_df.names
new_df.levels
- Panel
p = pd.Panel(np.arange(24), reshape(4, 3, 2), items=list('abcd'), major_axis=pd.date_range('20130101', periods=3), minor_axis=['first', 'second'])p['a']p.major_xs('2013-01-01')
3.1.4 Series
Series只有行索引
sr = data.iloc[1, :]print(sr)sr.indexsr.valuespd.Series(np.arange(3, 9, 2), index = ['a', 'b', 'c'])
3.1.5 索引操作
- 直接索引
- 按名字索引
- 按数字索引
- 组合索引
#不可以直接进行数字索引#直接索引(必须先列后行)data['open']['2018-02-26']#按名字进行索引data.loc['2018-02-26']['open'] data.loc['2018-02-26', 'open'] #按照数字索引data.iloc(1, 0)#获取从第一天到第四天,['open', 'close', 'high', 'low']这个四个指标的结果data.ix[:4, ['open', 'close', 'high', 'low']]
3.1.6 赋值操作
data.open = 100data.iloc[1, 0] = 222
3.1.7 排序
- df.sort_values(key=, ascending=)
- 单个键或者多个键进行排序,默认升序
- ascending=False 降序
- ascending=True升序
data = data.sort_values(by='p_change')
- df.sort_index对索引进行排序
3.2 DataFrame运算
3.2.1 算术运算
- add(other)
data['open'] + 3
data['open'].add(3).head()
- sub(other)
data['close'].sub(data['open'])
3.2.2 逻辑运算
data['p_change'] > 2
data[data['p_change'] > 2].head()
(data['p_change'] > 2) & (data['low'] > 15)
3.2.3 逻辑运算函数
- query(expr)
- expr:查询字符串
data.query('p_change > 2 & turnover > 15')
- isin(values)
data[data['turnover'].isin([4.19, 2.39])]
3.2.4 统计运算
- describe()
data.describe()
3.2.5 统计函数
- max(axis=)
- min(axis=)
- std()
- var()
- median()
- idxmax()
- isxmin()
- cumsum()
3.2.6 自定义运算
- apply(func, axis=0)
data[['open', 'close']].apply(lambda x:x.max() - x.min(), axis = 0)
3.3 pandas画图
data.plot(x='p_change', y='turnover', kind='scatter')
3.4 文件读取与存储
3.4.1 CSV
- pandas.read_csv(filepath, sep='', delimeter=None, ues_cols=[])
- DataFrame.to_csv(filepath, sep='', columns=None, header=True,index=True,index_label=None,mode='w',encoding=None)
3.4.2 HDF5
- pandas.read_hdf(path, key=None , **kwargs)
hdf5文件的读取和存储都需要指定一个键,值为要存储的DataFrame
day_close = pd.read_hdf("文件路径")
day_close.to_hdf("文件路径", key="close") # 不指定key无法存取
pd.read_hdf("test.h5", key="close").head() #不指定键值也可以进行读取
#当有多个键值得情况下,必须带着key,否则无法读取
3.4.3 json
- read_json(path)
sa = pd.read_json("文件路径", orient='records', lines=True)
sa.to_json("文件路径", orient="records")
3.5 高级处理-缺失值处理
-
缺失值处理思路:
- 删除含有缺失值的样本
- 替换缺失值
-
判断数据是否为nan
- pd.isnull(df)
- pd.notnull(df)
-
存在缺失值nan,并且是 np.nan
- 删除存在缺失值的:dropna(axis='rows', inplace=False)
- 替换缺失值:fillna(value, inplace=True)
-
不是缺失值但是有默认的标记
- 替换为np.nan
- df.replace(to_replace=, value=)
- to_replace 为替换前的值
- value 为替换后得值
- df.replace(to_replace=, value=)
- 按照处理np.nan的步骤
- 替换为np.nan
import pandas as pd
import numpy as np
movie = pd.read_csv('文件路径')
pd.isnull(movie) # 返回True or False
np.any(pd.isnull(movie))
pd.isnull(movie).any() #判断每个字段是否存在缺失值的情况
#不是缺失值但是有默认的标记
#如果源文件没有标题,默认会将第一行当做标题,我们可以添加name属性,为其添加标题
pd.read_csv("文件路径")
data_new = data.replace(to_replace='?', value=np.nan)
data_new.dropna(inplace=True)
data_new.isnull()
3.6 高级处理-合并
3.6.1 pd.concat实现合并
- pd.concat([data1, data2], axis= 1)
3.6.2 pd.merge实现合并
-
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False,sort=True,suffixes=('__x', '__y')
-
merge_method
- inner
- left
- right
- outer
3.7 高级处理-数据离散化
- 对数据进行分组
- 自动分组:pd.qcut(data, bins)
- 自定义分组:pd.cut(data, bins)
- 对数据进行分组将数据分组 一般会与value_counts搭配使用,统计每组的个数
- series.value_counts():统计分组次数
- 对分好组的数据求哑变量
- panfas.get_dummies(data, prefix=None)
- data:array-like, Series, or DataFrame
- prefix:分组名字
- panfas.get_dummies(data, prefix=None)
#准备数据
data = pd.Series([np.random.randint(150, 200) for i in range(8)])
#分组
#自动分组
SR = pd.qcut(data, 3)
type(SR)
#转化为one-hot编码
pd.get_dummies(SR, prrfix='height')
#看到每个区间有多少个人
pd.value_counts()
# 自定义分组
bins = [150, 165, 180, 195]
sr = pd.cut(data, bins)
pd.get_dummies(sr, prefix='身高')
3.8 高级处理-交叉表和透视表
https://blog.csdn.net/u012735708/article/details/86504489
3.9 分组与联合
- DataFrame.groupby(ley, as_index=False)
- key:分组的列依据,可以多个
col = pd.DataFrame({'color':['white', 'red', 'green', 'red', 'green'], 'object':['pen', 'pencial', 'pencil', 'ashtray', 'pen'], 'price1':[5.12, 435.23, 23.12, 23.3, 2.1],'price2':[3.2, 2.34, 12.23, 23.213, 2.1]})
# 进行分组,对颜色分组,pricel进行聚合
# 用DataFrame的方法进行分组
col.groupby(by="col")
col.groupby(by='color')['pricel'].max()
col