python基础 练习7

第7课练习和作业

练习1

在 Python 下对一个二维列表,l1=[[1,2,3],[4,5,6]],然后进行每个元素+1 的操作。

要求使用

 Python 循环

 Map 函数

 Numpy 计算(广播算法)

方法1:Python循环

l1 = [[1,2,3],[4,5,6]]
for row in range(len(l1)):
    for col in range(len(l1[0])):
        l1[row][col] +=1
print(l1)

结果:[[2, 3, 4], [5, 6, 7]]

方法2:map

l1 = [[1,2,3],[4,5,6]]
l2 = list(map(lambda x:(list(map(lambda y:y+1,x))),l1))
print(l2)

结果:[[2, 3, 4], [5, 6, 7]]

方法3:numpy

import numpy as np
l1 = [[1,2,3],[4,5,6]]
l2 = np.array(l1)
l2 = l2 +1  #直接用numpy 的 广播操作 +1
l3 = list(l2) #转换为 list
for i in range(len(l3)): #内部的每个维度都要转换为list
    l3[i] = list(l3[i])
print(l3)

结果:[[2, 3, 4], [5, 6, 7]]

练习2

矩阵转置:

对 arr= [[1, 2, 3], [4, 5, 6], [7,8, 9], [10, 11, 12]]进行行列互转

 Python 列表表达式

 Numpy 进行转置

方法1:列表表达式

arr= [[1, 2, 3], [4, 5, 6], [7,8, 9], [10, 11, 12]]
[[x[i] for x in arr] for i in range(len(arr[0]))]

结果:[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]

方法2:numpy转置

import numpy as np
arr= [[1, 2, 3], [4, 5, 6], [7,8, 9], [10, 11, 12]]
arr_t1 = np.array(arr).transpose()
arr_t2 = np.array(arr).T
print(arr_t1)
print(arr_t2)

结果:注意,结果是 numpy 的dnarray,没有转换为python的list

[[ 1 4 7 10]

[ 2 5 8 11]

[ 3 6 9 12]]

[[ 1 4 7 10]

[ 2 5 8 11]

[ 3 6 9 12]]

练习3:

矩阵内部运算

 在 Python 下对一个二维列表,l1=[[1,2,3],[4,5,6]],要求求出按行与按列求和。

 在 numpy 下对一个二维列表,l1=[[1,2,3],[4,5,6]],要求求出按行与按列求和。

方法1:Python循环

l1=[[1,2,3],[4,5,6],[1,2,3],[4,5,6]]
l_sum_col =[0 for i in range(len(l1[0]))] #创建一个有相同列数的list
for i in range(len(l1)):
    for j in range(len(l1[0])):
        l_sum_col[j] += l1[i][j]
print("按列求和:",l_sum_col)
l_sum_row =[0 for i in range(len(l1))] #创建一个有相同行数的list
for i in range(len(l1)):
    for j in range(len(l1[0])):
        l_sum_row[i] += l1[i][j]
print("按行求和:",l_sum_row)

结果:

按列求和: [10, 14, 18]

按行求和: [6, 15, 6, 15]

方法2:numpy

import numpy as np
l1=[[1,2,3],[4,5,6],[1,2,3],[4,5,6]]
print(np.sum(l1,axis=0)) #保留列(按列求和)
print(np.sum(l1,axis=1)) #保留行(按行求和)

结果:

[10 14 18]

[ 6 15 6 15]

练习4:

NDArray 创建与属性

 使用 Numpy 创建一个多维数组,请输出以下属性

 该数组的形状

 该数组的维度

 该数组元素的个数

 该数组的数据类型

l1 = np.array((range(1,5),range(6,10),range(11,15))) # 3*4
print(l1.shape) # (3,4)
print(l1.ndim) # 2
print(l1.size) # 12
print(l1.dtype) # np.int32

练习5:

NDArray 的访问

创建一个包含从数字 1 到 60,的数组,并将于其形状变为为(3,2,10)的三维数组,

并按如下要求访问这个三维数组

 访问第 0 维度中第二个元素的所有的信息

 访问第 0 维度中所有元素的全部第 0 个维度(行),和最后一个维度(列)6-7 列

 将该数组降维至二维,形状自行定义

 打乱矩阵内元素的顺序

 按行维度进行排序

 按列维度进行排序

Python 基础升级班

 将降维后的数组进行行列转置

 将转至后的数组展平至一维数组。

import numpy as np
a = np.arange(1,61)
a = a.reshape(3,2,-1)
print(a)

访问第 0 维度中第二个元素的所有的信息

print(a[2])

访问第 0 维度中所有元素的全部第 0 个维度(行),和最后一个维度(列)6-7 列

print(a[:,0,6:8])

将该数组降维至二维,形状自行定义

a.shape = (12,5)

打乱矩阵内元素的顺序

np.random.shuffle(a)
a = a.T
np.random.shuffle(a)
a = a.T
print(a)

按行维度进行排序

a.sort(axis=0)

按列维度进行排序

a.sort(axis=1)

将降维后的数组进行行列转置

a = a.T

将转至后的数组展平至一维数组。

a = a.flatten() #或者 a.ravel()

练习6:

拼接与切分 NDArray 对象

 先建立两个矩阵 arr1=[[1,2,3],[4,5,6]]和 arr2=[[7,8,9],[10,11,12]]

 对两个矩阵进行横向拼接,并输出结果

 对两个矩阵进行纵向拼接,赋值给 arr3 并输出结果

 对 arr3 按列进行分割为 3 个新元素并输出

 对 arr3 按行进行分割为 2 个新元素并输出

 将 arr3 转换为 Python 列表,并指定数据类型为 int

import numpy as np
arr1=[[1,2,3],[4,5,6]]
arr2=[[7,8,9],[10,11,12]]

对两个矩阵进行横向拼接

print(np.hstack((arr1,arr2)))

对两个矩阵进行纵向拼接,赋值给 arr3 并输出结果

arr3 = np.vstack((arr1,arr2))
print(arr3)

对 arr3 按列进行分割为 3 个新元素并输出

l1,l2,l3  = np.hsplit(arr3,3)

对 arr3 按行进行分割为 2 个新元素并输出

l1,l2 = np.vsplit(arr3,2)

将 arr3 转换为 Python 列表,并指定数据类型为 int

arr3 = arr3.astype(np.int32)
l3 = arr3.tolist()

练习7:

数据导入导出

 生成一个随机数矩阵,形状为(3,5)

 将其第 2 行第 4 列的元素修改为 998

 保存至本地文件 random_matrix.txt

 并尝试从这个文件中载入并验证修改是否正确

import numpy as np
l1 = np.random.rand(3,5)*100
l1[2][4]=998
np.savetxt("random_matrix.txt",l1)
l2 = np.loadtxt("random_matrix.txt")

练习8:

使用 numpy 实现 softmax

思路:

 计算指数,并安全处理避免数字过大

 按行求和

 每行均除以计算的和

import numpy as np
L1 = np.random.randn(10,3)*10
print("source input:\n",L1)  #原始输入
max_line = L1.max(axis=1)
max_line = max_line.reshape(10,1) #求每行的最大值
L2 = L1 - max_line  #每个数字减去 每行的最大值
print("subtract max_line:\n",L2)
L3 = np.exp(L2)  #求e的次方
print("exp():\n",L3)
sum_line = L3.sum(axis=1)
sum_line = sum_line.reshape(10,1) #求exp()的每行的和
print("sum_line:\n",sum_line)
res = (L3 / sum_line)
print("result:\n",res)

练习9:

股票相关统计量计算

 读入的给定的 ibm 股价数据中的收盘价及成交量

 计算成交量加权平均价 VWAP(收盘价)

 计算时间加权平均价 TWAP(收盘价)

 找出 IBM 股票收盘价的极差

 计算其收盘价的中位数,均值及方差

 计算股票的收益率(简单收益率与对数收益率)

 计算对数收益收益率大于 1%的天数有多少?

import numpy as np

 读入的给定的 ibm 股价数据中的收盘价及成交量

c,v = np.loadtxt("python-7.ibm.txt",delimiter="\t",usecols=(5,6),unpack=True,skiprows=1)

 计算成交量加权平均价 VWAP(收盘价)

np.average(c,weights=v)  #106.4904345988427

 计算时间加权平均价 TWAP(收盘价)

t = np.arange(len(c),0,-1) #时间越近权重越高,所以反过来
np.average(c,weights=t) #123.481860285

 找出 IBM 股票收盘价的极差

max(c) - min(c) #205.0

 计算其收盘价的中位数,均值及方差

np.median(c) #中位数 102.2
np.mean(c) #均值 110.63084231682807
np.var(c) #方差 1539.72768752

 计算股票的收益率(简单收益率与对数收益率)

c1 = c[::-1] #将时间越近的放在后面
dif1 = np.diff(c1) / c1[0:-1] #变化值 / 变化前的值,结果应该是百分比
dif1_where = np.where(dif1>0) #得到正收益的下标
dif2 = np.diff(np.log(c1)) #对数收益率
dif2[dif2*100>10]
np.where(dif2*100>10)

 计算对数收益收益率大于 1%的天数有多少?

dif2[dif2*100>1].size #1227

计算周1到周5的平均价,并找出最大和最小值

import numpy as np
from datetime import *
z,c=np.loadtxt("python-7.ibm.txt",delimiter="\t",usecols=(1,5),skiprows=1,unpack=True,dtype={'names':('Date','Close'),'formats':('S10','f8')})
bb = [str(z[i].decode()).split("/") for i in range(len(z))]
wk = list(map(lambda x:date(int(x[0]),int(x[1]),int(x[2])).weekday() ,bb))
wk1 = np.array(wk)
wk_mean = np.zeros(5)
for i in range(5):
    a_tf = wk1==i
    wk_mean[i] = c[a_tf].mean()
print("周1到周5的平均价:\n",wk_mean) #[ 110.55213178  110.66381462  110.70765806  110.72665458  110.49569991]
print("最高平均: 周",wk_mean.argmax()+1,"价格为:",wk_mean.max()) #最高平均: 周 4 价格为: 110.726654578
print("最低平均: 周",wk_mean.argmin()+1,"价格为:",wk_mean.min()) #最低平均: 周 5 价格为: 110.495699909

按周对股票价格进行汇总:

在上一题的基础上选取有连续交易的三周时间(共计 15 天)后,按周进行汇总要求得出每周的开,高,低,收。

Stock Date Open High Low Close Volume

IBM 2013/8/30 182.8 183.0 181.5 182.3 2731000

IBM 2013/8/29 182.0 183.7 181.4 182.6 2980900

IBM 2013/8/28 182.7 183.5 181.1 182.2 3979200

IBM 2013/8/27 183.6 184.5 182.6 182.7 3190700

IBM 2013/8/26 185.3 187.0 184.7 184.7 2170400

IBM 2013/8/23 185.3 185.7 184.6 185.4 2292700

IBM 2013/8/22 185.6 186.3 184.3 185.2 2354300

IBM 2013/8/21 184.7 186.6 184.3 184.9 3551000

IBM 2013/8/20 184.4 185.6 183.2 184.6 3117800

IBM 2013/8/19 185.3 186.5 184.0 184.2 3248900

IBM 2013/8/16 185.5 186.5 185.3 185.3 3426400

IBM 2013/8/15 186.2 187.0 185.4 185.8 3692400

IBM 2013/8/14 188.6 188.9 187.3 187.5 2892300

IBM 2013/8/13 189.5 190.0 187.6 188.4 3542900

IBM 2013/8/12 187.0 189.6 186.9 189.1 3026500

import numpy as np
from datetime import *
def day_to_str(s): #decode转换 bytes为str
    return str(s.decode()) #其实啥也没做!
def day_in_week(s): #计算是周几
    return datetime.strptime(s[0].decode(),"%Y/%m/%d").weekday()
def year_week(s): #计算是哪年第几周,作为唯一的周标识 年*100+本年第几周
    date1 = datetime.strptime(s[0].decode(),"%Y/%m/%d")
    #print(date1)
    return 100*date1.year + date1.isocalendar()[1]

d,o,h,l,c = np.loadtxt("python-7.ibm-15.txt",unpack=True,skiprows=1,usecols=(1,2,3,4,5),delimiter="\t",
                       converters={1:day_to_str},
                       dtype={"names":("d","o","h","l","c"),"formats":("S10","f8","f8","f8","f8")})

d是原始的日期字符串,构建 d_w,d_id,分别表示星期几 和 周ID

d_c = d.reshape(len(d),1)  #d_c是 n * 1的列向量

d_w = np.apply_along_axis(day_in_week,1,d_c)
d_w.shape = (-1,1) #转为列向量

d_id = np.apply_along_axis(year_week,1,d_c)
d_id.shape = (-1,1) #转为列向量

week_split = np.arange(15) #构建 按周切分的 下标数组
week_split = np.array(np.split(week_split,3))

def week_data(week_split,d_id,o,h,l,c):
    o1 = np.take(o,week_split)[-1]
    c1 = np.take(c,week_split)[0]
    h1 = np.max(np.take(h,week_split))
    l1 = np.min(np.take(l,week_split))
    did = np.take(d_id,week_split)[0]
    return (did,o1,h1,l1,c1)

a = np.apply_along_axis(week_data,1,week_split,d_id,o,h,l,c)
print(a.tolist())

结果:

[[201335.0, 185.3, 187.0, 181.1, 182.3],

[201334.0, 185.3, 186.6, 183.2, 185.4],

[201333.0, 187.0, 190.0, 185.3, 185.3]]

方法2:

尝试自己写个循环遍历(这样就不需要一周必须5条数据了)

import numpy as np
from datetime import datetime
def week(s): #计算是(周几,周ID)
    date1 = datetime.strptime(s.decode(),"%Y/%m/%d")
    return [100*date1.year + date1.isocalendar()[1],date1.weekday()]

d,o,h,l,c = np.loadtxt("python-7.ibm.txt",delimiter="\t",usecols=(1,2,3,4,5),skiprows=1,unpack=True,
                      dtype={"names":("d","o","h","l","c"),"formats":("S10","f8","f8","f8","f8")})
d=d.tolist()
dd = np.array(list(map(week,d))) #周ID,周几 的list
d_all = np.hstack((dd,o.reshape(-1,1),h.reshape(-1,1),l.reshape(-1,1),c.reshape(-1,1)))
ww = []
ww1 = []
last_week = 0
i=0
for item in d_all:
    if item[0]!=last_week: #周ID发生变化了
        if last_week!=0:
            #保存上次的数据
            ww1 = np.array(ww1)
            wid = int(ww1[0][0])
            o1 = ww1[-1][2]
            h1 = np.max(ww1[:,3])
            l1 = np.min(ww1[:,4])
            c1 = ww1[0][5]
            ww.append([wid,o1,h1,l1,c1])
            ww1 = []
            pass
        last_week = item[0]
        #存放新的数据到 ww1
        ww1.append(item)
    else:#继续存放ww1
        ww1.append(item)

print(np.array(ww))
已邀请:

ClownFish

赞同来自:


np.random.shuffle(a)
a = a.T
np.random.shuffle(a)
a = a.T

这里是粘多了,还是代码就是这样?

softmax这题你是以输入数字做为源数据的。。不错。
另外 ,试试,多行ndarray,然后对每一行进行求softmax.

t = np.arange(len(c),0,-1) #时间越近权重越高,所以反过来
np.average(c,weights=t) #123.481860285

你选择的是按长度,是一个办法,其它的办法也可以是按指数或其它方法,目的是让最近的日子的权重显著高于之前的日子。

np里的diff也用到了,棒~

最后一题第二种思路很好,对日期的处理更灵活。不受apply_along_axis的拘束了。棒~

从作业中能看出,已经对numpy ndarray对象的运用很到位了。
坚持练习,过渡到熟练的境界~

要回复问题请先登录注册

返回顶部