二、ndarray的属性
4个必记参数:
ndim:维度
shape:形状(各维度的长度)
size:总长度
dtype:元素类型
import matplotlib.pyplot as plt
ndarr = plt.imread("./jin.png")
plt.imshow(ndarr)
# 接下来展示的是几个属性
ndarr.ndim # 多少个维度
ndarr.shape # 形状 273 411 3
ndarr.size # 总共有多少个元素 273*411*3
ndarr.dtype
三、ndarray的基本操作
1. 索引
基本索引:一维与列表完全一致 多维时同理
ndarr = np.random.randint(0,10,size=(4,5))
# 二维数组 数组中有4个元素(数组) 这4个数组中分别有 5个元素
ndarr
结果为:
array([[2, 4, 1, 8, 1],
[5, 1, 6, 8, 5],
[0, 2, 1, 6, 6],
[2, 3, 9, 0, 5]])
ndarr[0] #按照索引就可以把元素取出 array([2, 4, 1, 8, 1])
ndarr[1] array([5, 1, 6, 8, 5])
ndarr[1][3] 8
ndarr[1][-2] 8
高级索引:整数数组形式的索引
ndarr = np.random.randint(0,10,size=(4,5)) # 二维数组 数组中有4个元素(数组) 这4个数组中分别有 5个元素
ndarr
结果为:
array([[8, 5, 5, 6, 4],
[0, 1, 7, 6, 8],
[7, 4, 2, 9, 1],
[9, 4, 6, 2, 4]])
ndarr[0][0] 8
ndarr[0,0] # 多维数组还支持 整数数组的形式 作为索引 8
ndarr[2,3] 9
ndarr[2,-2] 9
list1 = [[0, 8, 2, 9, 3],
[9, 2, 3, 0, 1],
[9, 1, 0, 6, 7],
[2, 7, 6, 5, 4]]
list1[0][0]
list1[0,0] # 注意整数数组索引是 ndarray特有的索引方式 list没有
结果显示:TypeError: list indices must be integers or slices, not tuple
练习:使用数组索引寻找指定位置的值
nd = np.random.randint(0,10,size=(2,4,3,7))
nd
结果为:
array([[[[8, 5, 6, 9, 6, 9, 6],
[6, 4, 1, 3, 4, 1, 7],
[1, 9, 9, 0, 3, 2, 6]],
[[6, 3, 8, 7, 1, 8, 8],
[1, 9, 5, 4, 0, 2, 9],
[4, 7, 0, 2, 9, 9, 1]],
[[1, 5, 8, 4, 0, 1, 4],
[6, 1, 7, 4, 5, 8, 9],
[6, 2, 2, 1, 0, 6, 5]],
[[2, 3, 5, 0, 4, 9, 0],
[6, 1, 6, 5, 1, 5, 8],
[7, 2, 9, 0, 3, 0, 5]]],
[[[9, 1, 7, 9, 5, 2, 3],
[6, 2, 7, 2, 7, 1, 9],
[6, 8, 6, 6, 4, 3, 9]],
[[1, 9, 7, 6, 0, 7, 8],
[2, 3, 9, 7, 7, 2, 2],
[9, 7, 7, 7, 0, 4, 3]],
[[7, 6, 2, 2, 4, 5, 4],
[5, 9, 3, 6, 3, 6, 4],
[1, 6, 1, 9, 0, 0, 4]],
[[1, 7, 2, 3, 4, 1, 6],
[0, 5, 3, 8, 3, 0, 3],
[9, 9, 8, 5, 7, 9, 4]]]])
nd[0,0,0,4] 6
nd[0,0,0,-3] 6
nd[0,0,2,0] 1
nd[0,2,1,-3] 5
- 切片
一维与列表切片完全一致 多维时同理
nd = np.random.randint(0,10,size=(5,4))
nd
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8]])
nd[0:3] # start:end [start:end)
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4]])
nd[:3] # 如果从0开始 0可以省略 与上面结果保持一致
nd[1:] # 如果取到最后 后面的值可以省略
array([[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8]])
nd[1:3] # 从第0行取到弟2行
结果为:
array([[1, 1, 5, 8],
[6, 9, 5, 4]])
nd[1:3,0:2] # 从外往里 层层切片 从第0行取到弟2行且列数为第0列取到第一列
结果为:
array([[1, 1],
[6, 9]])
nd[0:4:2,0:4:2]
结果为:
array([[3, 6],
[6, 5]])
nd[::2,::2] #每行每列挑一行或一列取
结果为:
array([[3, 6],
[6, 5],
[4, 2]])
nd[::-1] #把外围元素即每行的顺序颠倒
结果为:
array([[4, 1, 2, 8],
[6, 7, 9, 5],
[6, 9, 5, 4],
[1, 1, 5, 8],
[3, 9, 6, 6]])
nd[:,::-1] #把里围元素即每列的顺序颠倒
结果为:
array([[6, 6, 9, 3],
[8, 5, 1, 1],
[4, 5, 9, 6],
[5, 9, 7, 6],
[8, 2, 1, 4]])
练习:取项尚人头
jin = plt.imread("./123.jpg")
plt.imshow(jin)
jin.shape
plt.imshow(jin[25:150,175:260])
结果为:
两个:: 的形式 进行切片和翻转
nd
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8]])
nd[::2] #start:end:step #每行隔一行取
结果为:
array([[3, 9, 6, 6],
[6, 9, 5, 4],
[4, 1, 2, 8]])
nd[1:4:2] #从第0行取到第三行 且每行隔一行取
结果为:
array([[1, 1, 5, 8],
[6, 7, 9, 5]])
nd[::2,::2] #每行每列隔一行取
结果为:
array([[3, 6],
[6, 5],
[4, 2]])
nd[:,::-2] #每列从右向左隔一行取
结果为:
array([[6, 9],
[8, 1],
[4, 9],
[5, 7],
[8, 1]])
练习: 图片的上下颠倒 左右颠倒 变瘦 色值的交换
jin = plt.imread("./jin.png")
plt.imshow(jin)
jin.shape
plt.imshow(jin[::-1]) # 翻转了最外围 上下颠倒
plt.imshow(jin[:,::-1]) # 左右颠倒
plt.imshow(jin[::-1,::-1]) # 旋转180度
plt.imshow(jin[:,::3]) # 变瘦
# 红 绿 蓝 # 蓝 绿 红
plt.imshow(jin[:,:,::-1]) # 蓝精灵
# 红 绿 蓝
plt.imshow(jin[:,:,[1,0,2]]) # 绿巨人
3. 变形
使用reshape函数,注意参数是一个tuple!
np
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8]])
nd.shape 结果为:(5, 4)
nd.reshape((4,5)) # 改变形状 注意参数是一个元组
nd.reshape((2,10)) # 不止可以颠倒行列 只要元素总是一样 都可以变形
nd.reshape((2,8)) # 总数一样可以变形 总数不一样就会报错了
4. 连结
- np.concatenate() 连结需要注意的点:
- 连结的参数是列表:一定要加小括号
- 维度必须相同
- 形状相符
- 连结的方向默认是shape这个tuple的第一个值所代表的维度方向
- 可通过axis参数改变连结的方向
nd
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8]])
nd2 = np.random.randint(0,10,size=(2,4))
nd2
结果为:
array([[1, 7, 6, 6],
[0, 6, 4, 8]])
np.concatenate((nd,nd2))
结果为:
array([[3, 9, 6, 6],
[1, 1, 5, 8],
[6, 9, 5, 4],
[6, 7, 9, 5],
[4, 1, 2, 8],
[1, 7, 6, 6],
[0, 6, 4, 8]])
np.concatenate((nd,nd2),axis=1) # 形状要相符
5. 切分
与级联类似,三个函数完成切分工作:
- np.split
- np.vsplit
- np.hsplit
ndarr = np.random.randint(0,10,size=(4,4))
ndarr
结果为:
array([[4, 2, 0, 6],
[4, 0, 4, 4],
[0, 0, 3, 4],
[4, 2, 9, 6]]
# 参数 1.要切分的数组 2.要分成几份 3切分时候的轴
np.split(ndarr,2) # axis默认是0
结果为:
array([[4, 2, 0, 6],
[4, 0, 4, 4]]),
array([[0, 0, 3, 4],
[4, 2, 9, 6]])]
np.split(ndarr,2,axis=1)
结果为:
[array([[4, 2],
[4, 0],
[0, 0],
[4, 2]]), array([[0, 6],
[4, 4],
[3, 4],
[9, 6]])]
np.vsplit(ndarr,2) # v vertical 垂直 对垂直方向的元素进行切割(切割的时候是水平去切的)
结果为:
[array([[4, 2, 0, 6],
[4, 0, 4, 4]]), array([[0, 0, 3, 4],
[4, 2, 9, 6]])]
np.hsplit(ndarr,2) # h horizon 水平 对水平方向上的元素进行切割(切的时候垂直切)
结果为:
[array([[4, 2],
[4, 0],
[0, 0],
[4, 2]]), array([[0, 6],
[4, 4],
[3, 4],
[9, 6]])]
ndarr
结果为:
array([[4, 2, 0, 6],
[4, 0, 4, 4],
[0, 0, 3, 4],
[4, 2, 9, 6]])
np.split(ndarr,[1,3])
结果为:
[array([[4, 2, 0, 6]]), array([[4, 0, 4, 4],
[0, 0, 3, 4]]), array([[4, 2, 9, 6]])]
6. 副本
所有赋值运算不会为ndarray的任何元素创建副本。对赋值后的对象的操作也对原来的对象生效。
ndarr
结果为:
array([[4, 2, 0, 6],
[4, 0, 4, 4],
[0, 0, 3, 4],
[4, 2, 9, 6]])
ndarr1 = ndarr
print(id(ndarr),id(ndarr1))
结果为:
134475984 134475984
可使用copy()函数创建副本
ndarr2 = ndarr.copy() #多维数组调用自身的copy()方法 就会返回一个一模一样 但是完全独立的数组
print(id(ndarr),id(ndarr2))
134475984 130613536
四、ndarray的聚合操作
1. 求和np.sum
2. 最大最小值:np.max/ np.min
3. 其他聚合操作
Function Name NaN-safe Version Description
np.sum np.nansum Compute sum of elements 所有元素的和
np.prod np.nanprod Compute product of elements 所有元素的乘积
np.mean np.nanmean Compute mean of elements
np.std np.nanstd Compute standard deviation
np.min np.nanmin Find minimum value
np.max np.nanmax Find maximum value
np.argmin np.nanargmin Find index of minimum value
np.argmax np.nanargmax Find index of maximum value
np.median np.nanmedian Compute median of elements
np.power 幂运算
np.any N/A Evaluate whether any elements are true
np.all N/A Evaluate whether all elements are true
ndarr
结果为:
array([[6, 4, 2, 2],
[1, 8, 2, 7],
[0, 9, 3, 9],
[7, 0, 4, 0]])
np.sum(ndarr) 64
np.any(ndarr) # any 只要元素中有True就是True 0是False 其他都是True
结果为:True
np.all(ndarr) # all 必须所有元素都是True才是True 0是False 其他都是True
结果为:
False
ndarr = np.random.randint(0,10,size=(4,6))
ndarr
结果为:
array([[3, 6, 1, 0, 1, 4],
[2, 0, 3, 1, 5, 1],
[2, 5, 4, 6, 4, 0],
[6, 1, 3, 6, 2, 9]])
np.any(ndarr,axis=1)
array([False, False, False, True])
np.any(ndarr,axis=-1)
array([False, False, False, True]
np.any(ndarr,axis=0) #只要有true就是True
结果为:
array([ True, True, True, True, True, True])
# any和all将来可以用来做数据过滤
ndarr
结果为:
array([[9, 6, 8, 5, 8, 9],
[6, 0, 0, 4, 1, 3],
[1, 8, 9, 0, 3, 2],
[4, 0, 2, 3, 9, 1]])
# 按照条件到多维数组中寻找
np.argwhere(ndarr == 0) # 返回要找的值的位置
结果为:
array([[1, 1],
[1, 2],
[2, 3],
[3, 1]], dtype=int64)
np.argwhere(ndarr > 8)
结果为:
array([[0, 0],
[0, 5],
[2, 2],
[3, 4]], dtype=int64)
np.sum 和 np.nansum 的区别 nan not a number
ndarr2 = np.array([1,2,3,np.NAN])
ndarr2
结果为:
array([ 1., 2., 3., 4., 5., nan])
np.sum(ndarr2) # 运算中 只要遇到nan结果就是nan 结果为:nan
# 如果不希望是nan
np.nansum(ndarr2) # 把nan当作0来参与运算 结果为:15.0
array([ 1., 2., 3., nan])
操作文件
使用pandas打开文件president_heights.csv 获取文件中的数据
import pandas as pd
data = pd.read_csv("./president_heights.csv")
data
type(data) pandas.core.frame.DataFrame
type(data.values) numpy.ndarranumpy.ndarray
五、ndarray的矩阵操作
1. 基本矩阵操作
- 算术运算符:
- 加减乘除
import numpy as np
ndarr = np.random.randint(0,10,size=(4,5))
ndarr
结果为:
array([[4, 7, 6, 2, 3],
[6, 5, 2, 0, 4],
[0, 7, 8, 9, 4],
[4, 2, 7, 8, 5]])
# 矩阵和数值的运算
ndarr + 1 # 矩阵和数值做加法 给矩阵中所有的值都加上这个数 广播机制
ndarr - 1 # 矩阵中每一个值都减这个数值
ndarr * 2 # 每个值都乘以这个数值
ndarr / 2 #
- 矩阵积np.dot()
点积 是 第一个的行和第二个的列做运算,第二个矩阵的行数必须等于第一个矩阵的列数 这样 前后两组数字才能对应上
ndarr
结果为:
array([[4, 7, 6, 2, 3],
[6, 5, 2, 0, 4],
[0, 7, 8, 9, 4],
[4, 2, 7, 8, 5]])
ndarr.shape (4, 5)
ndarr2 = np.random.randint(0,10,size=(5,3)) # 必须是5行
ndarr2.shape (5, 3)
ndarr2
结果为:
array([[0, 4, 8],
[7, 1, 7],
[0, 7, 7],
[0, 1, 7],
[8, 7, 5]]
np.dot(ndarr,ndarr2)
结果为:
array([[108, 140, 65],
[ 94, 105, 60],
[125, 173, 92],
[107, 161, 83]])
2. 广播机制
【重要】ndarray广播机制的两条规则
- 规则一:为缺失的维度补1
- 规则二:假定缺失元素用已有值填充
例1: m = np.ones((2, 3)) a = np.arange(1,4,1) 求m+a
m = np.ones((2, 3))
m
结果为:
array([[1., 1., 1.],
[1., 1., 1.]])
a = np.arange(1,4,1)
a
结果为:array([1, 2, 3])
a+m
结果为:
array([[2., 3., 4.],
[2., 3., 4.]])
例2: a = np.arange(3).reshape((3, 1)) b = np.arange(3) 求a+b
a = np.arange(3).reshape((3, 1))
a
结果为:
array([[0],
[1],
[2]])
b = np.arange(3)
b
结果为:
array([0, 1, 2])
a + b
结果为:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
习题 a = np.ones((4, 1)) b = np.arange(4) 求a+b
六、ndarray的排序
小测验: 使用以上所学numpy的知识,对一个ndarray对象进行选择排序。
def Sortn(x):
代码越短越好
1. 快速排序
np.sort()与ndarray.sort()都可以,但有区别:
- np.sort()不改变输入
- ndarray.sort()本地处理,不占用空间,但改变输入
nadrr
结果为:
array([[4, 7, 6, 2, 3],
[6, 5, 2, 0, 4],
[0, 7, 8, 9, 4],
[4, 2, 7, 8, 5]])
np.sort(ndarr) # 传入一个数组 np.sort会返回一个新数组 这个新数组是从小到大排序的数组 (原数组不变)
结果为:
array([[2, 3, 4, 6, 7],
[0, 2, 4, 5, 6],
[0, 4, 7, 8, 9],
[2, 4, 5, 7, 8]])
aandarr.sort() # 多维数组调用自身的sort 会把自己按照从小到大的顺序排改变自身数组
ndarr
结果为:
array([[2, 3, 4, 6, 7],
[0, 2, 4, 5, 6],
[0, 4, 7, 8, 9],
[2, 4, 5, 7, 8]])
2. 部分排序
np.partition(a,k)
有的时候我们不是对全部数据感兴趣,我们可能只对最小或最大的一部分感兴趣。
- 当k为正时,我们想要得到最小的k个数
- 当k为负时,我们想要得到最大的k个数
ndarr3 = np.random.randint(0,100,size=15)
ndarr3
结果为:
array([49, 64, 5, 28, 50, 90, 20, 26, 98, 13, 65, 0, 54, 99, 43])
np.partition(ndarr3,1)
结果为:array([ 0, 5, 64, 28, 50, 90, 20, 26, 98, 13, 65, 49, 54, 99, 43])
np.partition(ndarr3,2)
结果为:array([ 0, 5, 13, 28, 50, 90, 20, 26, 98, 64, 65, 49, 54, 99, 43])
np.partition(ndarr3,3)
结果为:array([ 0, 5, 13, 20, 26, 28, 43, 64, 98, 90, 65, 50, 54, 99, 49])
np.partition(ndarr3,4)
结果为:array([ 0, 5, 13, 20, 26, 28, 43, 64, 98, 90, 65, 50, 54, 99, 49])
np.partition(ndarr3,-5) #最大的5个放后面
结果为:array([20, 26, 5, 28, 0, 13, 43, 50, 49, 54, 64, 98, 90, 99, 65])
Pandas的数据结构
导入pandas:
数据分析三剑客 numpy pandas matplotlib
import pandas as pd
from pandas import Series,DataFrame
import numpy
import matplotlib.pyplot as plt
1、Series
Series是一种类似于一维数组的对象,由下面两个部分组成:
- index:相关的数据索引标签
- values:一组数据(ndarray类型)
1)Series的创建
两种创建方式:
(1) 由列表或numpy数组创建
默认索引为0到N-1的整数型索引
s1 = Series([1,2,3,4])
s1
结果为:
0 1
1 2
2 3
3 4
dtype: int64
s1.index # 索引 结果为:RangeIndex(start=0, stop=4, step=1)
s1.values # 值 值是多维数 结果为:array([1, 2, 3, 4], dtype=int64)
还可以通过设置index参数指定索引
s2 = Series([1,2,3],index=("a","b","c")) # 通过index可以指定索引 注意:索引的个数和值的个数要对应
结果为:
a 1
b 2
c 3
dtype: int64
(2) 由字典创建
s3 = Series({"A":10,"B":20,"C":30})
s3
结果为:
A 10
B 20
C 30
dtype: int64
============================================
练习1:
使用多种方法创 建以下Series,命名为s1:
语文 150
数学 150
英语 150
理综 300
============================================
s1 = Series([150,150,150,300],index=("语文","数学","英语","理综"))
s1
结果为:
语文 150
数学 150
英语 150
理综 300
dtype: int64
2)Series的索引和切片
可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:
(1) 显式索引:
- 使用index中的元素作为索引值
- 使用.loc[](推荐)
注意,此时是闭区间
s2
结果为:
a 1
b 2
c 3
dtype: int64
s2["a"] 结果为:1
s2.loc["a"] # loc location 定位 根据传入的索引去定位值
结果为:1
s2.loc[["a","c"]] #用于定位的中括号里面 传入的是一个值或者是列表
结果为:
a 1
c 3
dtype: int64
(2) 隐式索引:
- 使用整数作为索引值
- 使用.iloc[](推荐)
注意,此时是半开区间
s2[0] 结果为:1
s2.iloc[0] # iloc index location 通过索引号去定位元素
结果为:1
根据索引对Series进行切片
============================================
练习2:
使用多种方法对练习1创建的Series s1进行索引和切片:
索引: 数学 150
切片: 语文 150 数学 150 英语 150
============================================
s1
结果为:
语文 150
数学 150
英语 150
理综 300
dtype: int64
s1.loc["语文":"英语"]
结果为:
语文 150
数学 150
英语 150
dtype: int64
s1["语文":"英语"]
结果为:
语文 150
数学 150
英语 150
dtype: int64
s1[0:3]
结果为:
语文 150
数学 150
英语 150
dtype: int64
s1["数学"]
s1[1]
s1.loc["数学"]
s1.iloc[1]
以上四种方法都是对数学分数的索引 结果为:150
3)Series的常用属性和方法
可以把Series看成一个定长的有序字典
可以通过shape,size,index,values等得到series的属性
s1
结果为:
数学 150
英语 150
理综 300
dtype: int64
s1.shape 结果为:(4,)
s1.size 结果为:4
s1.index
结果为:
Index(['语文', '数学', '英语', '理综'], dtype='object')
s1.values
结果为:array([150, 150, 150, 300], dtype=int64)
可以通过head(),tail()快速查看Series对象的样式
s.head(2)看头两个 s.tail(1)看后一个
s1.head(2)
结果为:
语文 150
数学 150
dtype: int64
s1.tail(3)
结果为:
数学 150
英语 150
理综 300
dtype: int64
当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
s2 = Series([1,3,5,7,-2,-4,None,np.nan],index=("a","b","c","d","e","f","g","h"))
s2
结果为:
a 1.0
b 3.0
c 5.0
d 7.0
e -2.0
f -4.0
g NaN
h NaN
dtype: float64
ndarr1 = np.array([1,3,5,7,-2,-4,None,np.nan])
ndarr1
array([1, 3, 5, 7, -2, -4, None, nan], dtype=object)
# ndarr1.sum() # 多维数组中 如果有None nan 就没法求和
结果为:
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
s2.sum() # Series的sum遇到nan可以当做0 然后求和
结果为:10.0
可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据
s2
结果为:
a 1.0
b 3.0
c 5.0
d 7.0
e -2.0
f -4.0
g NaN
h NaN
dtype: float64
s2.isnull() # 是nan则返回True
结果为:
a False
b False
c False
d False
e False
f False
g True
h True
dtype: bool
s2.notnull() # 不是nan返回True
结果为:
a True
b True
c True
d True
e True
f True
g False
h False
dtype: bool
condition = s2.isnull()
s2[condition] = -100
结果为:
a 1.0
b 3.0
c 5.0
d 7.0
e -2.0
f -4.0
g -100.0
h -100.0
dtype: float64
Series对象本身及其实例都有一个name属性
s3 = Series([1,2,3,4,5],index=("a","b","c","d","e"),name="张三")
s3
结果为:
a 1
b 2
c 3
d 4
e 5
Name: 张三, dtype: int64
s4 = Series([1,2,3,4,5],index=("a","b","c","d","e"),name="李四")
s4
结果为:
a 1
b 2
c 3
d 4
e 5
Name: 李四, dtype: int64
4)Series的运算
(1) 适用于numpy的数组运算也适用于Series
s4 + 50
结果为:
a 51
b 52
c 53
d 54
e 55
Name: 李四, dtype: int64
s4 * 2
结果为:
a 2
b 4
c 6
d 8
e 10
Name: 李四, dtype: int64
(2) Series之间的运算
- 在运算中自动对齐不同索引的数据
- 如果索引不对应,则补NaN
- 注意:要想保留所有的index,则需要使用.add()函数
s3 + s4 # 索引对应的项目的值会相加
结果为:
a 2
b 4
c 6
d 8
e 10
dtype: int64
s1 + s3 # 两个Series进行加和时,如果索引不对应,返回值 nan
结果为:
a NaN
b NaN
c NaN
d NaN
e NaN
数学 NaN
理综 NaN
英语 NaN
语文 NaN
dtype: float64
索引不对应 就出NaN 如果不喜欢这样可以调用 series自身的add()方法
s1.add(s3)
结果为:
a NaN
b NaN
c NaN
d NaN
e NaN
数学 NaN
理综 NaN
英语 NaN
语文 NaN
dtype: float64
s1.add(s3,fill_value=0)
结果为:
a 1.0
b 2.0
c 3.0
d 4.0
e 5.0
数学 150.0
理综 300.0
英语 150.0
语文 150.0
dtype: float64
练习3:
-
想一想Series运算和ndarray运算的规则有什么不同?
前者索引不匹配时仍可可以运算,只是会显示nan,后者结构不同时无法运算
-
新建另一个索引包含“文综”的Series s2,并与s2进行多种算术操作。思考如何保存所有数据。