numpy 和 pandas基础学习

1. numpy创建数组:array()

import numpy as np
import pandas as pd


# 创建一维数组
res = np.array([1,2,3])
print(res) # [1 2 3]

# 创建二维数组,多维数组以此类推
res = np.array([[1,2,3],[4,5,6]])
print(res) 
"""
[[1 2 3]
 [4 5 6]]
"""

数组特点:

# 数组中数据类型是统一的
res = np.array([[1,'strvar',3],[4,4.9,6]])
print(res)
"""
优先级顺序:
字符串>浮点型>整型
[['1' 'strvar' '3']
 ['4' '4.9' '6']]
"""

 

numpy相关方法:ones() zero() linspace() arange() random.randint()random.random() astype()

# ones()方法创建一个数组,值用1填充,shape制定数组的形状和维度,三个参数的话就是三维
# zero()方法同理,只不过值用0填充
ar = np.ones(shape=(3,4))
print(ar)
"""
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
"""

# linspace()是返回一个一维的数组, num代表需要几个数值,然后linspace会等分形成一个一维数组
ar = np.linspace(0,30,num=6)
print(ar) # [ 0.  6. 12. 18. 24. 30.]

# arange()也是返回一个一维数组,第三个参数是步长
ar = np.arange(0,30,8)
print(ar) # [ 0  8 16 24]

# random.ranint()在制定的范围内返回随机数组,size是返回数组维度和形状
ar = np.random.randint(10,20,size=(3,4))
print(ar)
"""
[[17 10 13 10]
 [11 15 15 12]
 [13 18 16 19]]
"""

# random.random()是返回0到1之间的随机浮点数数组
ar = np.random.random(size=(2,3))
print(ar)
"""
[[0.45168459 0.64069979 0.68093153]
 [0.68517369 0.67128161 0.21001053]]
"""

# astype()可修改数组的数据类型
ar = np.array([1,2,3],dtype='float32')
print(ar)

res = ar.astype('int8')
print(res)
"""
[1. 2. 3.]
[1 2 3]
"""

numpy相关属性:shape, ndim, size, dtype

# shape属性返回数组的形状
res = ar.shape
print(res) # (2, 3)

# ndim属性返回数组的维度
res = ar.ndim
print(res)  # 2

# size属性返回数组的元素个数
res = ar.size
print(res) # 6

# dtype属性返回数组元素的数据类型
res = ar.dtype
print(res) # float64

# type属性返回数组的数据类型
res = type(ar)
print(res) # <class 'numpy.ndarray'>

numpy的索引和切片:

ar = np.random.randint(10,20,size=(4,5))
print(ar)
# 切出数组的前两行
res = ar[0:2]
print(res)

# 切出数组的前两列,冒号前面的代表是行的切片,冒号后面的是列的切片
res = ar[:,0:2]
print(res)

# 切出前两行的前两列
res = ar[0:2,0:2]
print(res)

# 将数组的行倒置
res = ar[::-1]
print(res)

# 将数组的列进行倒置
res = ar[:,::-1]
print(res)

# 应用:将图片进行翻转和裁剪
ar = plt.imread('./666.bmp')
# 左右翻转
ar = plt.imshow(ar[:,::-1,:])

# 图片裁剪
ar = plt.imshow(ar[50:100,100:150,:])

变形:reshape()

ar = np.random.randint(10,20,size=(2,4))
print(ar)

# 变成一维数组,注意元素的个数跟之前数组的元素个数一定要相等
ar = ar.reshape((8,))
print(ar)
# 变成三维数组
ar = ar.reshape((2,2,2))
print(ar)

# -1为自动计算,如行为4,根据元素相等,自动计算列有多少
ar = ar.reshape((4,-1))
print(ar)

级联拼接:concatenate()

ar = np.random.randint(10,20,size=(2,4))
print(ar)

# axis为0表示以行拼接,为1表示以列来拼接
# 注意,在以行拼接时要保证两个数组的行数一致,以列拼接时同理,不然报错
ar = np.concatenate((ar,ar),axis=0)
print(ar)

# 应用:图片九宫格拼接

常用的聚合函数:sum() max() min() mean()

ar = np.random.randint(10,20,size=(2,4))
print(ar)

# sum()返回数据数据的总和
res = ar.sum()
print(res) # 103

# max()返回数组数据的最大值,若指定了axis参数,则表示求行或者列
res = ar.max(axis=0)
print(res) # 19

# min()返回数据数据的最小值
res = ar.min()
print(res) # 10

# mean()返回数组数据的均值
res = ar.mean()
print(res) # 12.5

数学函数:

ar = np.array([33.72,12.39,3.88])
# decimals参数表示保留几位小数然后进行四舍五入计算,默认为1
res = np.around(ar,decimals=1)
print(res) # [33. 13.  4.]

# 参数decimals为-1代表区数组小数点左边的部分进行四舍五入
res = np.around(ar, decimals=-1)
print(res) # [30. 10.  0.]

# 统计函数,axis为1表示每行里面的最小值,返回列表,np.amax()同理
res = np.amin(ar,axis=1)
print(res) # [12 10 11]

# ptp()是数组里面最大值减去最小值
res = np.ptp(ar)
print(res) # 9

# median()是返回数组中元素的中位数,也可以用axis来指定轴
res = np.median(ar)
print(res) # 13.0

# std()是返回数组中的标准差,也可以用axis来指定轴
res = np.std(ar)
print(res) # 2.153807997220014

# var()是返回数组中的方差,也可以用axis来指定轴
res = np.var(ar)
print(res) # 1.909722222222222

数组的倒置和矩阵的乘法:

ar = np.random.randint(10,20,size=(3,4))
print(ar)

# T是数组所有元素的倒置
res = ar.T
print(res)

# dot()是矩阵的乘法
res = np.dot([[1,2],[2,3]],[[2,0],[1,4]])
print(res)

 

2. pandas:

Series相当于一个一维数组

 

DataFrame: 相当于一个二维数组

df = DataFrame(data=np.random.randint(10,20,size=(3,2)),columns=['第一列','第二列'],index=['第一行','第二行','第三行'])
print(df)
"""
columns是指定列索引的,index是指定行索引的
DataFrame的同样有shape index columns(返回列元素) values(返回元素)属性
     第一列  第二列
第一行   10   16
第二行   19   11
第三行   16   12
"""

# header防止将数据第一行内容当成头部信息,sep表示头部以自增数字表示
res = pd.read_csv('./tu.txt',header=None, sep='-')

DataFrame的索引和切片:

df = DataFrame(data=np.random.randint(10,20,size=(3,2)),columns=['第一列','第二列'],index=['第一行','第二行','第三行'])
print(df)
# 若指定了显示索引,只能直接使用显示列索引取值
res = df['第一列']
print(res)

# loc用于取显示行索引,第一行的第二列元素
res = df.loc['第一行','第二列']
print(res)

# iloc用于取隐示行索引,两个中括号表示取第一行和第二行的所有元素,逗号前面是行,后面是列
res = df.iloc[[0,1],]
print(res)

# 一个中括号表示取第一行的第二个元素
res = df.iloc[0,1]
print(res)

# 行切片
res = df[0:2]
print(res)

# 列切片
res = df.iloc[:,1:2]
print(res)

 

3. matplotlib创建图片数组和展示图片数组:

import matplotlib.pyplot as plt

# 可以读取图片信息,结果时三维数组
res = plt.imread('./666.bmp')
print(res)
"""
[[[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
"""
# 展示图片类型的数组
res = plt.imshow(res)
print(res)

# plt将二维数组展示成图片
a = np.array([[223,123,234],[255,143,25]])
res = plt.imshow(a)
print(res)

 

绘制简单图像:

# 绘制折线图
x = np.array([1,2,3,4])
y = x * 2
# 保存图像,实例化一个对象
fig = plt.figure()

# 等比例的放大或者缩小坐标系(刻度不会发生变化)
plt.figure(figsize=(3,6))

res = plt.plot(x,y,label='deadline')
# 调用图例
plt.legend()
print(res)

# 给坐标系设置标示
# 设置x抽名称
plt.xlabel('time')
# 设置y抽名称
plt.ylabel('money')
# 设置坐标系名称
plt.title('happy')

# 保存图像
fig.savefig('保存图像的路径')

# 绘制柱状图
x = [1,2,3,4] # x抽的标示
y = [2,4,5,1] # 柱状图的高度
plt.bar(x,y) # 柱状图
plt.barh(x,y) # 横向的柱状图

# 绘制直方图/密度图
x = [1,2,3,2,1,2,3,4,2,4,5,6,3,2,2,4,7]
# 标示数据出现的频次
plt.hist(x,bins=10) # bins标示柱子的个数

# 绘制饼图
x = [0.1,0.4,0.3] # 表示数据的比例
# labels参数表示给数据起别名,labeldistance表示别名距离圆心的距离
# autopct表示显示占比,保留两位小数,explode表示每部分跟圆心的距离
plt.pie(x,labels=['a','b','c'],labeldistance=0.5,autopct='%.2f%%',explode=[0.2,0.2,0.2])

# 绘制散点图
x = [1,2,3,4.9,5,4,2.8]
y = [0.1,0.4,0.2,0.8,0.9]
plt.scatter(x,y)

 

4. tushare简单使用

import tushare

t1 = tushare.get_k_data(code='603660', start='1993-11-23')
print(t1)

# 将数据存贮到本地
t1.to_csv('./tu.txt')

# 将外部数据加载到数组
df = pd.read_csv('./tu.txt')
print(df)

# 将第一列删除,labels表示删除的列名称,axis此时表示列,inplace表示在原来数组的基础上做修改
res = df.drop(labels='Unnamed: 0',axis=1,inplace=True)
print(df)

# 将列数据整体下移一位可以用列数据.shift(1)

# resample()方法可以重新取样,如取出每个月的第一条数据
df.resample(rule='M').first()

 

案例:计算某一股票金叉买入死叉卖出的收益

df = tushare.get_k_data(code='000001', start='2010-01',end='2021-1')
df.to_csv('./pingan.csv')
df = pd.read_csv('./pingan.csv')

# 删除不需要的这一行
df.drop(labels='Unnamed: 0',axis=1,inplace=True)
# 将时间字符串转给时间格式
df['date'] = pd.to_datetime(df['date'])
# 将时间变成行索引
df.set_index('date',inplace=True)

# 计算5日均值
ma5 = df['close'].rolling(5).mean()
# 计算30日均值
ma30 = df['close'].rolling(30).mean()
# 根据得到的布尔值来找金叉和死叉的时间点
s1 = ma5 < ma30
s2 = ma5 > ma30
# 取出死叉对应的时间点
sale_time = df.loc[s1 & s2.shift(1)].index
# 取出金叉对应的时间点
buy_time = df.loc[~(s1 | s2.shift(1))].index

# 将金叉和死叉时间存放在series中
series_1 = Series(data=1, index=buy_time)
series_2 = Series(data=0, index=sale_time)
# 将金叉死叉日期整合到一起,并且去掉30天均线前面的30个无意义日期
series_all = series_1.append(series_2).sort_index()[30:]

# 开始计算金叉和死叉的交易
first_money = 100000 # 本金
cost_money = 100000 # 手上剩余资金
hold = 0 # 手上持有股票(支)

for index in series_all.index:
    if series_all[index] == 1:
        # 说明是金叉,要买入股票
        # 当天股票开盘价
        price = df.loc[index]['open']
        # 剩余资金可以购买的手数
        hand = cost_money // (price * 100)
        # 购买股票的数量(支)
        hold = hand * 100
        # 手上剩余资金
        cost_money -= (hold * price)
    else:
        # 说明是死叉,应该卖出股票
        # 当天股票开盘价
        price = df.loc[index]['open']
        cost_money += (price * hold)
        hold = 0

# 计算最后手上剩余股票的资金
last_money = hold * df['open'][-1]
print(cost_money+last_money-first_money)

 

基于pandas的简单数据清洗:

空值处理:

# 简单的数据清洗
df = DataFrame(data=np.random.randint(10,20,size=(3,4)))
df.iloc[0,1] = None
df.iloc[2,2] = np.NAN
print(df)

# dropna()方法是删除空,axis为1表示行
res = df.dropna(axis=0)
print(res)

# fillna()方法是将空值填充
# 将空值以666来填充
res = df.fillna(value=666)
print(res)
# 使用空值的近邻值来填充
# axis表示为列,ffill表示为以列的前面一个值来填充,bfill表示为以列的后面一个值来填充
res = df.fillna(axis=0,method='ffill').fillna(axis=0,method='bfill')
print(res)

# 使用均值来填充空值
for col in df.columns:
    if df[col].isnull().sum() > 0:
        mean_value = df[col].mean()
        df[col] = df[col].fillna(value=mean_value)

重复值处理:

# 简单的数据清洗
df = DataFrame(data=np.random.randint(10,20,size=(3,4)))
df.iloc[1] = 2
df.iloc[2] = 2
print(df)

# duplicated表示去掉重复的行,keep代表保留重复的第一行,返回布尔值
res = df.duplicated(keep='first')
print(res)
# drop_duplicates()是直接返回删除重复行的数组,keep默认我first
res = df.drop_duplicates()
print(res)

 

级联操作:对表格进行拼接

# 行列索引都一致的叫匹配级联
df1 = DataFrame(data=np.random.randint(10,20,size=(3,4)))
df2 = DataFrame(data=np.random.randint(10,20,size=(3,4)))
# concat()是级联拼接,axis为1是以行做拼接
df3 = pd.concat((df1,df2),axis=1)
print(df3)

# 行列索引不一致
df1 = DataFrame(data=np.random.randint(10,20,size=(3,4)),index=['a','b','c'])
df2 = DataFrame(data=np.random.randint(10,20,size=(3,4)),index=['a','d','c'])
# 以行为索引进行拼接,没有问题,但是如果以列进行拼接,b,d两行会出现NAN
# join 参数表示的是拼接方式,inner表示拼接能拼接的,其他舍弃,outer表示所有都拼接,不能拼接的以NAN补充
df3 = pd.concat((df1,df2),axis=1,join='outer')
print(df3)

 

合并操作:对数据进行合并

df1 = DataFrame(data=np.random.randint(10,20,size=(3,4)),index=['a','b','c'])
df2 = DataFrame(data=np.random.randint(10,20,size=(3,4)),index=['a','d','c'])
# 以class字段合并df1和df2两个数组,on默认使用两个数组中的共同字段来连接
# how 参数inner表示合并能合并的,outer表示全都合并,left表示以左边为主合并,right表示以右边为主合并
# left_on指明左表使用的合并,right_on指明右表使用的合并,这样没有相同索引的两个数组也可以进行合并操作
df3 = pd.merge(df1,df2,on='class',how='inner')

 

pandas替换操作:replace

df1 = DataFrame(data=np.random.randint(10,20,size=(3,4)),index=['a','b','c'])
print(df1)

# replace()方法可以将一个值替换成另一个值
res = df1.replace(to_replace=11, value='一一',inplace=True)
print(df1)
# 多值替换
res = df1.replace(to_replace={11: "一一", 18: "一二"},inplace=True)
print(df1)
# 替换指定索引值
res = df1.replace(to_replace={2:11},value='第二行的11',inplace=True)
print(df1)

 

映射:

df = DataFrame(data=[['bob',12],['jack',14],['bob',12]],columns=['name','salary'])
print(df)

# 映射关系表
dic = {
    'bob': '张三',
    'jack': '李四'
}
# map()方法添加映射,map只是series的方法
df['cname'] = df['name'].map(dic)
print(df)

# 将原有工资加100
df['after_salary'] = df['salary'].map(lambda s : s+100)
print(df)

 

抽样和分组:

df = DataFrame(np.random.randint(10,20,size=(4,3)),columns=['A','B','C'])
print(df)

# 按照列对数组进行打乱,indices接收的是隐示索引,permutation()方法是随机生成3以下的数字
df = df.take(indices=np.random.permutation(3),axis=1)
print(df)

# 随机抽样
df = df.take(indices=np.random.permutation(3),axis=1).take(indices=np.random.permutation(4),axis=0)[:2]
print(df)

# 分组:groupby()分组,groups查看分组结果
res = df.groupby('B').groups
print(res)

 

数据透视图:

# 透视图:pivot_table()
# index代表分类条件,values代表筛选条件,columns设置列层次字段,aggfunc使用的聚合函数,默认为均值mean,fill_value是以什么值填充空值
res = df.pivot_table(index='',values='',columns='',aggfunc='',fill_value='')

 

posted on 2023-08-28 07:49  fdsimin  阅读(36)  评论(0编辑  收藏  举报