数值运算
# 概述
数值运算主要包括:
- Series 和 Series 之间的运算
- DataFrame 和 DataFrame 之间的运算
- Series 和 DataFrame 之间的运算
DataFrame 和 Series 之间的算术运算会将 Series 的索引匹配到 DataFrame 的列,然后沿着行一直向下广播。
如果某个索引值在 DataFrame 的列或 Series 的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集。
如果你希望匹配行且在列上广播,则必须使用算术运算方法。
import numpy as np
import pandas as pd
1
2
2
# 逐元素二元运算
记住:
- 此类运算都是默认以label 对齐的;
- 可以认为相加的两个操作数都是先将 index 和 columns 拓展至相同后,再执行运算。
df1 = pd.DataFrame([[1,2],[3,4]], index =['a','b'],columns = ['A','B'])
df1
1
2
2
A | B | |
---|---|---|
a | 1 | 2 |
b | 3 | 4 |
df2 = pd.DataFrame([[3,4],[5,6]], index =['b','c'],columns = ['B','C'])
df2
1
2
2
B | C | |
---|---|---|
b | 3 | 4 |
c | 5 | 6 |
# +
df1 + df2 # df1的'B','b'和df2的'B','b'对上了,其他位置都至少有一个缺失值,此时填NaN
1
A | B | C | |
---|---|---|---|
a | NaN | NaN | NaN |
b | NaN | 7.0 | NaN |
c | NaN | NaN | NaN |
s1 = pd.Series([1,2], index =['A','B'], name = 'A')
s1
1
2
2
A 1
B 2
Name: A, dtype: int64
df1 + s1 # +号默认将Series的index与DataFrame的columns对齐,然后以DataFrame的index为index,纵向复制构造一个DataFrame。
# 也即s1被转化成了:
# A B
#a 1 2
#b 1 2
1
2
3
4
5
2
3
4
5
A | B | |
---|---|---|
a | 2 | 4 |
b | 4 | 6 |
# .add()
add 比+号功能更强,区别提体现在可以控制 Series 构造的方式。
DataFrame.add(other, axis='columns', fill_value=None)
- other:另一个 DataFrame 或 Series;
- axis:如果 other 是 Series,指定 Series 的索引去和 DataFrame 的行匹配,还是和列匹配(+号是默认和列匹配);
- fill_value:这个参数是指两个 DataFrame 只有一个值缺失的情况,缺失的值怎么处理。两者都缺失,那么就是 NaN。
df1.add(s1, axis = 'columns') # 和+号功能相同
1
A | B | |
---|---|---|
a | 2 | 4 |
b | 4 | 6 |
s2 = pd.Series([1,2], index =['a','B'])
s2
1
2
2
a 1
B 2
dtype: int64
df1.add(s2, axis = 'index')
# s1被转化为:以DataFrame的columns为columns,横向复制
# A B
#A 1 1
#B 2 2
1
2
3
4
5
2
3
4
5
A | B | |
---|---|---|
B | NaN | NaN |
a | 2.0 | 3.0 |
b | NaN | NaN |
# 其它运算和加法运算类似
运算方式 | 运算符 | 函数 |
---|---|---|
减法 | - | sub() |
乘法 | x | mul() |
除法 | / | div() |
模运算 | % | mod() |
幂运算 | ** | pow() |
# 矩阵运算
pandas 是以 numpy 这个数值代数库为基础的,所以其也支持矩阵操作,虽然它并以此为目的。
# .dot()
DataFrame.dot(other)
- other:DataFrame 或 Series
注意,pandas 在做矩阵运算时,**要求:**矩阵的维度相同,左操作数的列索引和右操作数的行索引相同。
df1
1
A | B | |
---|---|---|
a | 1 | 2 |
b | 3 | 4 |
df2
1
B | C | |
---|---|---|
b | 3 | 4 |
c | 5 | 6 |
# df1.dot(df2)#报错
df2.index = ['A','B']
df2
1
2
3
2
3
B | C | |
---|---|---|
A | 3 | 4 |
B | 5 | 6 |
df1.dot(df2) # 左操作数的行索引和右操作数的列索引变为内积后元素的行、列索引
1
B | C | |
---|---|---|
a | 13 | 16 |
b | 29 | 36 |
s1
1
A 1
B 2
Name: A, dtype: int64
df1.dot(s1)
1
a 5
b 11
dtype: int64
# .T
矩阵的转置。
df1.T
1
a | b | |
---|---|---|
A | 1 | 3 |
B | 2 | 4 |
# 本地一元变换
这些运算不改变索引,只是在当前位置做一些变化。
# .abs()
转化为绝对值。
df1.loc['a','A'] = -1
df1
1
2
2
A | B | |
---|---|---|
a | -1 | 2 |
b | 3 | 4 |
df1.abs()
1
A | B | |
---|---|---|
a | 1 | 2 |
b | 3 | 4 |
# .cumxxx()
累计运算,从开始到当前数据结束获取一个值。
DataFrame.cumxxx(axis='index')
- axis:'index'或'columns'
xxx 可取:max, min, sum, prod
df1.cummax() # 默认为沿index,列
1
A | B | |
---|---|---|
a | -1 | 2 |
b | 3 | 4 |
df1.cummax(axis = 'columns') # columns意思,行
1
A | B | |
---|---|---|
a | -1 | 2 |
b | 3 | 4 |
# .clip()
顾名思义,裁剪也即将数据裁剪到一定范围内。
DataFrame.clip(lower=None, upper=None)
- lower:float
- upper:float
df1 = pd.DataFrame([[-1,1],[-2,3]])
df1
1
2
2
0 | 1 | |
---|---|---|
0 | -1 | 1 |
1 | -2 | 3 |
df1.clip( -0.5,0.5)
1
0 | 1 | |
---|---|---|
0 | -0.5 | 0.5 |
1 | -0.5 | 0.5 |
# .rank()
顾名思义,rank 次序的意思,也即标示出数值的次序
DataFrame.rank(axis=0, method='average', ascending=True, pct=False)
- axis:0('index')-按列方向,1('columns')-按行方向
- method:对于值相同的数怎么标记顺序,
- 'first':所有数按照大小排序,如相同按照出现顺序赋次序。
- 'dense':值相同为一组,按照组值排序,组内取相同次序,和 min 不同—min 是将相同数用第一
- ascending:True or False,升序还是降序;
- pct:percent,按照百分比显示,将显示的次序除以列、或行元素个数。
df1 = pd.DataFrame(data = [[1,1,2,2],[2,3,2,4]])
df1
1
2
2
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1 | 1 | 2 | 2 |
1 | 2 | 3 | 2 | 4 |
df1.rank(axis='columns', method='min', pct=False) # 注意和下面 dense 对比
1
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1.0 | 1.0 | 3.0 | 3.0 |
1 | 1.0 | 3.0 | 1.0 | 4.0 |
df1.rank(axis='columns', method='dense', pct=False) #
1
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1.0 | 1.0 | 2.0 | 2.0 |
1 | 1.0 | 2.0 | 1.0 | 3.0 |
df1.rank(axis='columns', method='dense', pct=True) # 按照百分比显示,相当于直接除行元素个数
1
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.500000 | 0.500000 | 1.000000 | 1.0 |
1 | 0.333333 | 0.666667 | 0.333333 | 1.0 |
# .round()
前面一章介绍了设置显示精度的操作,其不改变实际精度,而这个 API 则可以改变精度。
Series.round(decimals=0)
- decimals:控制小数位数
s= pd.Series([1.111,2.222])
s
1
2
2
0 1.111
1 2.222
dtype: float64
s.round(1)
1
0 1.1
1 2.2
dtype: float64
s.round(2)
1
0 1.11
1 2.22
dtype: float64
上次更新: 2023/11/01, 03:11:44