pandas与numpy中神奇的axis
最近在百奥智汇兼职,基本上比较重的工作就在数据处理,所以pandas和numpy用的比较多。
不知不觉中,pandas各种函数越用越熟练,但是总要靠结果来推算到底应该指定axis=0还是1,你有没有这种经历呢?
经过摸索,我找到了一种axis利于记忆也好解释的理论。下面一起来看看吧!
核心内容
axis 是你要操作的轴。
pandas
导入包,创建一个3X4的dataframe。
import pandas as pd
import numpy as np
data = pd.DataFrame(np.random.randn(4,3))
data.sum(axis=1)
out:
0 -0.429278
1 0.415985
2 1.555418
3 3.364704
dtype: float64
axis=1 ,说明我们要对第二个轴进行操作。
操作中处理的是第二个轴一共3个值,3个值被消灭了,被1个和值取代,结果是长度为4的series。
data.drop(1,axis=1)
out:
| 0 | 2 |
---|
0 | -0.002617 | 0.345585 | 1 | 0.273499 | -0.386345 | 2 | 2.602432 | 0.284169 | 3 | 1.570347 | 1.656065 |
同样对第二个轴进行操作。
处理的是第二个轴3个值,3个值被drop掉1列后变为2个值,结果是4X2的dataframe。
data_ = pd.DataFrame(np.random.randn(4,3))
pd.concat([data,data_],axis=1)
out:
| 0 | 1 | 2 | 0 | 1 | 2 |
---|
0 | -0.002617 | -0.772246 | 0.345585 | -0.349359 | -0.033281 | -0.774378 | 1 | 0.273499 | 0.528832 | -0.386345 | -1.630738 | 0.773259 | -0.953177 | 2 | 2.602432 | -1.331183 | 0.284169 | 1.714436 | 0.115564 | 2.480489 | 3 | 1.570347 | 0.138292 | 1.656065 | 0.229122 | 1.489628 | 3.029022 |
处理的是第二个轴,data 二轴3个值,拼接的data_ 二轴也为3个值,所以结果是4X6的dataframe。
data.sort_values([0],axis=1)
out:
| 1 | 0 | 2 |
---|
0 | -0.772246 | -0.002617 | 0.345585 | 1 | 0.528832 | 0.273499 | -0.386345 | 2 | -1.331183 | 2.602432 | 0.284169 | 3 | 0.138292 | 1.570347 | 1.656065 |
处理的是第二个轴3个值,对第一个轴name为0对应的3个值进行排序,从小到大,结果是4X3的dataframe。
来个更复杂的
下面为常见的归一化:
data.apply(lambda a:(a-np.min(a))/(np.max(a)-np.min(a)),axis=1)
out:
| 0 | 1 | 2 |
---|
0 | 0.688502 | 0.0 | 1.000000 | 1 | 0.721001 | 1.0 | 0.000000 | 2 | 1.000000 | 0.0 | 0.410653 | 3 | 0.943524 | 0.0 | 1.000000 |
处理的是第二个轴3个值,对第一轴每一个name对应的三个值进行归一化处理,结果是4X3的dataframe 。
强行输出就会看的更清晰:
data.apply(lambda a:print(a),axis=1)
0 -0.002617
1 -0.772246
2 0.345585
Name: 0, dtype: float64
0 0.273499
1 0.528832
2 -0.386345
Name: 1, dtype: float64
0 2.602432
1 -1.331183
2 0.284169
Name: 2, dtype: float64
0 1.570347
1 0.138292
2 1.656065
Name: 3, dtype: float64
out:
0 None
1 None
2 None
3 None
dtype: object
lambda 函数没有指定返回值,所以默认返回None ,结果是长度为4全为None 的series。
apply 函数可以实现非常多的自定义操作,也可以拿来自己实现sum , sort , drop 等操作,每次输入的都是n个值,返回1个值最后为series,返回n个值最后则为dataframe。
pandas中的axis是基于numpy的, 所以上面的概念在numpy中也适用。
numpy
其实numpy难的地方在于多维,下面来看一个三维的例子:
import numpy as np
data = np.arange(0, 24).reshape((2,3,4))
print(data.shape)
data
(2, 3, 4)
out:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
rollaxis 是轴滚动的意思,axis=n ,将n轴移到0轴。
data = np.arange(0, 24).reshape((2,3,4))
data = np.rollaxis(data,axis=2)
print(data.shape)
data
(4, 2, 3)
out:
array([[[ 0, 4, 8],
[12, 16, 20]],
[[ 1, 5, 9],
[13, 17, 21]],
[[ 2, 6, 10],
[14, 18, 22]],
[[ 3, 7, 11],
[15, 19, 23]]])
将最后一个轴移到最前面,其实就是挨个取最后一层的4个值,组成第一层,内部就是2X3的矩阵。
data = np.arange(0, 24).reshape((2,3,4))
data = np.rollaxis(data,axis=1)
print(data.shape)
data
(3, 2, 4)
out:
array([[[ 0, 1, 2, 3],
[12, 13, 14, 15]],
[[ 4, 5, 6, 7],
[16, 17, 18, 19]],
[[ 8, 9, 10, 11],
[20, 21, 22, 23]]])
将倒数第二个轴移到最前面,其实就是把最后一层4个值当成一个对象进行处理,挨个取第二层3个值,组成第一层,最后内部就是2X4的矩阵。
swapaxes 是轴交换的意思,m, n,将m轴与n轴交换。
data = np.arange(0, 24).reshape((2,3,4))
data = np.swapaxes(data,0,1)
print(data.shape)
data
(3, 2, 4)
out:
array([[[ 0, 1, 2, 3],
[12, 13, 14, 15]],
[[ 4, 5, 6, 7],
[16, 17, 18, 19]],
[[ 8, 9, 10, 11],
[20, 21, 22, 23]]])
结果为3,2,4,把最后一层4个值当成一个对象,实现的其实就是前面3, 2的转置。
data = np.arange(0, 24).reshape((2,3,4))
data = np.swapaxes(data,0,2)
print(data.shape)
data
(4, 3, 2)
out:
array([[[ 0, 12],
[ 4, 16],
[ 8, 20]],
[[ 1, 13],
[ 5, 17],
[ 9, 21]],
[[ 2, 14],
[ 6, 18],
[10, 22]],
[[ 3, 15],
[ 7, 19],
[11, 23]]])
结果为4,3,2,挨个取最后一层4个值,最后一层为第一层每次的2个值。
transpose 转置
data = np.arange(0, 24).reshape((2,3,4))
data = np.transpose(data,(1,2,0))
print(data.shape)
data
(3, 4, 2)
out:
array([[[ 0, 12],
[ 1, 13],
[ 2, 14],
[ 3, 15]],
[[ 4, 16],
[ 5, 17],
[ 6, 18],
[ 7, 19]],
[[ 8, 20],
[ 9, 21],
[10, 22],
[11, 23]]])
转置,2,3,4经过1,2,0的取值后为3,4,2,第一层移到最后。
np.newaxis 可以强行增加新轴。
data = np.arange(0, 24).reshape((2,3,4))
data = data[:,np.newaxis,:,:]
print(data.shape)
data
(2, 1, 3, 4)
out:
array([[[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]],
[[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]]])
思考
遇到点有意思的结果,不如大家一起思考一下:
array = np.array([['hello world','sssimon yang']])
print(array.shape)
(1, 2)
np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=0,arr=array)
out:
array([['hello', 'sssim']], dtype='<U5')
np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=1,arr=array)
out:
array([['hello', 'sssimon']], dtype='<U7')
为什么两次的结果会不一样呢?欢迎在评论区给出你的答案。
感谢大家
原文使用jupyterlab,out为jupyterlab每个cell的默认输出。谢谢大家!
我
我是 SSSimon Yang,关注我,用code解读世界
|