数据分析
day01
什么是数据分析
- 是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来,总结出所研究对象的内在规律
- 数据分析是用适当的方法对收集来的大量数据进行分析,帮助人们做出判断,以便采取适当的行动
- 商品采购量的多少
- 总部向各个地区代理的发货量
- ......
为什么学习数据分析
- 有岗位的需求
- 是Python数据科学的基础
- 是机器学习课程的基础
数据分析实现流程
- 提出问题
- 准备数据
- 分析数据
- 获得结论
- 成果可视化
数据分析三剑客
- numpy
- pandas
- matplotlib
numpy模块
一维或者是多维的数组(低版本的列表)
- NumPy(Numerical Python) 是 Python 语言中做科学计算的基础库。重在于数值计算,也是大部分Python科学计算库的基础,多用于在大型、多维数组上执行的数值运算。
numpy的创建
-
使用np.array()创建
-
使用plt创建
-
使用np的routines函数创建
-
使用array()创建一个一维数组
import numpy as np
arr = np.array([1,2,3,4,5,6])
arr
array([1, 2, 3, 4, 5, 6])
- 使用array()创建一个多维数组
np.array([[1,2,3,4],[5,6,7,8],[9,9,9,9]])
array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 9, 9, 9]])
- 数组和列表的区别是什么?
- 数据中存储的数组元素的数据类型必须是统一
- 数据类型是有优先级:
- str>float>int
arr = np.array([1,2.2,3,4,5,6])
arr
array([1. , 2.2, 3. , 4. , 5. , 6. ])
- 将外部的一张图片读取加载到numpy数组中,然后尝试改变数组元素的数值查看对原始图片的影响
import matplotlib.pyplot as plt
img_arr = plt.imread('./1.jpg')
plt.imshow(img_arr)
<matplotlib.image.AxesImage at 0x165791e0dd8>
plt.imshow(img_arr-100)
<matplotlib.image.AxesImage at 0x165794d4e48>
- zeros() # 创建一个数组指定行列 值都为0
- ones() # 创建一个数组指定行列 值都为0
- linespace() # 指定数值范围内分成多少个值
- arange() # 指定数值范围内间隔多少
- random系列
np.zeros((3,4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
np.linspace(0,100,num=20)
array([ 0. , 5.26315789, 10.52631579, 15.78947368,
21.05263158, 26.31578947, 31.57894737, 36.84210526,
42.10526316, 47.36842105, 52.63157895, 57.89473684,
63.15789474, 68.42105263, 73.68421053, 78.94736842,
84.21052632, 89.47368421, 94.73684211, 100. ])
np.arange(0,100,step=3)
array([ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48,
51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99])
np.random.randint(0,100,size=(5,6))
array([[71, 76, 47, 11, 7, 6],
[47, 89, 70, 44, 41, 96],
[58, 42, 36, 53, 49, 55],
[13, 32, 64, 58, 15, 7],
[78, 56, 40, 71, 45, 63]])
np.random.random((3,4)) # 1以内小数
array([[0.24913375, 0.91988476, 0.36386714, 0.58404557],
[0.15544885, 0.73892461, 0.82189615, 0.80368295],
[0.07230386, 0.45535116, 0.75370029, 0.03377829]])
- 随机性:
- 随机因子:x(时间)
#固定随机性
np.random.seed(10) # 指定随机随之种子,就是固定的了
np.random.randint(0,100,size=(5,6))
array([[ 9, 15, 64, 28, 89, 93],
[29, 8, 73, 0, 40, 36],
[16, 11, 54, 88, 62, 33],
[72, 78, 49, 51, 54, 77],
[69, 13, 25, 13, 92, 86]])
numpy的常用属性
- shape # 返回形状 行列
- ndim # 返回维度
- size # 元素个数
- dtype # 数据类型
img_arr.shape
img_arr.ndim
img_arr.size
img_arr.dtype
type(img_arr)
numpy.ndarray
arr = np.array([1,2,3],dtype='uint8')
numpy的数据类型
- array(dtype=?):可以设定数据类型
- arr.dtype = '?':可以修改数据类型
arr = np.array([1,2,3])
arr.dtype = 'int32'
numpy的索引和切片操作(重点)
- 索引操作和列表同理
arr = np.random.randint(0,100,size=(6,8))
arr
array([[30, 30, 89, 12, 65, 31, 57, 36],
[27, 18, 93, 77, 22, 23, 94, 11],
[28, 74, 88, 9, 15, 18, 80, 71],
[88, 11, 17, 46, 7, 75, 28, 33],
[84, 96, 88, 44, 5, 4, 71, 88],
[88, 50, 54, 34, 15, 77, 88, 15]])
arr[1]
array([27, 18, 93, 77, 22, 23, 94, 11])
切片操作
- 切出前两列数据
- 切出前两行数据
- 切出前两行的前两列的数据
- 数组数据翻转
- 练习:将一张图片上下左右进行翻转操作
- 练习:将图片进行指定区域的裁剪
arr.shape
(6, 8)
#切出前两行
arr[0:2]
array([[30, 30, 89, 12, 65, 31, 57, 36],
[27, 18, 93, 77, 22, 23, 94, 11]])
#切出前两列arr[hang,lie]
arr[:,0:2]
array([[30, 30],
[27, 18],
[28, 74],
[88, 11],
[84, 96],
[88, 50]])
#切出前两行的前两列的数据
arr[0:2,0:2]
array([[30, 30],
[27, 18]])
#数组数据翻转
plt.imshow(img_arr)
<matplotlib.image.AxesImage at 0x16578fb6a20>
img_arr.shape #前两个维度表示的是像素,最后一个维度表示颜色
(426, 640, 3)
#将图片进行上下翻转
plt.imshow(img_arr[::-1,:,:])
<matplotlib.image.AxesImage at 0x16578b53080>
plt.imshow(img_arr[:,::-1,:])
<matplotlib.image.AxesImage at 0x16579085f28>
plt.imshow(img_arr[::-1,::-1,::-1])
<matplotlib.image.AxesImage at 0x16578bfc588>
#裁剪
plt.imshow(img_arr)
<matplotlib.image.AxesImage at 0x165791662b0>
plt.imshow(img_arr[50:200,50:300,:])
<matplotlib.image.AxesImage at 0x16578f80c88>
- 切片汇总:
- 切行:arr[index1:index3]
- 切列:arr[行切片,列切片]
- 翻转:arr[::-1]
变形reshape
- 变形前和变形后对应的数组元素个数是一致
arr = np.array([1,2,3,4,5,6])
arr
array([1, 2, 3, 4, 5, 6])
#将一维数组变形成二维
arr.reshape((2,3))
array([[1, 2, 3],
[4, 5, 6]])
arr.reshape((-1,2))
array([[1, 2],
[3, 4],
[5, 6]])
级联操作concatenate
- 是对numpy数组进行横向或者纵向的拼接
- axis轴向的理解
- 0:列
- 1:行
arr1 = np.array([[1,2,3],[4,5,6]])
arr1
array([[1, 2, 3],
[4, 5, 6]])
np.concatenate((arr1,arr1),axis=1)
array([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
arr2 = np.array([[1,2,3,3],[4,5,6,6]])
arr2
array([[1, 2, 3, 3],
[4, 5, 6, 6]])
- 匹配级联
- 级联的多个数组的形状是一样
- 不匹配级联
- 级联的多个数组的形状是不一样(维度必须一样)
- 多个数组的行数一样进行行级联
- 多个数组的列数一样进行列级联
- 级联的多个数组的形状是不一样(维度必须一样)
#讲arr1和arr2进行级联
np.concatenate((arr1,arr2),axis=1)
array([[1, 2, 3, 1, 2, 3, 3],
[4, 5, 6, 4, 5, 6, 6]])
常用的聚合操作
- sum,max,min,mean
arr = np.random.randint(0,10,size=(4,5))
arr
array([[6, 6, 5, 6, 0],
[0, 6, 9, 1, 8],
[9, 1, 2, 8, 9],
[9, 5, 0, 2, 7]])
arr.sum(axis=1)
array([23, 24, 29, 23])
常用的数学函数
- NumPy 提供了标准的三角函数:sin()、cos()、tan()
- numpy.around(a,decimals) 函数返回指定数字的四舍五入值。
- 参数说明:
- a: 数组
- decimals: 舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置
- 参数说明:
np.sin(arr)
array([[-0.2794155 , -0.2794155 , -0.95892427, -0.2794155 , 0. ],
[ 0. , -0.2794155 , 0.41211849, 0.84147098, 0.98935825],
[ 0.41211849, 0.84147098, 0.90929743, 0.98935825, 0.41211849],
[ 0.41211849, -0.95892427, 0. , 0.90929743, 0.6569866 ]])
arr = np.random.random(size=(3,4))
arr
array([[0.07961309, 0.30545992, 0.33071931, 0.7738303 ],
[0.03995921, 0.42949218, 0.31492687, 0.63649114],
[0.34634715, 0.04309736, 0.87991517, 0.76324059]])
np.around(arr,decimals=2)
array([[0.08, 0.31, 0.33, 0.77],
[0.04, 0.43, 0.31, 0.64],
[0.35, 0.04, 0.88, 0.76]])
常用的统计函数
- numpy.amin() 和 numpy.amax(),用于计算数组中的元素沿指定轴的最小、最大值。
- numpy.ptp():计算数组中元素最大值与最小值的差(最大值 - 最小值)。
- numpy.median() 函数用于计算数组 a 中元素的中位数(中值)
- 标准差std():标准差是一组数据平均值分散程度的一种度量。
- 公式:std = sqrt(mean((x - x.mean())**2))
- 如果数组是 [1,2,3,4],则其平均值为 2.5。 因此,差的平方是 [2.25,0.25,0.25,2.25],并且其平均值的平方根除以 4,即 sqrt(5/4) ,结果为 1.1180339887498949。
- 方差var():统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数,即 mean((x - x.mean())** 2)。换句话说,标准差是方差的平方根。
arr = np.random.randint(0,20,size=(5,3))
arr
array([[12, 18, 17],
[17, 16, 0],
[ 5, 9, 0],
[ 6, 0, 2],
[ 3, 3, 18]])
np.amin(arr,axis=0)
array([3, 0, 0])
np.ptp(arr,axis=0)
array([14, 18, 18])
np.median(arr,axis=0)
array([6., 9., 2.])
np.std(arr,axis=0)
array([5.16139516, 7.02566723, 8.28492607])
np.var(arr,axis=0)
array([26.64, 49.36, 68.64])
矩阵相关
-
NumPy 中包含了一个矩阵库 numpy.matlib,该模块中的函数返回的是一个矩阵,而不是 ndarray 对象。一个 的矩阵是一个由行(row)列(column)元素排列成的矩形阵列。
-
matlib.empty() 函数返回一个新的矩阵,语法格式为:numpy.matlib.empty(shape, dtype),填充为随机数据
- 参数介绍:
- shape: 定义新矩阵形状的整数或整数元组
- Dtype: 可选,数据类型
- 参数介绍:
import numpy.matlib as matlib
matlib.empty(shape=(4,5))
matrix([[-0.2794155 , -0.2794155 , -0.95892427, -0.2794155 , 0. ],
[ 0. , -0.2794155 , 0.41211849, 0.84147098, 0.98935825],
[ 0.41211849, 0.84147098, 0.90929743, 0.98935825, 0.41211849],
[ 0.41211849, -0.95892427, 0. , 0.90929743, 0.6569866 ]])
-
numpy.matlib.zeros(),numpy.matlib.ones()返回填充为0或者1的矩阵
-
numpy.matlib.eye() 函数返回一个矩阵,对角线元素为 1,其他位置为零。
- numpy.matlib.eye(n, M,k, dtype)
- n: 返回矩阵的行数
- M: 返回矩阵的列数,默认为 n
- k: 对角线的索引
- dtype: 数据类型
- numpy.matlib.eye(n, M,k, dtype)
matlib.eye(5,5,1)
matrix([[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0.]])
- numpy.matlib.identity() 函数返回给定大小的单位矩阵。单位矩阵是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为 1,除此以外全都为 0。
matlib.identity(6)
matrix([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1.]])
- 转置矩阵
- .T
arr = matlib.identity(6)
arr
matrix([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1.]])
a = np.array([[1,2,3],[4,5,6]])
a
array([[1, 2, 3],
[4, 5, 6]])
a.T
array([[1, 4],
[2, 5],
[3, 6]])
- 矩阵相乘
- numpy.dot(a, b, out=None)
- a : ndarray 数组
- b : ndarray 数组
- 第一个矩阵第一行的每个数字(2和1),各自乘以第二个矩阵第一列对应位置的数字(1和1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值3。也就是说,结果矩阵第m行与第n列交叉位置的那个值,等于第一个矩阵第m行与第二个矩阵第n列,对应位置的每个值的乘积之和。
- 线性代数基于矩阵的推导:
- numpy.dot(a, b, out=None)
arr_1 = np.array([[1,2,3],[4,5,6]]) #2行3列
arr_2 = np.array([[1,2,3],[4,5,6]])
arr_2 = arr_2.T
arr_1
array([[1, 2, 3],
[4, 5, 6]])
arr_2
array([[1, 4],
[2, 5],
[3, 6]])
np.dot(arr_1,arr_2)
array([[14, 32],
[32, 77]])
- 重点掌握:
- 数组的创建
- 数组的索引和切片
- 数据的级联,变形
- numpy的聚合(sum,max,mean)和统计函数(std())
- 矩阵的乘法原理
为什么学习pandas
- numpy已经可以帮助我们进行数据的处理了,那么学习pandas的目的是什么呢?
- numpy能够帮助我们处理的是数值型的数据,当然在数据分析中除了数值型的数据还有好多其他类型的数据(字符串,时间序列),那么pandas就可以帮我们很好的处理除了数值型的其他数据!
什么是pandas?
- 首先先来认识pandas中的两个常用的类
- Series
- DataFrame
Series
-
Series是一种类似与一维数组的对象,由下面两个部分组成:
- values:一组数据(ndarray类型)
- index:相关的数据索引标签
-
Series的创建
- 由列表或numpy数组创建
- 由字典创建
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
s = Series(data=[1,2,3,4,5])
0 1
1 2
2 3
3 4
4 5
dtype: int64
Series的索引
- 隐事索引:默认
- 显式索引:增强数据的可读性
- index的参数指定
s1 = Series(data=[1,2,3],index=['a','b','c'])
s1
a 1
b 2
c 3
dtype: int64
dic = {
'数学':100,
'理综':188
}
s3 = Series(data=dic)
s3
数学 100
理综 188
dtype: int64
s4 = Series(data=np.random.randint(0,100,size=(3,)))
s4
0 9
1 91
2 24
dtype: int32
Series的索引和切片
s1 = Series(data=[1,2,3],index=['a','b','c'])
s1['a'] # 1
s1[0] # 1
s1.a # 1
s1[0:2]
a 1
b 2
dtype: int64
s1['a':'c']
a 1
b 2
c 3
dtype: int64
Series的常用属性
- shape
- size
- index
- values
s1.shape # (3,)
s1.size # 3
s1.index # Index(['a', 'b', 'c'], dtype='object')
s1.values # array([1, 2, 3], dtype=int64)
Series的常用方法
- head(),tail() # 取开头和结尾几个
- unique() # 去重
- isnull(),notnull() # 是否是空值(缺失值) 返回布尔值
- add() sub() mul() div() # 每个值都进行加减乘除运算
Series的算术运算
s1 = Series(data=[1,2,3,4],index=['a','b','c','d'])
a 1
b 2
c 3
d 4
dtype: int64
s2 = Series(data=[1,2,3,4],index=['a','b','e','d'])
a 1
b 2
e 3
d 4
dtype: int64
- Series的运算法则:
- 索引一致的元素值进行算数运算,否则补空
s = s1+s2
a 2.0
b 4.0
c NaN
d 8.0
e NaN
dtype: float64
- 基于Series的空值(缺失值)过滤 将每条数据是否为空值计算出来,返回的布尔值当做索引算出数据
-
isnull,notnull:判断某些元素是否为空值
s.isnull()
a False
b False
c True
d False
e True
dtype: bool
-
#使用布尔值充当索引
s[[True,True,False,True,False]]
a 2.0
b 4.0
d 8.0
dtype: float64
s.notnull()
a True
b True
c False
d True
e False
dtype: bool
s[s.notnull()]
a 2.0
b 4.0
d 8.0
dtype: float64
DataFrame
-
DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
- 行索引:index
- 列索引:columns
- 值:values
-
DataFrame的创建
- ndarray创建
- 字典创建
DataFrame(data=np.random.randint(0,100,size=(4,6)))
0 1 2 3 4 5
0 69 71 54 12 35 16
1 98 80 23 32 57 70
2 22 55 42 63 94 26
3 16 4 36 84 75 17
dic = {
'name':['张三','李四','王老五'],
'salary':[10000,20000,15555]
}
df = DataFrame(data=dic,index=['a','b','c'])
name salary
a 张三 10000
b 李四 20000
c 王老五 15555
DataFrame的属性
- values、columns、index、shape
df.values # 返回值
df.columns # 返回列索引
df.index # 返回行索引
df.shape # 返回形状 几行几列
============================================
练习4:
根据以下考试成绩表,创建一个DataFrame,命名为df:
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0
from pandas import DataFrame
import numpy as np
dic = {
'张三':[150,150,150,150],
'李四':[0,0,0,0]
}
df = DataFrame(data=dic, index=['语文','数学','英语','理综'])
df
============================================
DataFrame索引操作
- 对行进行索引 行索引需要加loc或iloc
- 队列进行索引 列索引直接中括号
- 对元素进行索引 行列定位元素
#取出第一列
df['name']
a 张三
b 李四
c 王老五
Name: name, dtype: object
#取出多列
df[['name','salary']]
name salary
a 张三 10000
b 李四 20000
c 王老五 15555
#取出一行
df.loc['a']
df.iloc[0]
name 张三
salary 10000
Name: a, dtype: object
#取多行
df.loc[['a','b']]
df.iloc[[0,1]]
name salary
a 张三 10000
b 李四 20000
- loc['显式索引']
- iloc[隐式索引]
# 取单个的元素(李四的薪资取出) # 行索引列索引定位元素
df.iloc[1,1] # 20000
df.loc['b','salary'] # 20000
# 取多个的元素 # 行
df.loc[['a','c'],'salary']
a 10000
c 15555
Name: salary, dtype: int64
DataFrame的切片操作
- 对行进行切片 行切片直接中括号
- 对列进行切片 列切片需要加loc或iloc , loc顾头顾尾 ,iloc顾头不顾尾
#切出前两行
df[0:2]
df['a':'b']
name salary
a 张三 10000
b 李四 20000
#切出前两列
df.iloc[:,0:2]
df.loc[:,'name':'salary']
name salary
a 张三 10000
b 李四 20000
c 王老五 15555
索引和切片的汇总
ps:
col : 列
row:行
索引:
- df[col]:取单列
- df[[col1,col2]]:取多列
- df.loc[row]:取单行
- df.loc[[row1,row2]]:取多行
- df.loc[row,col]:取元素
切片
-
切行:df[row1:row3]
-
切列:df.loc[:,col1:col3]
-
DataFrame的运算:和Series的运算法则一样
=============================================================
练习:
-
假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。
-
假设张三期中考试数学被发现作弊,要记为0分,如何实现?
-
李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?
-
后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?
============================================
-
时间数据类型的转换
- pd.to_datetime(col)
-
将某一列设置为行索引
- df.set_index()
-
股票:
- 使用tushare包获取某股票的历史行情数据。
- tushre财经数据接口包:提供了各种财经历史交易数据
- 下载tushare:pip install tushare
- 输出该股票所有收盘比开盘上涨3%以上的日期。
- 输出该股票所有开盘比前日收盘跌幅超过2%的日期。
- 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
- 使用tushare包获取某股票的历史行情数据。
"""
分析:设定买卖股票是基于股票的开盘价进行买卖的
买入:
一个完整的年需要买入12次股票共计1200只
将每月第一个交易日对应的行数据取出,从行数据中提取出购买的单价(开盘价)
卖出:
一个完整的年需要卖出1次股票共计1200只
将每年最后一个交易日的行数据取出,从行数据中提取出售卖的单价(开盘价)
特殊情况:
在2020年只可以买入100只股票但是无法卖出。但是剩余股票的价值也需要计算到总收益中
"""
import tushare as ts
df = ts.get_k_data('600519',start='2000-01-01') # tushare获取历史行情
df.to_csv('./maotai.csv') # 写入到文件
df = pd.read_csv('./maotai.csv') # 将本地的数据读取到df
df.head(5)
#将无用的列删除.drop系列的函数中axis=0为行,1为列 与numpy中相反
df.drop(labels='Unnamed: 0',axis=1,inplace=True) #inplace=True把数据从原始数据中删除
##将date列中的数据类型转换成时间序列类型
df['date'] = pd.to_datetime(df['date'])
df.info() # 数据的详细信息,数据的行数,每一列元素的数据类型,可以查看有没有空值
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4385 entries, 0 to 4384
Data columns (total 7 columns):
date 4385 non-null datetime64[ns]
open 4385 non-null float64
close 4385 non-null float64
high 4385 non-null float64
low 4385 non-null float64
volume 4385 non-null float64
code 4385 non-null int64
dtypes: datetime64[ns](1), float64(5), int64(1)
memory usage: 239.9 KB
"""
#将date列作为源数据的行索引
df.set_index('date',inplace=True)
# 输出该股票所有收盘比开盘上涨3%以上的日期。
#(收盘-开盘)/开盘 > 0.03
(df['close'] - df['open'])/df['open'] > 0.03
#将布尔值作为了源数据df的行索引,可以取出True对应的行数据
df.loc[(df['close'] - df['open'])/df['open'] > 0.03].index
"""
DatetimeIndex(['2001-08-27', '2001-08-28', '2001-09-10', '2001-12-21',
'2002-01-18', '2002-01-31', '2003-01-14', '2003-10-29',
'2004-01-05', '2004-01-14',
...
'2019-03-01', '2019-03-18', '2019-04-10', '2019-04-16',
'2019-05-10', '2019-05-15', '2019-06-11', '2019-06-20',
'2019-09-12', '2019-09-18'],
dtype='datetime64[ns]', name='date', length=303, freq=None)
"""
# shift(1):将Series的数据整体向下移动一位
#输出该股票所有开盘比前日收盘跌幅超过2%的日期
#(开盘-前日收盘)/前日收盘 < -0.02
#将布尔值作为源数据的行索引
df.loc[(df['open'] - df['close'].shift(1))/df['close'].shift(1) < -0.02].index
"""
DatetimeIndex(['2001-09-12',
太多了,略······
,'2020-01-02'],
dtype='datetime64[ns]', name='date', freq=None)
"""
"""
假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
分析:设定买卖股票是基于股票的开盘价进行买卖的
买入:
一个完整的年需要买入12次股票共计1200只
将每月第一个交易日对应的行数据取出,从行数据中提取出购买的单价(开盘价)
卖出:
一个完整的年需要卖出1次股票共计1200只
将每年最后一个交易日的行数据取出,从行数据中提取出售卖的单价(开盘价)
特殊情况:
在2020年只可以买入100只股票但是无法卖出。但是剩余股票的价值也需要计算到总收益中
"""
data = df['2010':'2020'] # data表示的是2010-2020年之间的历史交易数据
df_month_first = data.resample('M').first() # 按照月份进行重新取样,取每个月的第一个交易日
send_money = df_month_first['open'].sum() * 100 # 总支出
df_year_last = data.resample('A').last()[:-1] # 按照年份进行重新取样, 取出每年的最后交易日数据
recv_money = df_year_last['open'].sum() * 1200 # 2020年之前的总收入
last_money = data['open'][-1] * 100 # 2020年一月的股票价值
all_money = recv_money - send_money + last_money # 总利润
day02
需求:双均线策略制定
使用tushare包获取某股票的历史行情数据
计算该股票历史数据的5日均线和30日均线
什么是均线?
- 对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、30天、60天、120天和240天的指标。
- 5天和10天的是短线操作的参照指标,称做日均线指标;
- 30天和60天的是中期均线指标,称做季均线指标;
- 120天和240天的是长期均线指标,称做年均线指标。
均线计算方法:MA=(C1+C2+C3+...+Cn)/N C:某日收盘价 N:移动平均周期(天数)
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import tushare as ts#财经数据接口包
import matplotlib.pyplot as plt
df = ts.get_k_data('600519',start='2000-01-01')
df.to_csv('./maotai.csv')
df = pd.read_csv('./maotai.csv')
df.head()
df.drop(labels='Unnamed: 0',axis=1,inplace=True)
df.info() # 消息信息
df.describe() # 聚合操作
# 将date列的数据转成时间序列且将其作为源数据的行索引
df['date'] = pd.to_datetime(df['date'])
df.set_index('date',inplace=True)
#ma表示的是均线
ma5 = df['close'].rolling(5).mean() # 5日均线
ma30 = df['close'].rolling(30).mean() # 30日均线
#将ma5和ma30汇总到源数据中
df['ma5'] = ma5
df['ma30'] = ma30
df
可视化历史数据的收盘价和两条均线
plt.plot(ma5[50:100],c='red')
plt.plot(ma30[50:100],c='blue')
分析输出所有金叉日期和死叉日期
-
股票分析技术中的金叉和死叉,可以简单解释为:
- 分析指标中的两根线,一根为短时间内的指标线,另一根为较长时间的指标线。
- 如果短时间的指标线方向拐头向上,并且穿过了较长时间的指标线,这种状态叫“金叉”;
- 如果短时间的指标线方向拐头向下,并且穿过了较长时间的指标线,这种状态叫“死叉”;
- 一般情况下,出现金叉后,操作趋向买入;死叉则趋向卖出。当然,金叉和死叉只是分析指标之一,要和其他很多指标配合使用,才能增加操作的准确性。
-
如果我从假如我从2010年1月1日开始,初始资金为100000元,金叉尽量买入,死叉全部卖出,则到今天为止,我的炒股收益率如何?
df = df['2010':'2020']
df
sr1 = df['ma5'] < df['ma30']
sr2 = df['ma5'] >= df['ma30']
让sr1和sr2.shift(1)进行与操作或者或操作,返回的结果定位到金叉和死叉
df.loc[sr1 & sr2.shift(1)] #死叉对应的行数据
death_dates = df.loc[sr1 & sr2.shift(1)].index
df.loc[~(sr1 | sr2.shift(1))]#金叉对应的行数据
golden_dates = df.loc[~(sr1 | sr2.shift(1))].index
基于金叉和死叉买卖股票计算收益
first_money = 100000
money = first_money
hold = 0 # 持有股票的数量(股)
s1 = Series(1,index=golden_dates)# 1标识金叉日期
s2 = Series(0,index=death_dates)# 0表示死叉日期
s = s1.append(s2) # 存储的是所有的金叉和死叉日期
s = s.sort_index() # 根据索引排序
for i in s.index:
# 开盘价作为买卖的单价
price = df.loc[i]['open']
if s[i] == 1:# 金叉:买入
hand_cost = 100 * price# 1手股票花费的钱数
hand_count = money // hand_cost # 最多买入了多少手股票
hold = hand_count * 100 # 买入的多少只股票
money -= hold*price # 买入后还剩多少钱
else:
# 死叉,卖出
money += hold * price # 卖出收入多少钱
hold = 0 # 卖出后所持股票数量为0
# 如果最后一天为金叉,最后一天买入股票,没有卖出。剩余的股票也要计算到总收益中
last_money = hold * df['open'][-1] # 使用剩余的股票乘以最后一天的开盘价
print(money + last_money - first_money) # 最终受益
处理丢失数据
有两种丢失数据:
- None
- np.nan(NaN)
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import tushare as ts#财经数据接口包
import matplotlib.pyplot as plt
两种丢失数据的区别
type(np.nan) # float
np.nan + 3 # nan nan跟任何数值进行运算都是nan
type(None) # NoneType None不能参与运算
- pandas中的None和NAN
df = DataFrame(data=np.random.randint(0,100,size=(8,5)))
df
df.iloc[1,2] = None
df.iloc[3,4] = None
df.iloc[4,1] = None
df.iloc[7,4] = np.nan
pandas处理空值操作
-
isnull
-
notnull
-
any
-
all
-
dropna
-
fillna
-
检测出原始数据中哪些行中存在空值
删除空值
- any和all可以帮我们检测df中哪些行列中存在空值
- isnull->any(axis=1)
- notnull->all(axis=1)
~df.isnull().any(axis=1) # 配合使用
df.loc[~df.isnull().any(axis=1)] # 删除存在空值的行
df.notnull().all(axis=1) # 配合使用
df.loc[df.notnull().all(axis=1)] # 删除存在空值的行
df.dropna(axis=0) #将空值对应的行数据删除
drop系列方法的axis的参数与正常相反
填充空值
#fillna将空值进行覆盖
df.fillna(method='ffill',axis=0) #使用紧邻值填充空值
# ffill 使用前面的值填充
# bfill 使用后面的值填充
# axis 指定使用行还是列的值
面试题
-
数据说明:
- 数据是1个冷库的温度数据,1-7对应7个温度采集设备,1分钟采集一次。
-
数据处理目标:
- 用1-4对应的4个必须设备,通过建立冷库的温度场关系模型,预估出5-7对应的数据。
- 最后每个冷库中仅需放置4个设备,取代放置7个设备。
- f(1-4) --> y(5-7)
-
数据处理过程:
- 1、原始数据中有丢帧现象,需要做预处理;
- 2、matplotlib 绘图;
- 3、建立逻辑回归模型。
-
无标准答案,按个人理解操作即可,请把自己的操作过程以文字形式简单描述一下,谢谢配合。
-
测试数据为testData.xlsx
处理重复数据
处理异常数据
- 自定义一个1000行3列(A,B,C)取值范围为0-1的数据源,然后将C列中的值大于其两倍标准差的异常值进行清洗

浙公网安备 33010602011771号