数据分析

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 = '?':可以修改数据类型
    image.png
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: 数据类型
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列,对应位置的每个值的乘积之和。
    • 线性代数基于矩阵的推导:
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的运算法则一样

=============================================================

练习:

  1. 假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。

  2. 假设张三期中考试数学被发现作弊,要记为0分,如何实现?

  3. 李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?

  4. 后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?

============================================

  • 时间数据类型的转换

    • pd.to_datetime(col)
  • 将某一列设置为行索引

    • df.set_index()
  • 股票:

    • 使用tushare包获取某股票的历史行情数据。
      • tushre财经数据接口包:提供了各种财经历史交易数据
      • 下载tushare:pip install tushare
    • 输出该股票所有收盘比开盘上涨3%以上的日期。
    • 输出该股票所有开盘比前日收盘跌幅超过2%的日期。
    • 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
"""
分析:设定买卖股票是基于股票的开盘价进行买卖的
买入:
一个完整的年需要买入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列中的值大于其两倍标准差的异常值进行清洗
posted @ 2020-04-21 14:54  我的儿  阅读(143)  评论(0)    收藏  举报