Numpy简介
Numpy是高性能科学计算和数据分析的基础包。它是pandas等其他各种工具的基础。
Numpy的主要功能:
- ndarray,一个多维数组结构,高效且节省空间
- 无需循环对数组数据进行快速运算的数学函数
- 线性代数、随机数生成和博立叶变换功能
创建ndarray:np.array(array_list)
数组与列表的区别:
- 数组对象内的元素类型必须相同
- 数组大小不可修改
常用属性
- T 数组的转置
- size 数组元素的个数
- ndim 数组的维数
- shape 数组的维度大小(元祖形式)
- dtype 数组元素的数据类型
创建array
np.zeros(10) # 10个 0.的数组
np.ones(10) # 10个的1.的数组
a = np.empty(100) # 内存中存的值
np.arange(100) # 快速创建100的数组
np.arange(15).reshape(3, 5) # 创建二维数组
np.arange(2, 10, 0.3)
np.linspace(0, 50, 100) # 0 ~ 50 平分成100份
np.eye(10) # 线性代数
ndarray 批量运算
数组和标量之间的运算
a+1 1*3 1//a a**0.5 a>5
同样大小数组之间的运算
a+b a/b a**b a%b a==b
索引
-
一位数组索引
a[5]
-
多维数组索引
- 列表式写法
a[2][1]
- 新式写法
a[2, 1]
- 列表式写法
切片
- 一位数组:
a[5:8]
a[4:]
a[2:10]
- 多维数组:
a[1:2, 3:4]
a[:, 3:5]
a[:,1]
- np数组的切片与列表切片的不同:数组切片时并不会自动复制(而是创建一个视图),在切片数组上的修改会影响原数组
copy()
方法可以创建数组的深拷贝
ndarray布尔型索引
问题:给一个数组,选出数组中所有大于5的数
答案:a[a>5]
原理
- 数组与标量的运算:a>5会对a中的每一个元素进行判断,返回一个布尔数组
- 布尔型索引:将同样大小的布尔数组传进索引,会返回一个由所有
True
对应位置的元素的数组
例子:
# 1,给一个数组,选出数组中所有大于5的数
a = np.array([random.randint(1, 10) for _ in range(20)])
a[a>5] # array([8, 6, 6, 7, 7, 6, 6])
# 2,给一个数组,选出数组中所有大于5的偶数
a = np.array([random.randint(1, 10) for _ in range(20)])
a[(a>5) & (a%2==0)]
# 3,给一个数组,选出数组中所有大于5的数和偶数
a = np.array([random.randint(1, 10) for _ in range(20)])
a[(a>5) | (a%2==0)]
ndarray花式索引
根据索引位置给出值
a = np.arange(20)
a[[1,4,5,6]] # array([1, 4, 5, 6])
a = np.arange(20).reshape(4,5) # array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19]])
a[0, 2:5] # array([7, 8, 9])
a[0, a[0]>2]
a[[1, 3], [1, 3]] # 注意2个花式索引的取法,解析有点不一样,获取到的值是:array([ 6, 18])
# 如果就是想取6 8 16 18 可以使用下满的方法
a[[1, 3],:][:,[1,3]] # : 表示全切
Numpy 通用函数
通用函数:能同时对数组中所有元素进行运算的函数
补充知识:
int # 向零取整
round # 向零外取整,round到两边距离相等时取偶数值
math.floor # 向小取整(向左取整)(地板)
math.ceil # 向大取整(向右取整)(天花)
常见通用函数:
一元函数: 对一维数组处理
np.abs(a) # 绝对值
np.sqrt(a) # 开方
np.exp(a)
np.log(a)
np.ceil(a) # 向大取整(向右取整)(天花)
np.floor(a) # 向小取整(向左取整)(地板)
np.rint(a) # 等价于 round
np.round(a) # 向零外取整,round到两边距离相等时取偶数值
np.trunc(a) # 向零取整
np.modf(a) # 将小数和整数拆开
np.isnan(a) # 过滤nan
np.isinf(a) # 过滤inf
np.cos(a)
np.sin(a)
np.tan(a)
例子
a = np.arange(-5.5,5)
np.abs(a)
x, y = np.modf(a) # 将小数和整数拆开,x是小数,y是整数
# numpy过滤nan
a = np.arange(0,5)
b = a/a # array([nan, 1., 1., 1., 1.])
b[~np.isnan(b)] # ~ 是取反
# numpy过滤inf
a=np.array([3,4,5,6])
b=np.array([2,0,3,0])
c = a/b
c[c!=np.inf] # 过滤inf
c[~np.isinf(c)] # 过滤inf
二元函数: 对二维数组处理
np.add(a,b) # a数组 + b数组
np.subtract(a,b) # a-b 一般不用调函数,直接对数组相加就好
np.multiply(a,b)
np.divide(a,b)
np.power(a,b)
np.mod(a,b)
np.maximum(a,b) # 两个数组中的最大
np.minimum(a,b) # 两个数组中的最小
Numpy 数学和统计方法
sum # 求和
mean # 求平均值
std # 求标准差
var # 求方差
min # 求最小值
max # 求最大值
argmin # 求最小值索引
argmax # 求最大值索引
# 求方差
1 2 3 4 5
mean:3
((1-3)**2+(2-3)**2+(3-3)**2+(4-3)**2+(5-3)**2)/5
# 方差表示你这组数据的离散程度
标准差 = sqrt(方差)
# 差不多60%的数据分布在这区间
a.mean()+a.std()
a.mean()-a.std()
# 差不多80%的数据分布在这区间
a.mean()+2*a.std()
a.mean()-2*a.std()
Numpy 随机数生成
随机数函数在np.random
子包内
np.random.rand 给定形状产生随机数组(0 ~ 1之间)
np.random.randint 给定**长度**产生随机整数
np.random.choice 给定形状产生随机选择
np.random.shuffle 与random.shuffle相同
np.random.uniform 给定形状产生随机数组
例子
np.random.randint(0, 10, 10) # 生成一个长度10的随机数组
np.random.rand(5)
np.random.choice([1,2,3,4,5], (2,3))
np.random.uniform(2,5, (3,4))
补充 - 浮点数特殊值
nan (Not a Number)
: 不等于任何浮点数(nan != nan)inf(infinity)
:比任何浮点数都大- Numpy中创建特殊值:
np.nan
np.inf
- 在数据分析中,
nan
常被用作表示数据缺失值
Pandas 数据分析
pandas简介
pandas是一个强大的Python数据分析的工具包,是基于NumPy构建的。
pandas的主要功能:
- 具备对其功能的数据结构DataFrame、Series
- 集成时间序列功能
- 提供丰富的数学运算和操作
- 灵活处理缺失数据
安装方法:pip install pandas
引用方法:import pandas as pd
Series 一维数组对象
Series是一种类似于一维数组的对象,由一组数据和一组与之相关相关的数据标签(索引)组成。
创建方式:
pd.Series([4, 5, -5, 3])
pd.Series([4, 5, -5, 3], index=['a', 'b', 'c', 'd'])
pd.Series({'a': 1, 'b': 2, 'c': 3})
pd.Series(0, index=['a', 'b', 'c'])
合并两个Series
sr = sr1.append(sr2).sort_index() # 方式二 (0,死叉) (1,金叉)
获取值数组和索引数组:values
属性和index
属性
Series比较像列表(数组)和字典的结合体
Series 使用特性
Series支持array的(下标)特性:
- 从
ndarray
创建Series:Series(arr)
- 与标量运算:
sr * 2
- 两个Series运算:
sr1+sr2
- 索引:
sr[0]
[sr[[1,2,4]]]
- 切片:
sr[0:2]
- 通用函数:
np.abs(sr)
- 布尔值过滤:
sr[sr>0]
Series支持字典的特性(标签)
- 从字典创建Series:
Series(dic)
- in运算:
'a' in sr
- 键索引:
sr['a']
sr[['a', 'b', 'd']]
sr.index
sr.values
sr.index[0]
sr[[1, 3]]
sr[['a', 'd']]
sr['a': 's'] # 通过标签切片,前包后也包
Series 整数索引
pandas Series对象的整数索引往往会使新手抓狂。
例如:
sr = pd.Series(np.arange(4))
sr[-1] # 会报错
如果索引是整数类型,则根据整数进行下标获取值时总是面向标签的。
解决办法:loc
属性(将索引解释为标签)和iloc
属性(将索引解释为下标)
sr2.loc[10] # 根据标签索引
sr2.iloc[10] # 根据下标索引
sr2.iloc[-1]
sr2.iloc[3:6]
sr2.iloc[[2, 3, 7]]
Series 数据对齐
两个series数组对象,将会根据索引对齐后再相加
sr1 = pd.Series([11,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
sr1+sr2 # 将会按照index对齐之后进行相加
sr1 = pd.Series([11,23,34], index=['c','a','d'])
sr2 = pd.Series([11,20,10,21], index=['d','c','a','b'])
sr1+sr2 # 出现缺省值,b 将会用 NaN 代替
sr1 = pd.Series([11,23,34], index=['b','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
sr1+sr2 # b NaN c NaN
sr1 = pd.Series([11,23,34], index=['b','a','d'])
sr2 = pd.Series([11,20,10], index=['d','c','a'])
# 如何使结果在索引`b`处的值为11,在索引`c`处的值为20
# 灵活的算术方法:add sub div mul
sr1.add(sr2, fill_value=0) # sr1 + sr2 , 有NaN就用0代替
Series 缺失值的处理
sr.isnull() # NaN 返回 True
sr.notnull() # not NaN 返回 True
# 丢掉
sr = sr[sr.notnull()]
sr = sr.dropna()
# 填充成其他值
sr = sr.fillna(0) # 使用0填充
sr = sr.fillna(sr.mean()) # 使用平均值填充
DataFrame的创建方式
dataframe的列得是同一个类型
DataFrame是一个表格型的数据结构,含有一组有序的列。DataFrame可以被看作是由Series组成的字典,并且共用一个索引。
创建方式
# 方式一
pd.DataFrame({'one': [1,2,3], 'two': [4,5,6]})
pd.DataFrame({'one': [1,2,3], 'two': [4,5,6]}, index=['a','b','c'])
# 方式二
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']), 'two':pd.Series([1,2,3,4], index=['b','a','c','d'])})
csv文件读取与写入
df.to_csv('test2.csv')
pd.read_csv('test2.csv')
DataFrame 常用属性
index 行索引
T 转置
columns 获取列索引
values 获取值数组 (二维数组)
describe() 获取快速统计
DataFrame 索引和切片
DataFrame是一个二维数据类型,所以有行索引和列索引。
DataFrame同样可以铜鼓标签和位置两种方法进行索引和切片
loc
属性和iloc
属性
- 使用方法:逗号隔开,前面是行索引,后面是列索引
- 行/列索引部分可以是常规索引、切片、布尔值索引、花式索引任意搭配
loc
会将行解释为索引标签,iloc
会将行解释为其索引下标
df['one']['a'] # one是列索引,a是行索引
df.loc['a', 'one'] # 推荐这种,a 是 行索引,one是列索引
df.loc['a',:] # 切片 a 这一行数据
df.loc[['a','c'],:]
df.loc[['a','c'],'two'] # 任意搭配
DataFrame 数据对齐与缺省数据
DataFrame对象在运算时,同样会进行数据对齐,其行索引和列索引分别对齐。
DataFrame处理缺省数据的相关方法:
dropna(axis=0,how='any',...) # axis=0按行删;axis=1按列删。how='any' 出现一个就删,how='all'都出现才删。
fillna() # 填充
isnull()
notnull()
df.dropna(how='all') # 都出现才删除 默认是 any
df2.dropna(axis=1) # 按列删 默认是0
Pandas 其他常用方法
mean(axis=0, skipna=False) 对列(行)求平均值
sum(axis=1) 对列(行)求平均值
sort_index(axio,...,ascending) 对列(行)索引排序
sort_values(by, axis, ascending) 按某一列(行)的值排序,注意:有nan的不参与排序 放到最后显示
# Numpy的通用函数同样适用于pandas
例子
f.sort_values(by='two') # 按two列排序
df.sort_values(by='two', ascending=False) # 按two降序排序
df.sort_values(by=1, ascending=False, axis=1) # 按1这一行降序排序
df.sort_index() # 按行索引排序
df.sort_index(ascending=False) # 按行索引降序排序
df.sort_index(ascending=False, axis=1) # 按列索引降序排序
Pandas 时间对象
时间序列类型:
- 时间戳:特定时刻
- 固定日期:如2017年7月
- 时间间隔:起始时间-结束时间
Python标准库处理时间对象:datetime
灵活处理时间对象: dateutil
dateutil.parser.parse()
成组处理事件对象:pandas
pd.to_datetime()
datetime.datetime.strptime('2010-08-21', '%Y-%m-%d')
import dateutil
dateutil.parser.parse('2001-01-01')
dateutil.parser.parse('200101/01')
dateutil.parser.parse('2001/01/01')
dateutil.parser.parse('01/01/2020')
pd.to_datetime(['2019-01-01','2010/Feb/02'])
Pandas 时间对象处理
产生时间对象数组 date_range
start 开始时间
end 结束时间
period 时间长度
freq 时间频率,默认为'D', 可选H(our), W(eek), B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year), ...
pd.date_range('2010-01-01','2010-5-1')
pd.date_range('2010-01-01',periods=60)
pd.date_range?
pd.date_range('2010-01-01',periods=60,freq='H')
pd.date_range('2010-01-01',periods=60,freq='W')
pd.date_range('2010-01-01',periods=60,freq='W-MON')
pf = pd.date_range('2010-01-01',periods=60,freq='B')
pd.date_range('2010-01-01',periods=60,freq='1h20min')
df[0].to_pydatetime() # 转换成Python的datetime类型
将索引转换为时间列
df['date'] = pd.to_datetime(df['date'])
df.set_index("date", inplace=True)
# df.set_index('date',drop=True)
Pandas 时间序列
时间序列就是以时间对象为索引的Series或DataFrame
datetime对象作为索引时是存储在DatetimeIndex对象中的
时间序列特殊功能:
- 传入“年”或“年月”作为切片方式
- 传入日期范围作为切片方式
- 丰富的函数支持:resample(), truncate() ....
sr = pd.Series(np.arange(1000), index=pd.date_range('2017-1-1', periods=1000))
sr['2017-3']
sr['2017-4']
sr['2017']
sr['2017':'2018-3']
sr['2017-12-24':'2018-2-1']
sr.resample('W').sum() # 按周求和
sr.resample('m').sum()
sr.resample('m').mean()
sr.resample('M').first() # 每个月第一天数据
sr.truncate(before='2018-2-3') # 切掉掉前面的,因为有时间切片了,所以不推荐这个方法
sr.truncate(after='2018-2-3')
Pandas 文件处理
数据文件常用格式:csv
(以某间隔符分割字符)
pandas读取文件:从文件名、URL、文件对象中加载数据
read_csv
默认分隔符为逗号read_table
默认分隔符为制表符
read_csv
read_table
函数主要参数
sep 指定分隔符,可用正则表达式,如's+', 不指定则默认是 `,`
header=None 指定文件无列名
names 指定列名
index_col 指定某列作为索引
skip_row 指定跳过某些行
na_values 指定某些字符串表示缺失值(将某些奇怪字符串解析成NaN)
parse_dates 指定某些列是否被解析为日期,类型为布尔型或列表
例子
# 常用
df = pd.read_csv('zn2006SHFE2020.csv', index_col='datetime', parse_dates=['datetime'])[['open','high','low','close']]
pd.read_csv('zn2006.csv')
pd.read_csv('zn2006.csv', index_col=0) # 指定第0列为索引
pd.read_csv('zn2006.csv', index_col='datetime') # 指定`datetime`列为索引
pd.read_csv('zn2006.csv', index_col='datetime', parse_dates=True)
pd.read_csv('zn2006.csv', index_col='datetime', parse_dates=['datetime'])
pd.read_csv('zn2006.csv', header=None)
pd.read_csv('zn2006.csv', header=None, names=list('qwertyuiopasdfg'))
pd.read_csv('zn2006.csv', header=None, skiprows=[2,3,4])
pd.read_csv('zn2006.csv', na_values=['None']) # 将None替换为NaN
写入到CSV文件:to_csv
函数
写入文件函数的主要参数:
sep 指定文件分隔符
na_rep 指定缺失值转换的字符串,默认为空字符串
header=False 不输出列名一行
index=False 不输出行索引一行
cols 指定输出的列,传入列表
df.to_csv('test.csv', header=False, index=False, na_rep='null')
df.to_csv('test.csv', header=False, index=False, na_rep='null',columns=['open','high','low','close'])
df.to_html('test.html')
pd.read_excel('test.xlsx')
pandas支持的其他文件类型
- json
- xml
- html
- 数据库
- pickle
- excel
补充
rolling函数
可以取前10的窗口
df['pre_high'] = df['high'].rolling(10).max()
shift
平移函数
通过shift函数里面的值来控制向前还是向后偏移, 缺少的值会填充NaN,groupby函数里的参数控制基于什么字段进行shift.
注意:-1
是向前前移
df16['pre_close'] = df16['close'].shift(1) # 向后偏移
temp['value_shift'] = temp.groupby('id')['value'].shift(1);temp
Out[180]:
id value value_shift
0 1 1 NaN
1 1 2 1.0
2 1 3 2.0
3 2 4 NaN
4 2 5 4.0
5 3 6 NaN
temp['value_shift_1'] = temp.groupby('id')['value'].shift(-1);temp
Out[181]:
id value value_shift value_shift_1
0 1 1 NaN 2.0
1 1 2 1.0 3.0
2 1 3 2.0 NaN
3 2 4 NaN 5.0
4 2 5 4.0 NaN
5 3 6 NaN NaN
通过shift
函数里面的值来控制向前还是向后偏移, 缺少的值会填充NaN
.
groupby
函数里的参数控制基于什么字段进行shift
.
补充函数
series.describe() # 总结数据分布情况
np.sign(<series/array>) # sign()是Python的Numpy中的取数字符号(数字前的正负号)的函数。(大于0,返回1) ;(等于0,返回0);(小于0,返回-1)
Series.value_counts() # 统计值的出现次数
series.cumsum() # 累加之前的数据
series.cumprod() # 累乘之前的数据
series.pct_change() # 表示当前元素与先前元素的相差百分比,当然指定periods=n,表示当前元素与先前第n 个元素的相差百分比。可以用来算当天较上一天的return(收益)