关于numpy、pandas的使用介绍教程

1、数组对象

Numpy库

Numpy最重要的一个特点是就是其N维数组对象,即ndarray,ndarray是一个通用的同构数据多维容器,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示各维度大小的元组,即表示有几行几列)和dtype(一个用于说明数组数据类型的对象)。本节将围绕ndarray数组展开。 
Numpy基础 
1、创建ndarray数组 
使用array函数,它接受一切序列型的对象,包括其他数组,然后产生一个新的Numpy数组。 
嵌套序列将会被转换成一个多维数组。 
np.array会尝试为每一个新建的数组推断出适合它的数据类型。 
arange是Python内置函数range的数组版。 
2、数据类型 
dtype是一个用来说明数组的数据类型的对象。其命名方式是一个类型名(float和int)后面跟一个用于表示各元素位长的数字。常用的是float64和int32. 
也可以使用astype进行数组中数据类型的转化。 
3、基本的索引和切片 
(1)元素索引、根据元素在数组中的位置来进行索引。 
一维数组的索引 
多维数组的索引 
(2)切片索引 
一维数组的切片索引(与Python列表的切片索引一样) 
多维数组的切片索引 
(3)花式索引 
元素索引和切片索引都是仅局限于连续区域的值,而花式索引可以选取特定区域的值。 
上述语句选出的是元素(1,0)、(5,3)、(7,1)、(2,2)。 
上述语句按0、3、1、2列的顺序依次显示1、5、7、2行。下述语句能实现同样的效果。 
Numpy数组的基本运算 
1、数组和标量之间的运算 
2、元素级数组函数 
是指对数组中每个元素执行函数运算。下面例子是对数组各元素执行平方根操作。还有abs、exp、sin、cos、log、sum、mean(算术平均数)、cumsum(所有元素的累计和)、cumprod(所有元素的累计积)、sort(将元素进行排序)等函数。

1.1、基础篇

官网文献,或者更详细的资料 
numpy的主要目标是构造由同种元素组成的多维数组,也就是一张在的表格,因为python自带的array.array,只能创建一维数组,并且只有简单的功能。所有的元素都是同一数据类型,元素通过索引定位,索引为整数,用元组来表示。在numpy中每一个维度都被称为轴,而轴的数目就是多维数组的秩。 
例如:[1,2,3]是一个秩为1的数组,该轴的长度为3,可以表示三维空间一个点,注意,这里的3维是通常意义的维,即向量空间的说法;而numpy中的维度是秩的意思,即数据需要用几个轴来表示。 
再如:[[1,2,3],[4,5,6]]是一个秩为2的多维数组,第一个轴的长度为2,第二个轴的长度为3,也就是对应的几行几列的意思。

在numpy中,数组类为ndarray,其具体的属性如下: 
ndarray.ndim: 
即多维数组的秩 
ndarray.shape: 
即多维数组各轴的长度,对二维数据来讲,就是行、列数。 
似乎各种数据只用到秩为2的多维数组就可以表示了,现实中自己还没想到需要更高维来表示的情形。 
ndarray.size: 
即多维数组元素的个数 
ndarray.dtype: 
即多维数组中元素的数据类型,可以是自定义的数据类型,可以是python原生数据类型,也可以是numpy中独有的数据类型。比如numpy.int32, numpy.int16, and numpy.float64 
ndarray.itemsize: 
即多维数组元素的字节数,一个元素类型为float64的数组itemsiz属性值为8(=64/8),又如,一个元素类型为complex32的数组item属性为4(=32/8) 
ndarray.data: 
即实际数组元素的缓冲区,也就是内在地址。通常用不到,因为一般我们是通过索引来访问元素的。在python原生的数据类型中,可通过id(变量名)来获得变量的内存地址。 
下面看一个例子:

import numpy as np
a=np.arange(0,15).reshape(3,5)#注意,numpy.arange给出范围的首尾后,得到的一维数组是不包含尾的,该例中生成了元素为0,……14数组
print(a)
print(type(a))
  • 1
  • 2
  • 3
  • 4

结果如下:

[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
<class 'numpy.ndarray'>
  • 1
  • 2
  • 3
  • 4
a_ndim=a.ndim
print(a_ndim)
  • 1
  • 2

结果为:2

a_shape=a.shape
print(a_shape)
  • 1
  • 2

结果为:(3, 5)

a_size=a.size
print(a_size)
  • 1
  • 2

结果为:15

a_dtype=a.dtype
print(a_dtype)
  • 1
  • 2

结果如下: 
int64 
可以看到默认的位数为64,应该是与python版本一致,也与ubuntu和电脑位数一致。

a_itemsize=a.itemsize
print(a_itemsize)
  • 1
  • 2

结果如下: 
8

a_data=a.data
print(a_data)
  • 1
  • 2

结果如下: 

1.2、创建数组

1.2.1、利用array()函数从python原生的list或和tuple中创建

生成的ndarray中元素的数据类型由原来list中的数据类型自动推导得到。值得注意的是,不能忘了[]号,要不程序不认识这类的结构。

a=np.array([1,2,3])
print(a)
print(type(a))
print(a.dtype)
  • 1
  • 2
  • 3
  • 4

结果如下:

[1 2 3]
<class 'numpy.ndarray'>
int64
  • 1
  • 2
  • 3
b=np.array([1.0,2.0,3.0])
print(b)
print(type(b))
print(b.dtype)
  • 1
  • 2
  • 3
  • 4

结果如下

[ 1.  2.  3.]
<class 'numpy.ndarray'>
float64
  • 1
  • 2
  • 3

也可以使用元组来创建

c=np.array((1,2,3))
print(c)
print(type(c))
print(c.dtype)
  • 1
  • 2
  • 3
  • 4

结果如下:

[1 2 3]
<class 'numpy.ndarray'>
int64
  • 1
  • 2
  • 3

下面创建二维数组

d=np.array([[1,2,3],[4,5,6]])
print(d)
print(type(d))
print(d.dtype)
结果如下:
  • 1
  • 2
  • 3
  • 4
  • 5

[[1 2 3] 
[4 5 6]] 

  • 1
d=np.array([(1,2,3),(4,5,6)])
print(d)
print(type(d))
print(d.dtype)
  • 1
  • 2
  • 3
  • 4

结果如下:

[[1 2 3]
 [4 5 6]]
<class 'numpy.ndarray'>
int64
  • 1
  • 2
  • 3
  • 4

创建二维数组的时候一定不能忘了最外层的[]。

#也可以直接指定元素的数据类型
e=np.array([[1,2,3],[4,5,6]],dtype=complex)
print(e)
print(type(e))
print(e.dtype)
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下: 
[[ 1.+0.j 2.+0.j 3.+0.j] 
[ 4.+0.j 5.+0.j 6.+0.j]] 

1.2.2、利用numpy中的函数来创建多维数组

zeros(),ones(),empty(),默认情况下,元素的数据类型都为float64,同时empty()得到的并不是内容为空的数组,而是依据内存状态随机产生内容。

a=np.zeros((3,4))
print(a)
print(a.dtype)
  • 1
  • 2
  • 3

结果如下:

[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]
float64
  • 1
  • 2
  • 3
  • 4
b=np.ones((3,4),dtype=np.int16)
print(b)
print(b.dtype)
  • 1
  • 2
  • 3

结果如下:

[[1 1 1 1]
 [1 1 1 1]
 [1 1 1 1]]
int16
  • 1
  • 2
  • 3
  • 4
c=np.empty((3,4))
print(c)
print(c.dtype)
  • 1
  • 2
  • 3

结果如下:

[[  6.90924984e-310   1.44608351e-316   6.90924999e-310   6.90923664e-310]
 [  2.37151510e-322   3.16202013e-322   0.00000000e+000   6.90922989e-310]
 [  6.90925005e-310   1.63041663e-322   1.42265056e-316   1.41881503e-316]]
float64
  • 1
  • 2
  • 3
  • 4

像上面那样手动输入列表或元组元素来创建多维数组问题很不方便,numpy提供了像arange()和linespace()这样的函数来创建一维数组。

a=np.arange(0,20,5)
print(a)
print(a.dtype)
  • 1
  • 2
  • 3

结果如下:

[ 0  5 10 15]
int64
  • 1
  • 2

首先可以看到,arange()的元素范围是不包括20的,这与R、matlab中的习惯不一样

b=np.arange(0,3.0,0.4)
print(b)
print(b.dtype)
结果如下:
  • 1
  • 2
  • 3
  • 4
[ 0.   0.4  0.8  1.2  1.6  2.   2.4  2.8]
float64
  • 1
  • 2

由于arange()中数据精度的问题,包括尾部截断的问题,我们并没有办法完成准确的确定得到的数组的元素个数。如果使用linespace()则不会有这个问题。

c=np.linspace(0,3.0,13)
print(c)
print(c.dtype)
  • 1
  • 2
  • 3

结果如下:

[ 0.    0.25  0.5   0.75  1.    1.25  1.5   1.75  2.    2.25  2.5   2.75
  3.  ]
float64
  • 1
  • 2
  • 3

其他的函数还有zeros_like、ones_like、empty_like、rand、randn、fromfunction、fromfile,详情参考

1.2.3、多维数组打印

创建的数组有时想查看对不对等,就需要打印出来。 
打印出来的数组以以类似嵌套列表的形式显示它,但是呈以下布局:

最后的轴从左到右打印
次后的轴从顶向下打印
剩下的轴从顶向下打印,每个切片通过一个空行与下一个隔开
  • 1
  • 2
  • 3

一维数组被打印成行,二维数组成矩阵,三维数组成矩阵列表。

a = np.arange(6)
print(a)
  • 1
  • 2

结果如下:

[0 1 2 3 4 5]
  • 1
b = np.arange(12).reshape(4,3)
print(b)
  • 1
  • 2

结果如下:

[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
  • 1
  • 2
  • 3
  • 4
c = np.arange(24).reshape(2,3,4)
print(c)
  • 1
  • 2

结果如下:

[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如果一个数组用来打印太大了,NumPy自动省略中间部分而只打印头部和尾部

print(np.arange(10000).reshape(100,100))
  • 1
[[   0    1    2 ...,   97   98   99]
 [ 100  101  102 ...,  197  198  199]
 [ 200  201  202 ...,  297  298  299]
 ..., 
 [9700 9701 9702 ..., 9797 9798 9799]
 [9800 9801 9802 ..., 9897 9898 9899]
 [9900 9901 9902 ..., 9997 9998 9999]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可以通过设置printoptions参数禁用NumPy的这种行为并强制打印整个数组。

np.set_printoptions(threshold='nan')
  • 1

具体用法参考官网。

1.3、数组的基本运算

数组的运算(算术和逻辑运算),是建立的元素的基础上,如两个数组相加是对应位置的元素相加。

a=np.array([20,21,23,24])
b=np.arange(1,5)
c=a+b
d=a-b
e=a*b
f=a/b
g=2*a
h=np.sin(a)
i=a<22
print('a=')
print(a)
print('b=')
print(b)
print('c=')
print(c)
print('d=')
print(d)
print('e=')
print(e)
print('f=')
print(f)
print('g=')
print(g)
print('h=')
print(h)
print('i=')
print(i)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

结果如下:

a=
[20 21 23 24]
b=
[1 2 3 4]
c=
[21 23 26 28]
d=
[19 19 20 20]
e=
[20 42 69 96]
f=
[ 20.          10.5          7.66666667   6.        ]
g=
[40 42 46 48]
h=
[ 0.91294525  0.83665564 -0.8462204  -0.90557836]
i=
[ True  True False False]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

*号实现的数据的对位相乘,如果要实现矩阵乘法,需要用doc()函数

a=np.arange(1,5).reshape((2,2))
b=np.arange(3,7).reshape((2,2))
c=a*b
d=np.dot(a,b)
print('a=')
print(a)
print('b=')
print(b)
print('c=')
print(c)
print('d=')
print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
a=
[[1 2]
 [3 4]]
b=
[[3 4]
 [5 6]]
c=
[[ 3  8]
 [15 24]]
d=
[[13 16]
 [29 36]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

+=和*=用来更改已存在的数组而不是创建一个新的数组。其他可以把它想像成赋值。

a=np.ones((2,3),dtype=np.int)
b=np.random.random((2,3))
print('更改前a=')
print(a)
print('更改前b=')
print(b)
a*=3
print('a乘3后变成a=')
print(a)
b+=a
print('更改后b=')
print(b)
a+=b
print('更改后a=')
print(a)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

结果如下:

更改前a=
[[1 1 1]
 [1 1 1]]
更改前b=
[[ 0.06645185  0.09648822  0.84473624]
 [ 0.14024568  0.18016756  0.49188146]]
a乘3后变成a=
[[3 3 3]
 [3 3 3]]
更改后b=
[[ 3.06645185  3.09648822  3.84473624]
 [ 3.14024568  3.18016756  3.49188146]]
Traceback (most recent call last):
  File "/home/digger/PycharmProjects/mllibdata/spark-warehouse/numpy_test.py", line 149, in <module>
    a+=b
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

可以看到计算后的结果,但是最后一个计算并没有成功,原因是无法将浮点型数据加到整个数据中,并改变整型数据的值(猜大概是因为整型数据在内存中占据的存储空间没有浮点型占据的多) 
在numpy中计算的时候会自动去适应精度更高的,如

a=np.ones(3,dtype=np.int32)
b=np.linspace(0,np.pi,3)
c=a+b
d=np.exp(c*1j)
print('a=')
print(a)
print('b=')
print(b)
print('c=')
print(c)
print('d=')
print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果为:

a=
[1 1 1]
b=
[ 0.          1.57079633  3.14159265]
c=
[ 1.          2.57079633  4.14159265]
d=
[ 0.54030231+0.84147098j -0.84147098+0.54030231j -0.54030231-0.84147098j]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

从上面结果可以看到c的精度跟a、b中较高的精度相一致,d的精度又跟1j一致,复数要比实现精度更高。这也不难理解,为什么之前的最后一个会报错,因为计算得到的是一个更高精度的数据,却填到一个低精度的空间,自然无法完成。

1.4、通用函数(ufunc)

sum()、max()、min() 
这三个函数都计算整个数组的元素,如果要按某一个轴来计算,需要用axis参数来指明。

b=np.arange(12).reshape((3,4))
print(b)
print(b.sum())
print(b.sum(axis=0))
print(b.max())
print(b.max(axis=1))
print(b.min())
print(b.min(axis=0))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

结果如下:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
66
[12 15 18 21]
11
[ 3  7 11]
0
[0 1 2 3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其他通用函数还有: 
sin(), cos(),exp(),sqrt(),add(),all, alltrue, any, apply along axis, argmax, argmin, argsort, average, bincount, ceil, clip,conj, conjugate, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, inv, lexsort, max,maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sometrue, sort, std, sum, trace, transpose, var, vdot, vectorize, where

详情用法请参考官网

1.5、索引、切片和迭代

1.5.1、一维数组

一维数组可以索引,切片(个人觉得切片不就是索引的延伸么),迭代,这种操作与列表是一样的。

a=np.arange(10)**3#两个*表示接几次方,挺好的一种表示方式
b=a[2]
c=a[2:5]#注意numpy中,不管是arange(),还是索引中,范围的表示都是不包含最后一个数字
print(a)
print(b)
print(c)
a[:6:2]=-1000#左边范围未写表示从0开始,表示数组a从左开始每隔一个元素,将其他值替换为-1000
print(a)
d=a[::-1]#左边范围未写分别默认为首尾,-1表示逆序
print(d)
for i in a:#迭代,并逐个打印
    print(i**(1/3))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果如下:

[  0   1   8  27  64 125 216 343 512 729]
8
[ 8 27 64]
[-1000     1 -1000    27 -1000   125   216   343   512   729]
[  729   512   343   216   125 -1000    27 -1000     1 -1000]
nan
1.0
nan
3.0
nan
5.0
6.0
7.0
8.0
9.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

从上面的结果可以看到,对元素求根号3时出现了nan,原因是原数据类型为int64,无法得到复数值。

1.5.2、多维数组

多维数组的索引可以通过在每一个轴上给出对应的索引值来获取对应位置的元素,这个与matlab和R中是一样的,python中索引从0开始,而R中是从1开始。

def f(x,y):
    return 10*x+y
b=np.fromfunction(f,(5,4),dtype=int)#注意这里(5,4)即声明了这个多维数组的行列数,也是传给f的x、y的聚会范围,x=arange(5),y=arange(4)
print('b=')
print(b)
#取一个元素
print('b[2,3]=')
print(b[2,3])
#取一部分元素
print('b[2:5,1]=')
print(b[2:5,1])
#只给出一部分轴的索引,其他轴会用:,表示全部索引
print('b[:,1]=')
print(b[:,1])
print('b[1,:]=')
print(b[1,:])
#只给出一部分轴,其他轴自动取全体索引,缺失的轴只能是后面的,不能前面缺失,如[,2:3]这样的是错的,但[2:3]是对的
print('b[1]=')
print(b[1])
#-1表示最后一行\一列
print('b[-1]=')
print(b[-1])
print('b[:,-1]=')
print(b[:,-1])

# 如果有多个轴,其他轴都取全体值,按之前的做法,我们要写多个:号,但是我们可以用...代替。
# x[1,2,...] is equivalent to x[1,2,:,:,:],
# x[...,3] to x[:,:,:,:,3] and
# x[4,...,5,:] to x[4,:,:,5,:].

c = np.array( [[[0,1,2],[ 10, 12, 13]],[[100,101,102],[110,112,113]]])
print('c=')
print(c)
print('c的行列数为:')
print(np.shape(c))
print('c[1,...]=')
print(c[1,...])
print('c[1,:,:]=')
print(c[1,:,:])
print('c[1]=')
print(c[1])
print('c[:,:,2]=')
print(c[:,:,2])
print('c[...,2]=')
print(c[...,2])

#对于多维数组,用循环的方式去取元素的时候,默认情况并不是取出逐个的元素,而是按照第一轴的顺序,依次整组整取出(当然也可以把其他轴一起组成的集合看成是第一轴上的某个元素)
print('按第一轴,逐组取:')
for x in c:
    print('分隔一下')
    print(x)
#如果要逐个元素取出,需要用数组的flat属性。
print('真正逐个元素取:')
for x in c.flat:
    print(x)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

结果如下:

b=
[[ 0  1  2  3]
 [10 11 12 13]
 [20 21 22 23]
 [30 31 32 33]
 [40 41 42 43]]
b[2,3]=
23
b[2:5,1]=
[21 31 41]
b[:,1]=
[ 1 11 21 31 41]
b[1,:]=
[10 11 12 13]
b[1]=
[10 11 12 13]
b[-1]=
[40 41 42 43]
b[:,-1]=
[ 3 13 23 33 43]
c=
[[[  0   1   2]
  [ 10  12  13]]

 [[100 101 102]
  [110 112 113]]]
c的行列数为:
(2, 2, 3)
c[1,...]=
[[100 101 102]
 [110 112 113]]
c[1,:,:]=
[[100 101 102]
 [110 112 113]]
c[1]=
[[100 101 102]
 [110 112 113]]
c[:,:,2]=
[[  2  13]
 [102 113]]
c[...,2]=
[[  2  13]
 [102 113]]
按第一轴,逐组取:
分隔一下
[[ 0  1  2]
 [10 12 13]]
分隔一下
[[100 101 102]
 [110 112 113]]
真正逐个元素取:
0
1
2
10
12
13
100
101
102
110
112
113
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

1.6、形态操作

1.6.1、改变数组形状

#改变数组形状
a=np.floor(np.random.random((3,4))*10)
print('a=')
print(a)
print('a_shape=')
print(a.shape)
#下面的这些函数在改变数组形状的时候并没有影响原数组,而是生成新的数组。这与数组的+=和*=是不一样的。
#将多维数组变成一维数组
print('a.ravel()=')
print(a.ravel())
#更改行列数
print('a.reshape(6,2)=')
print(a.reshape(6,2))
#获得转置后的数组,某种程度上可以当作矩阵使用
print('a.T=')
print(a.T)
print('a转置后的行列数为:')
print(a.T.shape)
print('a的行列数仍然为:')
print(a.shape)

#reshape()函数不影响原数组,而 resize()函数则改变原数组本身
a.resize(2,6)
print('resize()后原数发生变化,a=')
print(a)
print('a的行列数为:')
print(a.shape)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

结果如下:

a=
[[ 0.  3.  5.  9.]
 [ 5.  2.  4.  1.]
 [ 8.  8.  3.  6.]]
a_shape=
(3, 4)
a.ravel()=
[ 0.  3.  5.  9.  5.  2.  4.  1.  8.  8.  3.  6.]
a.reshape(6,2)=
[[ 0.  3.]
 [ 5.  9.]
 [ 5.  2.]
 [ 4.  1.]
 [ 8.  8.]
 [ 3.  6.]]
a.T=
[[ 0.  5.  8.]
 [ 3.  2.  8.]
 [ 5.  4.  3.]
 [ 9.  1.  6.]]
a转置后的行列数为:
(4, 3)
a的行列数仍然为:
(3, 4)
resize()后原数发生变化,a=
[[ 0.  3.  5.  9.  5.  2.]
 [ 4.  1.  8.  8.  3.  6.]]
a的行列数为:
(2, 6)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

1.7、数组的组合

#vstack和hstack分别是将原数组当成一块,然后以列的方式和行的方式堆积在一块
a=np.floor(np.random.random((2,3))*10)
b=np.floor(np.random.random((2,3))*10)
c=np.vstack((a,b))
d=np.hstack((a,b))
print('a=')
print(a)
print('b=')
print(b)
print('c=')
print(c)
print('d=')
print(d)
#colunm_stcak则是将原数组的各列拿出来,把列当成元素,排成一行。
e=np.column_stack((a,b))
print('e=')
print(e)
f=a[:,np.newaxis]#newaxis可以将原数组按第一轴的顺序拆分成单个‘元素’(第一轴外的结构不发生变化),拆分出来的单个‘元素’与原数组具有相同的秩,只不过只有一行而已,然后这些‘元素’再按列排列成新的数组,新数组的秩比原数组多1
print('f=')
print(f)
g=b[:,np.newaxis]#newaxis可以将原数组按第一轴的顺序拆分成单个‘元素’(第一轴外的结构不发生变化),拆分出来的单个‘元素’与原数组具有相同的秩,只不过只有一行而已,然后这些‘元素’再按列排列成新的数组,新数组的秩比原数组多1
print('g=')
print(g)
h=np.column_stack((f,g))
print('h=')
print(h)
#对比一下vstack
i=np.vstack((f,g))
print('i=')
print(i)

#concatenate参数可以指明沿哪个轴组合

#r_[],c_[]指明沿着一个方向产生数组
a=np.r_[1:4,0,4]
print('a=')
print(a)
b=np.c_[1:4]
print('b=')
print(b)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

结果如下:

a=
[[ 7.  6.  5.]
 [ 7.  3.  3.]]
b=
[[ 5.  3.  2.]
 [ 1.  1.  4.]]
c=
[[ 7.  6.  5.]
 [ 7.  3.  3.]
 [ 5.  3.  2.]
 [ 1.  1.  4.]]
d=
[[ 7.  6.  5.  5.  3.  2.]
 [ 7.  3.  3.  1.  1.  4.]]
e=
[[ 7.  6.  5.  5.  3.  2.]
 [ 7.  3.  3.  1.  1.  4.]]
f=
[[[ 7.  6.  5.]]

 [[ 7.  3.  3.]]]
g=
[[[ 5.  3.  2.]]

 [[ 1.  1.  4.]]]
h=
[[[ 7.  6.  5.]
  [ 5.  3.  2.]]

 [[ 7.  3.  3.]
  [ 1.  1.  4.]]]
i=
[[[ 7.  6.  5.]]

 [[ 7.  3.  3.]]

 [[ 5.  3.  2.]]

 [[ 1.  1.  4.]]]
a=
[1 2 3 0 4]
b=
[[1]
 [2]
 [3]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

1.8、数组的拆分

未完待续

1.9、numpy数组中Nan和Inf的处理方法

可使用isinf、isneginf、isposinf、isnan、isfinite 来进行判断

import numpy as np
np.isnan(np.array([[1, np.nan, np.inf],\ ... [np.nan, -np.inf, -0.25]])) 
array([[False, True, False], [ True, False, False]], dtype=bool)
  • 1
  • 2
  • 3

处理方法

numpy.nan_to_num(x):
  • 1

使用0代替数组x中的nan元素,使用有限的数字代替inf元素

import numpy as np
a = np.array([[np.nan,np.inf],\ ... [-np.nan,-np.inf]])
a array([[ nan, inf], [ nan, -inf]])
np.nan_to_num(a) array([[ 0.00000000e+000, 1.79769313e+308], [ 0.00000000e+000, -1.79769313e+308]])
  • 1
  • 2
  • 3
  • 4

但真正处理的方法应该是弄清nan产生的原因,对后续的影响,自己要完成的功能,采取切当的替换或其他处理。

2、矩阵对象

Numpy下的矩阵(Matrix)对象

Matrix类型继承于ndarray类型,因此含有ndarrayr的所有数据属性和方法。Matrix类型与ndarry类型有六个重要的不同点,当你把Matrix对象当作ndarray对象操作的时候,这些不同点会导致非预期的结果。

1)Matrix对象可以使用Matlab风格的字符串来创建,也就是一个以空格分隔列,以分号分隔行的字条串。 
2)Matrix对象问题二维的。这包含有深远的影响,比如m.ravel()的返回值是二维的,成员选择的返回值也是二维的,因此序列的行为与array会有本质的不同。 
3)Matrix类型的乘法覆盖了array的乘法,使用的是矩阵的乘法运算。当你接收矩阵的返回值的时候,确保自己已经理解这些函数的含义。特别地,如果m是一个matrix,函数asanyarray(m)会返回一个matrix。 
4)Matrix类型的幂运算也覆盖了之前的幂运算,使用矩阵的幂。如果使用一个矩阵的幂作为参数调用asanarray(…)跟上面的相同。 
5)矩阵默认的array_priority是10.0,因而ndaary和matrix对象混合的运算总是返回矩阵。 
6)矩阵有几个特有的属性使得计算更加容易,这些属性有: 
(a).T–返回自身的转置 
(b).H–返回自身的共轭转置 
(c).I–返回自身的逆矩阵 
(d).A–返回自身数据的2维数组的一个视图 
Matrix类是ndarray的一个python子类。Matrix对象也可以使用其他的Matrix对象,字符串,或者其他可以转换为ndarray的参数来构造。另外,在numpy里,mat是Matrix的一个别名。

#例子:使用字符串构造矩阵
from numpy import *
a=mat('1 2 3;4 5 3')
print('a=')
print(a)
print('a*a.T=')#这个里矩阵的乘法,而不是数组的对位相乘
print(a*a.T)
print('(a*a.T).I=')
print((a*a.T).I)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果如下:

a=
[[1 2 3]
 [4 5 3]]
a*a.T=
[[14 23]
 [23 50]]
(a*a.T).I=
[[ 0.29239766 -0.13450292]
 [-0.13450292  0.08187135]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
#例2: 使用嵌套序列构造矩阵
b=mat([[1,5,10],[1.0,3,4j]])
print('b=')
print(b)
  • 1
  • 2
  • 3
  • 4

结果如下:

b=
[[  1.+0.j   5.+0.j  10.+0.j]
 [  1.+0.j   3.+0.j   0.+4.j]]
  • 1
  • 2
  • 3

Matrix( data, dtype=None, copy=True ) 
将以参数data传进来的数据转换为矩阵。如果dtype是None,那么数据类型将由data的内容来决定。如果copy为True,则会拷贝data中的数据,否则会使用原来的数据缓冲。如果没有找到数据的缓冲区,当然也会进行数据的拷贝。注意:矩阵matrix事实上是一个对象,因

此当你构造实例的时候会调用matrix.new(matrix, data, dtype, copy)。

Asmatrix(data, dtype=None) 
返回不经过复制的数据。等价于matrix(data, dtype, copy=False)。

Bmat(obj, ldict=None, gdict=None) 
使用一个字符串,嵌套的序列或者一个数组(array)构造一个矩阵。这个命令允许你从其它的对象来建立起矩阵。其中当obj是一个字符串的时候才会使用参数ldict和gdict,这两个参数是局部和模块的字典。如果你没有提供它们,这些将由系统提供。

#利用组合来构造
A=mat('2 2;2 2')
B=mat('1 1;1 1')
C=bmat('A B;B A')
print('C=')
print(C)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:

C=
[[2 2 1 1]
 [2 2 1 1]
 [1 1 2 2]
 [1 1 2 2]]
  • 1
  • 2
  • 3
  • 4
  • 5

矩阵对象的属性: 
matrix.T transpose:返回矩阵的转置矩阵 
matrix.H hermitian (conjugate) transpose:返回复数矩阵的共轭元素矩阵 
matrix.I inverse:返回矩阵的逆矩阵 
matrix.A base array:返回矩阵基于的数组 
矩阵对象的方法: 
all([axis, out]) :沿给定的轴判断矩阵所有元素是否为真(非0即为真) 
any([axis, out]) :沿给定轴的方向判断矩阵元素是否为真,只要一个元素为真则为真。 
argmax([axis, out]) :沿给定轴的方向返回最大元素的索引(最大元素的位置). 
argmin([axis, out]): 沿给定轴的方向返回最小元素的索引(最小元素的位置) 
argsort([axis, kind, order]) :返回排序后的索引矩阵 
astype(dtype[, order, casting, subok, copy]):将该矩阵数据复制,且数据类型为指定的数据类型 
byteswap(inplace) Swap the bytes of the array elements 
choose(choices[, out, mode]) :根据给定的索引得到一个新的数据矩阵(索引从choices给定) 
clip(a_min, a_max[, out]) :返回新的矩阵,比给定元素大的元素为a_max,小的为a_min 
compress(condition[, axis, out]) :返回满足条件的矩阵 
conj() :返回复数的共轭复数 
conjugate() :返回所有复数的共轭复数元素 
copy([order]) :复制一个矩阵并赋给另外一个对象,b=a.copy() 
cumprod([axis, dtype, out]) :返回沿指定轴的元素累积矩阵 
cumsum([axis, dtype, out]) :返回沿指定轴的元素累积和矩阵 
diagonal([offset, axis1, axis2]) :返回矩阵中对角线的数据 
dot(b[, out]) :两个矩阵的点乘 
dump(file) :将矩阵存储为指定文件,可以通过pickle.loads()或者numpy.loads()如:a.dump(‘d:\a.txt’) 
dumps() :将矩阵的数据转存为字符串. 
fill(value) :将矩阵中的所有元素填充为指定的value 
flatten([order]) :将矩阵转化为一个一维的形式,但是还是matrix对象 
getA() :返回自己,但是作为ndarray返回 
getA1():返回一个扁平(一维)的数组(ndarray) 
getH() :返回自身的共轭复数转置矩阵 
getI() :返回本身的逆矩阵 
getT() :返回本身的转置矩阵 
max([axis, out]) :返回指定轴的最大值 
mean([axis, dtype, out]) :沿给定轴方向,返回其均值 
min([axis, out]) :返回指定轴的最小值 
nonzero() :返回非零元素的索引矩阵 
prod([axis, dtype, out]) :返回指定轴方型上,矩阵元素的乘积. 
ptp([axis, out]) :返回指定轴方向的最大值减去最小值. 
put(indices, values[, mode]) :用给定的value替换矩阵本身给定索引(indices)位置的值 
ravel([order]) :返回一个数组,该数组是一维数组或平数组 
repeat(repeats[, axis]) :重复矩阵中的元素,可以沿指定轴方向重复矩阵元素,repeats为重复次数 
reshape(shape[, order]) :改变矩阵的大小,如:reshape([2,3]) 
resize(new_shape[, refcheck]) :改变该数据的尺寸大小 
round([decimals, out]) :返回指定精度后的矩阵,指定的位数采用四舍五入,若为1,则保留一位小数 
searchsorted(v[, side, sorter]) :搜索V在矩阵中的索引位置 
sort([axis, kind, order]) :对矩阵进行排序或者按轴的方向进行排序 
squeeze([axis]) :移除长度为1的轴 
std([axis, dtype, out, ddof]) :沿指定轴的方向,返回元素的标准差. 
sum([axis, dtype, out]) :沿指定轴的方向,返回其元素的总和 
swapaxes(axis1, axis2):交换两个轴方向上的数据. 
take(indices[, axis, out, mode]) :提取指定索引位置的数据,并以一维数组或者矩阵返回(主要取决axis) 
tofile(fid[, sep, format]) :将矩阵中的数据以二进制写入到文件 
tolist() :将矩阵转化为列表形式 
tostring([order]):将矩阵转化为python的字符串. 
trace([offset, axis1, axis2, dtype, out]):返回对角线元素之和 
transpose(*axes) :返回矩阵的转置矩阵,不改变原有矩阵 
var([axis, dtype, out, ddof]) :沿指定轴方向,返回矩阵元素的方差 
view([dtype, type]) :生成一个相同数据,但是类型为指定新类型的矩阵。

ü All方法 
更详细的可参考该文

3、numpy中matrix 和 array的区别

Numpy matrices必须是2维的,但是 numpy arrays (ndarrays) 可以是多维的(1D,2D,3D····ND). Matrix是Array的一个小的分支,包含于Array。所以matrix 拥有array的所有特性。

在numpy中matrix的主要优势是:相对简单的乘法运算符号。例如,a和b是两个matrices,那么aba∗b,就是矩阵积。

matrix 和 array 都可以通过objects后面加.T 得到其转置。但是 matrix objects 还可以在后面加 .H f得到共轭矩阵, 加 .I 得到逆矩阵。

相反的是在numpy里面arrays遵从逐个元素的运算,所以array:c 和d的cdc∗d运算相当于matlab里面的c.dc.∗d运算。

数组要实现矩阵相乘,则需要numpy里面的dot命令 :

print(np.dot(c,d))
  • 1

∗∗ 运算符的作用也不一样 
因为a是个matrix,所以a2a∗∗2返回的是aaa∗a,相当于矩阵相乘。而c是array,c2c∗∗2相当于,c中的元素逐个求平方。

如果一个程序里面既有matrix 又有array,会让人脑袋大。 
可以通过下面的两条命令轻松的实现两者之间的转换:np.asmatrix和np.asarray

matlab中的matrix的最大的不同是,在做归约运算时,array的维数会发生变化,但matrix总是保持为2维,换句话说它不会自动规约。例如下面求平均值的运算。

#矩阵
m=np.mat([[1,2],[3,4]])
#mm=m.mean
#print('mm.shape=')
#print(mm.shape)#会报错
mm1=m.mean(1)
print('mm1.shape=')
print(mm1.shape)
print('m=')
print(m)
print('mm=')
#print(mm)
#print('m-mm=')
#print(m-mm)
print('mm1=')
print(mm1)
print('m-mm1=')
print(m-mm1)

#数组
a = np.array([[1,2],[2,3]])
am = a.mean()
print('am.shape=')
print(am.shape)
am1 = a.mean(1)
print('am1.shape=')
print(am1.shape)
print('a=')
print(a)
print('am=')
print(am)
print('a-am=')
print(a-am)
print('am1=')
print(am1)
print('a-am1=')
print(a-am1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

结果如下

mm1.shape=
(2, 1)
m=
[[1 2]
 [3 4]]
mm=
mm1=
[[ 1.5]
 [ 3.5]]
m-mm1=
[[-0.5  0.5]
 [-0.5  0.5]]
am.shape=
()
am1.shape=
(2,)
a=
[[1 2]
 [2 3]]
am=
2.0
a-am=
[[-1.  0.]
 [ 0.  1.]]
am1=
[ 1.5  2.5]
a-am1=
[[-0.5 -0.5]
 [ 0.5  0.5]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

NumPy是一个关于矩阵运算的库,熟悉Matlab的都应该清楚,这个库就是让python能够进行矩阵话的操作,而不用去写循环操作。

下面对numpy中的操作进行总结。 
numpy包含两种基本的数据类型:数组和矩阵。 
详细可参考 
矩阵 
矩阵的操作与Matlab语言有很多的相关性。

#创建矩阵
>>> m=mat([1,2,3])
>>> m
matrix([[1, 2, 3]])

#取值
>>> m[0]                #取一行
matrix([[1, 2, 3]])
>>> m[0,1]              #第一行,第2个数据
2
>>> m[0][1]             #注意不能像数组那样取值了
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/numpy/matrixlib/defmatrix.py", line 305, in __getitem__
    out = N.ndarray.__getitem__(self, index)
IndexError: index 1 is out of bounds for axis 0 with size 1

#将Python的列表转换成NumPy的矩阵
>>> list=[1,2,3]
>>> mat(list)
matrix([[1, 2, 3]])

#矩阵相乘
>>> m1=mat([1,2,3])     #13列
>>> m2=mat([4,5,6]) 
>>> m1*m2.T             #注意左列与右行相等 m2.T为转置操作
matrix([[32]])       
>>> multiply(m1,m2)     #执行点乘操作,要使用函数,特别注意
matrix([[ 4, 10, 18]])   

#排序
>>> m=mat([[2,5,1],[4,6,2]])    #创建23列矩阵
>>> m
matrix([[2, 5, 1],
        [4, 6, 2]])
>>> m.sort()                    #对每一行进行排序
>>> m
matrix([[1, 2, 5],
        [2, 4, 6]])

>>> m.shape                     #获得矩阵的行列数
(2, 3)
>>> m.shape[0]                  #获得矩阵的行数
2
>>> m.shape[1]                  #获得矩阵的列数
3

#索引取值
>>> m[1,:]                      #取得第一行的所有元素
matrix([[2, 4, 6]])
>>> m[1,0:1]                    #第一行第0个元素,注意左闭右开
matrix([[2]])
>>> m[1,0:3]
matrix([[2, 4, 6]])
>>> m[1,0:2]
matrix([[2, 4]])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

扩展矩阵函数tile() 
例如,要计算[0,0,0]到一个多维矩阵中每个点的距离,则要将[0,0,0]进行扩展。

tile(inX, (i,j)) ;i是扩展个数,j是扩展长度
  • 1

实例如下:

>>>x=mat([0,0,0])
>>> x
matrix([[0, 0, 0]])
>>> tile(x,(3,1))           #即将x扩展3个,j=1,表示其列数不变
matrix([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
>>> tile(x,(2,2))           #x扩展2次,j=2,横向扩展
matrix([[0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0]])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

python的常见矩阵运算

4、Pandas库

pandas快速入门 
Pandas数据结构

4.1、Series

(1)概念: 
Series是一种类似于一维数组的对象,它由一组数据以及一组与之相关的数据标签(即索引)组成。 
(2)创建Series 
a、通过series来创建 
Series的字符串表现形式为:索引在左边,值在右边。当我们没有为数据指定索引时,Series会自动创建一个0到N-1(N为数据的长度)的整数型索引。可以通过Series的values和index属性获取其数组的值和对应的属性。 
也可以在创建Series的时候为值直接创建索引。 
b、通过字典的形式来创建Series。 
(3)获取Series中的值 
通过索引的方式选取Series中的单个或一组值。 
Pandas Series 中的详细用法,可查看该网址或该网址。包括构造方法、属性、转换、索引和迭代、二元运算、函数应用&分组&窗口、描述统计学、从新索引&选择&标签操控、处理缺失值、重塑&排序、Combining&joining&merging、时间序列相关、类似Datetime类型的属性、DateTime属性、DateTime方法、Timedelta属性、Timedelta方法、字符串处理、分类、作图、转化为其他格式

4.2、DataFrame

(1)概念: 
DataFrame是一个表格型的数据结构,含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,其中的数据是以一个或多个二维块存放的,而不是列表、字典或别的一维数据结构。 
(2)创建DataFrame: 
最常用的一种方法是直接传入一个等长列表或numpy数组组成的字典: 
结果DataFrame会自动加上索引(添加方法与Series一样),且全部列会被有序排列。 
如果指定了列序列、索引,则DataFrame的列会按指定顺序及索引进行排列。 
也可以设置DataFrame的index和columns的name属性,则这些信息也会被显示出来。 
pandas 修改 DataFrame 列名 
有一个DataFrame,列名为:[‘a,a′,′b’, ‘c,c′,′d’, ‘$e’],现需要改为:[‘a’, ‘b’, ‘c’, ‘d’, ‘e’]

解决: 
方式一:columns属性 
①暴力

df.columns = ['a', 'b', 'c', 'd', 'e']
  • 1
import pandas as pd
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})
print(df)
df.columns=['a','b','c','d','e']
print(df)
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:

   $a  $b  $c  $d  $e
0   1   1   1   1   1
   a  b  c  d  e
0  1  1  1  1  1
  • 1
  • 2
  • 3
  • 4

②修改

df.columns = df.columns.str.strip('$')
  • 1

③修改

df.columns = df.columns.map(lambda x:x[1:])
  • 1

方式二:rename方法、columns参数 
④暴力(好处:也可只修改特定的列)

df.rename(columns=('$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}, inplace=True) 
  • 1

⑤修改

df.rename(columns=lambda x:x.replace('$',''), i">pandas 修改 DataFrame 列名
  • 1

(3)获取DataFrame的值(行或列) 
通过查找columns值获取对应的列。(下面两种方法) 
通过索引字段ix查找相应的行。 
pandas.dataframe中根据条件获取元素所在的位置(索引) 
代码如下所示:

df = pd.DataFrame({'BoolCol': [1, 2, 3, 3, 4],'attr': [22, 33, 22, 44, 66]},index=[10,20,30,40,50])
print(df)
a = df[(df.BoolCol==3)&(df.attr==22)].index.tolist()
print(a)
  • 1
  • 2
  • 3
  • 4

pandas中数据框是由元素是由列名和索引来定位的,如果没有定义索引,默认就是 0,1,…这样的等号。由值获取索引时,要有df.列名==值的形式 
上面的代码行构造了一个数据框,然后由符合条件的行筛选出来,最后再通过属性.index得到对应的索引值并将索引转化为列表形式。 
结果如下:

    BoolCol  attr
10        1    22
20        2    33
30        3    22
40        3    44
50        4    66
Int64Index([30], dtype='int64')
[30]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

pandas Dataframe 取某行 
df.iloc[[2]]#按index的序值获取行。 
df.loc[[2]]#按index的具体值获取行。 
(4)对列进行赋值处理。 
对某一列可以赋一个标量值也可以是一组值。 
也可以给某一列赋值一个列表或数组,其长度必须跟DataFrame长度相匹配。如果赋值的是一个Series,则对应的索引位置将被赋值,其他位置的值被赋予空值。

4.3、Pandas基本功能

1、重新索引 
Pandas对象的一个方法就是重新索引(reindex),其作用是创建一个新的索引,pandas对象将按这个新索引进行排序。对于不存在的索引值,引入缺失值。 
也可以按columns(行)进行重新索引,对于不存在的列名称,将被填充空值。 
对于不存在的索引值带来的缺失值,也可以在重新索引时使用fill_value给缺失值填充指定值。 
对于缺失值除使用fill_value的方式填充特定值以外还可以使用method=ffill(向前填充、即后面的缺失值用前面非缺失值填充)、bfill(向后填充,即前面的缺失值用后面的非缺失值填充)。 
重新索引的另一个属性是pandas.DataFrame.reset_index,详细用法,可查阅。 
DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False) 
设置单索引和复合索引。如果append添加新索引,drop为False,inplace为True时,索引将会还原为列。

     a    b  c    d  
0  bar  one  z  1.0  
1  bar  two  y  2.0  
2  foo  one  x  3.0  
3  foo  two  w  4.0  
indexed1 = data.set_index('c') 
     a    b    d  
c                 
z  bar  one  1.0  
y  bar  two  2.0  
x  foo  one  3.0  
w  foo  two  4.0 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=”) 
可以还原索引,从新变为默认的整型索引。level控制了具体要还原的那个等级的索引 drop为False则索引列会被还原为普通列,否则会丢失。

         c    d  
a   b            
bar one  z  1.0  
    two  y  2.0  
foo one  x  3.0  
    two  w  4.0  

data.reset_index() 
     a    b  c    d  
0  bar  one  z  1.0  
1  bar  two  y  2.0  
2  foo  one  x  3.0  
3  foo  two  w  4.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

下面是pd.dataframe索引和定位和重索引的一个例子

y1=[1,1,2,2,3,3]
y2=[4,5,6,7,8,9]
y3={'y1':y1,'y2':y2}
a=pd.DataFrame(y3)
print(a)
aIndex=(a.y1==1)&(a.y2==5)
print(aIndex)
b=a[aIndex].reset_index(drop=True)
print(b)
c=b['y1'][0]
print(c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2、丢弃指定轴上的项 
使用drop方法删除指定索引值对应的对象。 
可以同时删除多个索引对应的值。 
对于DataFrame,可以删除任意轴上(columns)的索引值。 
3、算数运算和数据对齐 
(1)Series 与Series之间的运算 
将不同索引的对象进行算数运算,在将对象进行相加时,如果存在时,则结果的索引就是该索引的并集,而结果的对象为空。 
(2)DataFrame与Series之间的运算 
将DataFrame的每一行与Series分别进行运算。(索引相同的进行算数运算,索引不同的被赋予空值) 
4、排序和排名 
根据某种条件对数据集进行排序。 
(1)Series数据结构的排序和排名 
a、按索引值进行排序 
b、按值进行排序 
默认情况下,排序是按升序排列的,但也可通过ascending=False进行降序排列。 
排名跟排序不同的是,排名会增设一个排名值。obj.rank() 
(2)DataFrame数据结构的排序和排名 
按索引值进行排列,一列或多列中的值进行排序,通过by将列名传递给sort_index. 
5、缺失数据处理 
(1)滤出缺失数据 
使用data.dropna()可以滤出缺失数据,默认情况下,data.dropna()滤出含有缺失值的所有行(是含有缺失数据的那一整行)。 
传入how=‘all’将只滤出全是缺失值的那一行。 
要用这种方式滤出列,只需传入axis=1即可。 
(2)填充缺失数据 
通过调用函数fillna,并给予这个函数一个值,则该数组中所有的缺失值都将被这个值填充。df.fillna(0)——缺失值都将被0填充。 
也可以给fillna函数一个字典,就可以实现对不同的列填充不同的值。 
Df.fillna({1:0.5,3:-1})——1列的缺失值用0.5填充,3列的缺失值用-1填充。(列从0开始计数) 
6、汇总和计算描述统计 
就是针对数组进行常用的数学和统计运算。大部分都属于约简和汇总统计。 
其中有求和(sum)运算、累计(cumsum)运算、平均值(mean)等运算。这些运算默认都是针对于行的运算,通过使用axis=1进行列的运算。 
Describe既不是约简型也不是累计型,他是用于一次性产生多个汇总统计指标的运算。根据数组中数据的类型不同,产生的统计指标不同,有最值、分位数(四分位、四分之三)、标准差、方差等指标。 
python 标准差计算(std)、中位数、分位数 
numpy.std() 求标准差的时候默认是除以 n 的,即是有偏的,np.std无偏样本标准差方式为 ddof = 1; 
pandas.std() 默认是除以n-1 的,即是无偏的,如果想和numpy.std() 一样有偏,需要加上参数ddof=0 ,即pandas.std(ddof=0) ;DataFrame的describe()中就包含有std(); 
np.median() 
np.percentile() 
spark sql中 
sqlContext.sql(“SELECT percentile_approx(x, 0.5) FROM df”) 
pandas-如何保存groupby函数的结果? 
解决方法之一如下: 
通过reset_index()函数可以将groupby()的分组结果转换成DataFrame对象,这样就可保存了! 
代码举例:

out_xlsx=in_f_name+'-group.xlsx'
df_group=df.groupby(['推广计划','推广组']).describe().reset_index()
df_group.to_excel(out_xlsx, sheet_name='Sheet1',index=False)
  • 1
  • 2
  • 3

注意:列名会与groupby之前的dataframe保持一致,这样对于后续操作就很方便 
7、唯一值的获取 
此方法可以用于显示去重后的数据。 
8、值计数 
用于计算一个Series中各值出现的次数 
9、层次化索引 
层次化索引是pandas的一个重要功能,它的作用是使你在一个轴上拥有两个或多个索引级别。相当于Excel中vlookup函数的多条件查找中的多条件。 
对于层次化索引对象,选取数据的方式可以通过内层索引,也可以通过外层索引来选取,选取方式和单层索引选取的方式一致。

4.4、Pandas数据类型转换

1、Pandas将列表(List)转换为数据框(Dataframe) 
Python中将列表转换成为数据框有两种情况:第一种是两个不同列表转换成一个数据框,第二种是一个包含不同子列表的列表转换成为数据框。 
第一种:两个不同列表转换成为数据框。这时核心是将列表转换成字典,好处是可以利用字典对列进行命名。

from pandas.core.frame import DataFrame
a=[1,2,3,4]#列表a
b=[5,6,7,8]#列表b
c={"a" : a,
   "b" : b}#将列表a,b转换成字典
data=DataFrame(c)#将字典转换成为数据框
print(data)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:

   a  b
0  1  5
1  2  6
2  3  7
3  4  8
  • 1
  • 2
  • 3
  • 4
  • 5

第二种:将包含不同子列表的列表转换为数据框

from pandas.core.frame import DataFrame
a=[[1,2,3,4],[5,6,7,8]]#包含两个不同的子列表[1,2,3,4]和[5,6,7,8]
data=DataFrame(a)#这时候是以行为标准写入的
print(data)
  • 1
  • 2
  • 3
  • 4

结果如下:

   0  1  2  3
0  1  2  3  4
1  5  6  7  8
  • 1
  • 2
  • 3

转换成dataframe后就可以很方便的变换行列

data=data.T#转置之后得到想要的结果
print(data)
  • 1
  • 2

结果如下:

   0  1
0  1  5
1  2  6
2  3  7
3  4  8
  • 1
  • 2
  • 3
  • 4
  • 5

我们也可以重命名这个dataframe

data.rename(columns={0:'a',1:'b'},inplace=True)
print(data)
  • 1
  • 2

结果如下:

   a  b
0  1  5
1  2  6
2  3  7
3  4  8
  • 1
  • 2
  • 3
  • 4
  • 5

4.5、Pandas时间序列

官网地址 
主要用来处理时间序列数据的,包括三个核心功能: 
1、产生特定时间周期的序列 
2、将时间序列转换为特定周期序列 
3、在各种不标准的时间序列数据基础上进行时间计算或时间回滚或时间前推。

#pandas通常用于处理成组日期,不管这些日期是DataFrame的轴索引还是列,to_datetime方法可以解析多种不同的日期表示形式,并得到DatetimeIndex对象。
date=['2017-6-26', '2017-6-27']
import pandas as pd
pd_date=pd.to_datetime(date)#可以设置格式
print(pd_date)
#结果为:DatetimeIndex(['2017-06-26', '2017-06-27'], dtype='datetime64[ns]', freq=None)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
import pandas as pd
rng = pd.date_range('1/1/2011', periods=6, freq='H')
print(rng)
#我们先得到一个标准时间格式的序列,'1/1/2011'是起始时间,periods=72是得到的序列元素个数,freq='H'是序列的时间间隔。
  • 1
  • 2
  • 3
  • 4

结果如下:

DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 01:00:00',
               '2011-01-01 02:00:00', '2011-01-01 03:00:00',
               '2011-01-01 04:00:00', '2011-01-01 05:00:00'],
              dtype='datetime64[ns]', freq='H')              
  • 1
  • 2
  • 3
  • 4
#利用时间序列来给数据索引
ts = pd.Series(np.random.rand(len(rng)),index=rng)
print(ts)
  • 1
  • 2
  • 3

结果如下

2011-01-01 00:00:00    0.191787
2011-01-01 01:00:00    0.931528
2011-01-01 02:00:00    0.218019
2011-01-01 03:00:00    0.064879
2011-01-01 04:00:00    0.485236
2011-01-01 05:00:00    0.427039
Freq: H, dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
#将时间序列转换成特定间隔的序列,其中的method参数规则了取数的规则,pad表示取截断处上一个数据
converted = ts.asfreq('90Min', method='pad')
print(converted)
  • 1
  • 2
  • 3

结果如一下:

2011-01-01 00:00:00    0.432201
2011-01-01 01:30:00    0.976395
2011-01-01 03:00:00    0.410688
2011-01-01 04:30:00    0.281520
Freq: 90T, dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
#时间序列进行重采样,参数'D'表示一天一个数据,其中的属性.mean()表示取这段时间的均值来采样
print(ts.resample('D').mean())
  • 1
  • 2

结果如下:

2011-01-01    0.564142
Freq: D, dtype: float64
  • 1
  • 2

下面是pandas 中与时间相关的类和创建的方法。

Class Remarks How to create
Timestamp Represents a single timestamp to_datetime, Timestamp
DatetimeIndex Index of Timestamp to_datetime, date_range, bdate_range, DatetimeIndex
Period Represents a single time span Period
PeriodIndex Index of Period period_range, PeriodIndex

4.5.1、时间戳和时间间隔

from datetime import datetime
print(pd.Timestamp(datetime(2012, 5, 1)))#由标准时间格式转换成时间戳
print(pd.Timestamp('2015-5-1'))#由时间格式的字符串转换成时间戳
print(pd.Timestamp(2015,5,1))##分开给出年、月、日转换成时间戳
  • 1
  • 2
  • 3
  • 4

结果如下:

2012-05-01 00:00:00
2015-05-01 00:00:00
2015-05-01 00:00:00
  • 1
  • 2
  • 3
print(pd.Period('2011-01'))#只给到月,所以默认的周期是月
print(pd.Period('2011-05','D'))#虽然只给到月,但定义的周期是天,因而会自动补上天,而且是从第1天开始补
  • 1
  • 2

结果如下:

2011-01
2011-05-01
  • 1
  • 2

时间戳和时间间隔数据类型可以用来作索引,当以时间戳和时间间隔为元素创建列表时,并将列表作为索引时,会自动强制将时间戳和时间间隔转换为时间索引(DatetimeIndex)和周期索引(PeriodIndex)。

dates = [pd.Timestamp('2012-05-01'), pd.Timestamp('2012-05-02'), pd.Timestamp('2012-05-03')]
ts=pd.Series(np.random.randn(len(dates)),index=dates)
print(type(ts.index))
print(ts.index)
print(ts)
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:

<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns]', freq=None)
2012-05-01   -1.223386
2012-05-02   -0.482359
2012-05-03    0.967157
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
periods = [pd.Period('2012-01'), pd.Period('2012-02'), pd.Period('2012-03')]
ts=pd.Series(np.random.randn(len(periods)),index=periods)
print(type(ts.index))
print(ts.index)
print(ts)
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:

<class 'pandas.core.indexes.period.PeriodIndex'>
PeriodIndex(['2012-01', '2012-02', '2012-03'], dtype='period[M]', freq='M')
2012-01    1.212027
2012-02    0.168450
2012-03    2.144617
Freq: M, dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

未完待续

4.6、Pandas读取数据

**4.6.1、pandas.read_csv

可用于将txt文件和csv文件中的数据读入到dataframe中。 
默认情况下,原文件需要以’,’号分隔;否则就需要在read_csv函数中通过参数sep=来指定。

4.6.2、Pandas读取数据库

import pandas as pd
import MySQLdb
mysql_cn= MySQLdb.connect(host='localhost', port=3306,user='myusername', passwd='mypassword', db='mydb')
df = pd.read_sql('select * from test;', con=mysql_cn)    
mysql_cn.close()
  • 1
  • 2
  • 3
  • 4
  • 5

4.7、Pandas操作整理

来源

4.7.1、导入数据:

pd.read_csv(filename):从CSV文件导入数据 
pd.read_table(filename):从限定分隔符的文本文件导入数据 
pd.read_excel(filename):从Excel文件导入数据 
pd.read_sql(query, connection_object):从SQL表/库导入数据 
pd.read_json(json_string):从JSON格式的字符串导入数据 
pd.read_html(url):解析URL、字符串或者HTML文件,抽取其中的tables表格 
pd.read_clipboard():从你的粘贴板获取内容,并传给read_table() 
pd.DataFrame(dict):从字典对象导入数据,Key是列名,Value是数据

4.7.2、导出数据:

df.to_csv(filename):导出数据到CSV文件 
df.to_excel(filename):导出数据到Excel文件 
df.to_sql(table_name, connection_object):导出数据到SQL表 
利用pandas 从mysql数据库读数据很容易,但要写到mysql数据库会有点问题,似乎需要flavor='SQLAlchemy'if_exists='replace',由于无法安装SQLAlchemy库,没有直接写操作过,详情参考 
df.to_json(filename):以Json格式导出数据到文本文件

4.7.3、创建测试对象:

pd.DataFrame(np.random.rand(20,5)):创建20行5列的随机数组成的DataFrame对象 
pd.Series(my_list):从可迭代对象my_list创建一个Series对象 
df.index = pd.date_range(‘1900/1/30’, periods=df.shape[0]):增加一个日期索引

4.7.4、查看、检查数据:

df.head(n):查看DataFrame对象的前n行 
df.tail(n):查看DataFrame对象的最后n行 
df.shape():查看行数和列数 
df.info() :查看索引、数据类型和内存信息 
df.describe():查看数值型列的汇总统计 
s.value_counts(dropna=False):查看Series对象的唯一值和计数 
df.apply(pd.Series.value_counts):查看DataFrame对象中每一列的唯一值和计数

4.7.5、数据选取:

df[col]:根据列名,并以Series的形式返回列 
df[[col1, col2]]:以DataFrame形式返回多列 
s.iloc[0]:按位置选取数据 
s.loc[‘index_one’]:按索引选取数据 
df.iloc[0,:]:返回第一行 
df.iloc[0,0]:返回第一列的第一个元素

4.7.6、数据统计:

df.describe():查看数据值列的汇总统计 
df.mean():返回所有列的均值 
df.corr():返回列与列之间的相关系数 
df.count():返回每一列中的非空值的个数 
df.max():返回每一列的最大值 
df.min():返回每一列的最小值 
df.median():返回每一列的中位数 
df.std():返回每一列的标准差

4.7.7、数据合并:

df1.append(df2):将df2中的行添加到df1的尾部 
df.concat([df1, df2],axis=1):将df2中的列添加到df1的尾部 
df1.join(df2,on=col1,how=’inner’):对df1的列和df2的列执行SQL形式的join

4.7.8、数据处理:

df[df[col] > 0.5]:选择col列的值大于0.5的行 
df.sort_values(col1):按照列col1排序数据,默认升序排列 
df.sort_values(col2, ascending=False):按照列col1降序排列数据 
df.sort_values([col1,col2], ascending=[True,False]):先按列col1升序排列,后按col2降序排列数据 
df.groupby(col):返回一个按列col进行分组的Groupby对象 
df.groupby([col1,col2]):返回一个按多列进行分组的Groupby对象 
df.groupby(col1)[col2]:返回按列col1进行分组后,列col2的均值 
df.pivot_table(index=col1, values=[col2,col3], aggfunc=max):创建一个按列col1进行分组,并计算col2和col3的最大值的数据透视表 
df.groupby(col1).agg(np.mean):返回按列col1分组的所有列的均值 
data.apply(np.mean):对DataFrame中的每一列应用函数np.mean 
data.apply(np.max,axis=1):对DataFrame中的每一行应用函数np.max

4.7.9、数据清理:

df[df[col] > 0.5]:选择col列的值大于0.5的行 
df.sort_values(col1):按照列col1排序数据,默认升序排列 
df.sort_values(col2, ascending=False):按照列col1降序排列数据 
df.sort_values([col1,col2], ascending=[True,False]):先按列col1升序排列,后按col2降序排列数据 
df.groupby(col):返回一个按列col进行分组的Groupby对象 
df.groupby([col1,col2]):返回一个按多列进行分组的Groupby对象 
df.groupby(col1)[col2]:返回按列col1进行分组后,列col2的均值 
df.pivot_table(index=col1, values=[col2,col3], aggfunc=max):创建一个按列col1进行分组,并计算col2和col3的最大值的数据透视表 
df.groupby(col1).agg(np.mean):返回按列col1分组的所有列的均值 
data.apply(np.mean):对DataFrame中的每一列应用函数np.mean 
data.apply(np.max,axis=1):对DataFrame中的每一行应用函数np.max

4.7.10、改列名:

方法1 
a.columns = [‘a’,’b’,’c’] 
方法2 
a.rename(columns={‘A’:’a’, ‘B’:’b’, ‘C’:’c’}, inplace = True)

4.7.11、插入行列

先把数据按列分割,然后再把分出去的列重新插入原数据块中。

In [1]:
import numpy as np
import pandas as pd

table = pd.read_csv('example.csv')
table

Out[1]:
  date spring summer autumn winter 
0 2000 12.233881 16.907301 15.692383 14.085962 
1 2001 12.847481 16.750469 14.514066 13.503746 
2 2002 13.558175 17.203393 15.699948 13.233652 
3 2003 12.654725 16.894915 15.661465 12.843479 
4 2004 13.253730 17.046967 15.209054 14.364791 
5 2005 13.444305 16.745982 16.622188 11.610823 
6 2006 13.505696 16.833579 15.497928 12.199344 
7 2007 13.488526 16.667733 15.817014 13.743822 
8 2008 13.151532 16.486507 15.729573 12.932336 
9 2009 13.457715 16.639238 18.260180 12.653159 
10 2010 13.194548 16.728689 15.426353 13.883358 
11 2011 14.347794 16.689421 14.176580 12.366542 
12 2012 13.605087 17.130568 14.717968 13.292552 
13 2013 13.027908 17.386193 16.203455 13.186121 
14 2014 12.746682 16.544287 14.736768 12.870651 
15 2015 13.465904 16.506123 12.442437 11.018138

In [2]:
date = table.pop('date')
date

Out[2]: 
0 2000 
1 2001 
2 2002 
3 2003 
4 2004 
5 2005 
6 2006 
7 2007 
8 2008 
9 2009 
10 2010 
11 2011 
12 2012 
13 2013 
14 2014 
15 2015 
Name: date, dtype: int64

In [3]:
summer = table.pop('summer')
summer

Out[3]: 
0 16.907301 
1 16.750469 
2 17.203393 
3 16.894915 
4 17.046967 
5 16.745982 
6 16.833579 
7 16.667733 
8 16.486507 
9 16.639238 
10 16.728689 
11 16.689421 
12 17.130568 
13 17.386193 
14 16.544287 
15 16.506123 
Name: summer, dtype: float64

In [4]:
winter = table.pop('winter')
winter

Out[4]: 
0 14.085962 
1 13.503746 
2 13.233652 
3 12.843479 
4 14.364791 
5 11.610823 
6 12.199344 
7 13.743822 
8 12.932336 
9 12.653159 
10 13.883358 
11 12.366542 
12 13.292552 
13 13.186121 
14 12.870651 
15 11.018138 
Name: winter, dtype: float64

In [5]:
table

Out[5]:
  spring  autumn
0 12.233881 15.692383 
1 12.847481 14.514066 
2 13.558175 15.699948 
3 12.654725 15.661465 
4 13.253730 15.209054 
5 13.444305 16.622188 
6 13.505696 15.497928 
7 13.488526 15.817014 
8 13.151532 15.729573 
9 13.457715 18.260180 
10 13.194548 15.426353 
11 14.347794 14.176580 
12 13.605087 14.717968 
13 13.027908 16.203455 
14 12.746682 14.736768 
15 13.465904 12.442437

分割完毕,现在要把各列重新插入,除在最右侧插入用标签直接创建外,其他列用.insert()方法进行插入。
In [6]:
table.insert(0,'date',date)
table

Out[6]:
date    spring  autumn
0 2000 12.233881 15.692383 
1 2001 12.847481 14.514066 
2 2002 13.558175 15.699948 
3 2003 12.654725 15.661465 
4 2004 13.253730 15.209054 
5 2005 13.444305 16.622188 
6 2006 13.505696 15.497928 
7 2007 13.488526 15.817014 
8 2008 13.151532 15.729573 
9 2009 13.457715 18.260180 
10 2010 13.194548 15.426353 
11 2011 14.347794 14.176580 
12 2012 13.605087 14.717968 
13 2013 13.027908 16.203455 
14 2014 12.746682 14.736768 
15 2015 13.465904 12.442437

In [7]:
table.insert(2,'summer',summer)
table

Out[7]: 
date spring summer autumn 
0 2000 12.233881 16.907301 15.692383 
1 2001 12.847481 16.750469 14.514066 
2 2002 13.558175 17.203393 15.699948 
3 2003 12.654725 16.894915 15.661465 
4 2004 13.253730 17.046967 15.209054 
5 2005 13.444305 16.745982 16.622188 
6 2006 13.505696 16.833579 15.497928 
7 2007 13.488526 16.667733 15.817014 
8 2008 13.151532 16.486507 15.729573 
9 2009 13.457715 16.639238 18.260180 
10 2010 13.194548 16.728689 15.426353 
11 2011 14.347794 16.689421 14.176580 
12 2012 13.605087 17.130568 14.717968 
13 2013 13.027908 17.386193 16.203455 
14 2014 12.746682 16.544287 14.736768 
15 2015 13.465904 16.506123 12.442437

In [8]: 
table['winter'] = winter table 
Out[8]: 
date spring summer autumn winter 
0 2000 12.233881 16.907301 15.692383 14.085962 
1 2001 12.847481 16.750469 14.514066 13.503746 
2 2002 13.558175 17.203393 15.699948 13.233652 
3 2003 12.654725 16.894915 15.661465 12.843479 
4 2004 13.253730 17.046967 15.209054 14.364791 
5 2005 13.444305 16.745982 16.622188 11.610823 
6 2006 13.505696 16.833579 15.497928 12.199344 
7 2007 13.488526 16.667733 15.817014 13.743822 
8 2008 13.151532 16.486507 15.729573 12.932336 
9 2009 13.457715 16.639238 18.260180 12.653159 
10 2010 13.194548 16.728689 15.426353 13.883358 
11 2011 14.347794 16.689421 14.176580 12.366542 
12 2012 13.605087 17.130568 14.717968 13.292552 
13 2013 13.027908 17.386193 16.203455 13.186121 
14 2014 12.746682 16.544287 14.736768 12.870651 
15 2015 13.465904 16.506123 12.442437 11.018138
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184

插入行 
目前来说我还没有找到一个直接插入行的函数或方法,所以用的方法是先切割,再拼接。 
创建一个DataFrame准备插入odata中第2行与第3行之间,将odata分割为上下两段,利用append方法将它们拼接起来,注意参数中的ignore_index=True,如果不把这个参数设为True,新排的数据块索引不会重新排列。

In [9]: 
insertRow = pd.DataFrame([[0.,0.,0.,0.,0.]],columns=['date','spring','summer','autumne','winter']) 
above = table.loc[:2] 
below = table.loc[3:] 
newdata = above.append(insertRow,ignore_index=True).append(below,ignore_index=True) 

newdata 
Out[9]: 
date spring summer autumne winter 
0 2000 12.233881 16.907301 15.692383 14.085962 
1 2001 12.847481 16.750469 14.514066 13.503746 
2 2002 13.558175 17.203393 15.699948 13.233652 
3 0 0.000000 0.000000 0.000000 0.000000 
4 2003 12.654725 16.894915 15.661465 12.843479 
5 2004 13.253730 17.046967 15.209054 14.364791 
6 2005 13.444305 16.745982 16.622188 11.610823 
7 2006 13.505696 16.833579 15.497928 12.199344 
8 2007 13.488526 16.667733 15.817014 13.743822 
9 2008 13.151532 16.486507 15.729573 12.932336 
10 2009 13.457715 16.639238 18.260180 12.653159 
11 2010 13.194548 16.728689 15.426353 13.883358 
12 2011 14.347794 16.689421 14.176580 12.366542 
13 2012 13.605087 17.130568 14.717968 13.292552 
14 2013 13.027908 17.386193 16.203455 13.186121 
15 2014 12.746682 16.544287 14.736768 12.870651 
16 2015 13.465904 16.506123 12.442437 11.018138
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

也可以用.concat()的方法来进行拼接,注意ignore_index=True

In [10]: newdata2=pd.concat([above,insert,below],ignore_index=True) 

newdata2 
Out[10]: 
date spring summer autumne winter 
0 2000 12.233881 16.907301 15.692383 14.085962 
1 2001 12.847481 16.750469 14.514066 13.503746 
2 2002 13.558175 17.203393 15.699948 13.233652 
3 0 0.000000 0.000000 0.000000 0.000000 
4 2003 12.654725 16.894915 15.661465 12.843479 
5 2004 13.253730 17.046967 15.209054 14.364791 
6 2005 13.444305 16.745982 16.622188 11.610823 
7 2006 13.505696 16.833579 15.497928 12.199344 
8 2007 13.488526 16.667733 15.817014 13.743822 
9 2008 13.151532 16.486507 15.729573 12.932336 
10 2009 13.457715 16.639238 18.260180 12.653159 
11 2010 13.194548 16.728689 15.426353 13.883358 
12 2011 14.347794 16.689421 14.176580 12.366542 
13 2012 13.605087 17.130568 14.717968 13.292552 
14 2013 13.027908 17.386193 16.203455 13.186121 
15 2014 12.746682 16.544287 14.736768 12.870651 
16 2015 13.465904 16.506123 12.442437 11.018138
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

参考链接 
http://python.jobbole.com/84416/

4.7.12、取数(元素):

取df中某一个具体的数据
iloc     index locate 
举例 :
    print df.iloc[0,0]
    print df.iloc[1, 1]
    print df.iloc[19, 7]

如果 df 是日期索引 +  a,b,c 列名

loc      locate

df.loc[ '2017-01-01', 'A'  ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4.7.13、取数(行):

    one_row = df.iloc[4]
    one_row2 = df.loc['2013-01-02']
    print type(one_row)


取某一行, 取出来后之后的数据类型是   Series
可以  one_row.iloc[1], 再访问 Series 里的数据

    print one_row.iloc[1]
    print one_row.loc['A']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.7.14、取数(列):

column2 = df['A']

column2 是一个 Series 类型

print type( column2 )

可访问 列里面的数据
    print column2[0]
    print column2['2013-01-03']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.7.15、取数(切片):

行模式切片

    dfsub1 = df.iloc[4:5]
    print type( dfsub1 )
    print  dfsub1

    dfsub2 = df.loc['2013-01-03':'2013-01-05']
    print  dfsub2

切片的结果 还是df,  而且改变 dfsub, 会同时改变
df


-------------------------------------------------
列模式 
    print ' get sub by  column mode '
    dfsub = df[['A','B']]
    print type( dfsub )
    print  dfsub


-------------------------------------------------
子集 
row  x  column
方式一:
    print ' get sub by  row  X column  mode '
    dfsub = df.loc['20130102':'20130104', ['A', 'B']]
    print type( dfsub )
    print  dfsub
方式二

dfsub = df.iloc[ 1:3, 1:3 ]
-------------------------------------------------
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

4.7.16、取数(条件切片):

dfsub =  df[  (df.A > 0) and  (df.B > 0)  ]
结果类型是 df

这个玩意很想数据库里的    select where 

送一个特殊条件

print df[ df > 0 ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.7.17、行遍历 :

def testForeach():

        df = pd.read_table('D:/run/data/sz002626_2017-01-04.cvs', encoding='gbk')  # ,header=0
        df = df.sort_index(axis=0, ascending=False)
        df.columns = [1, 2, 3, 4, 5, 6]
        df[7] = 'kong'
        print  df

        # 清洗
        df[3] = df[3].replace('--', '0.00')
        df[3] = df[3].astype(float)

        #遍历
        df[7] = df.apply(lambda r: dorec(r), axis=1)
        print df
        pass

def dorec(rec):
        if (rec[3] > 0):
            return '涨'
        if (rec[3] < 0):
            return '跌'
        else:
            return '平'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

4.7.18、pandas聚合和分组运算之groupby

来源 
根据一个或多个键(可以是函数、数组或DataFrame列名)拆分pandas对象。计算分组摘要统计,如计数、平均值、标准差,或用户自定义函数。对DataFrame的列应用各种各样的函数。应用组内转换或其他运算,如规格化、线性回归、排名或选取子集等。计算透视表或交叉表。执行分位数分析以及其他分组分析。 
1、简单例子

>>> import pandas as pd
>>> df = pd.DataFrame({'key1':['a', 'a', 'b', 'b', 'a'],
...     'key2':['one', 'two', 'one', 'two', 'one'],
...     'data1':np.random.randn(5),
...     'data2':np.random.randn(5)})
>>> df
      data1     data2 key1 key2
0 -0.410673  0.519378    a  one
1 -2.120793  0.199074    a  two
2  0.642216 -0.143671    b  one
3  0.975133 -0.592994    b  two
4 -1.017495 -0.530459    a  one
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

假设你想要按key1进行分组,并计算data1列的平均值,我们可以访问data1,并根据key1调用groupby:

>>> grouped = df['data1'].groupby(df['key1'])
>>> grouped
<pandas.core.groupby.SeriesGroupBy object at 0x04120D70>
  • 1
  • 2
  • 3

变量grouped是一个GroupBy对象,它实际上还没有进行任何计算,只是含有一些有关分组键df[‘key1’]的中间数据而已,然后我们可以调用GroupBy的mean方法来计算分组平均值:

>>> grouped.mean()
key1
a      -1.182987
b       0.808674
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5

说明:数据(Series)根据分组键进行了聚合,产生了一个新的Series,其索引为key1列中的唯一值。之所以结果中索引的名称为key1,是因为原始DataFrame的列df[‘key1’]就叫这个名字。 
2、如果我们一次传入多个数组,就会得到不同的结果

>>> means = df['data1'].groupby([df['key1'], df['key2']]).mean()
>>> means
key1  key2
a     one    -0.714084
      two    -2.120793
b     one     0.642216
      two     0.975133
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通过两个键对数据进行了分组,得到的Series具有一个层次化索引(由唯一的键对组成):

>>> means.unstack()
key2       one       two
key1                   
a    -0.714084 -2.120793
b     0.642216  0.975133
  • 1
  • 2
  • 3
  • 4
  • 5

在上面这些示例中,分组键均为Series。实际上,分组键可以是任何长度适当的数组:

>>> states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
>>> years = np.array([2005, 2005, 2006, 2005, 2006])
>>> df['data1'].groupby([states, years]).mean()
California  2005   -2.120793
            2006    0.642216
Ohio        2005    0.282230
            2006   -1.017495
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3、此外,你还可以将列名(可以是字符串、数字或其他Python对象)用作分组将:

>>> df.groupby('key1').mean()
         data1     data2
key1                   
a    -1.182987  0.062665
b     0.808674 -0.368333
>>> df.groupby(['key1', 'key2']).mean()
              data1     data2
key1 key2                   
a    one  -0.714084 -0.005540
     two  -2.120793  0.199074
b    one   0.642216 -0.143671
     two   0.975133 -0.592994
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

说明:在执行df.groupby(‘key1’).mean()时,结果中没有key2列。这是因为df[‘key2’]不是数值数据,所以被从结果中排除了。默认情况下,所有数值列都会被聚合,虽然有时可能会被过滤为一个子集。 
返回一个含有分组大小的Series:

>>> df.groupby(['key1', 'key2']).size()
key1  key2
a     one     2
      two     1
b     one     1
      two     1
dtype: int64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:分组键中的任何缺失值都会被排除在结果之外。 
5、对分组进行迭代

>>> for name, group in df.groupby('key1'):
...     print(name)
...     print(group)
...
a
      data1     data2 key1 key2
0 -0.410673  0.519378    a  one
1 -2.120793  0.199074    a  two
4 -1.017495 -0.530459    a  one
b
      data1     data2 key1 key2
2  0.642216 -0.143671    b  one
3  0.975133 -0.592994    b  two
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

对于多重键的情况,元组的第一个元素将会是由键值组成的元组:

>>> for (k1, k2), group in df.groupby(['key1', 'key2']):
...     print k1, k2
...     print group
...
a one
      data1     data2 key1 key2
0 -0.410673  0.519378    a  one
4 -1.017495 -0.530459    a  one
a two
      data1     data2 key1 key2
1 -2.120793  0.199074    a  two
b one
      data1     data2 key1 key2
2  0.642216 -0.143671    b  one
b two
      data1     data2 key1 key2
3  0.975133 -0.592994    b  two
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

当然,你可以对这些数据片段做任何操作。有一个你可能会觉得有用的运算:将这些数据片段做成一个字典:

>>> pieces = dict(list(df.groupby('key1')))
>>> pieces['b']
      data1     data2 key1 key2
2  0.642216 -0.143671    b  one
3  0.975133 -0.592994    b  two
>>> df.groupby('key1')
<pandas.core.groupby.DataFrameGroupBy object at 0x0413AE30>
>>> list(df.groupby('key1'))
[('a',       data1     data2 key1 key2
0 -0.410673  0.519378    a  one
1 -2.120793  0.199074    a  two
4 -1.017495 -0.530459    a  one), ('b',       data1     data2 key1 key2
2  0.642216 -0.143671    b  one
3  0.975133 -0.592994    b  two)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6、在其他任何轴上进行分组 
groupby默认是在axis=0上进行分组的,通过设置也可以在其他任何轴上进行分组。那上面例子中的df来说,我们可以根据dtype对列进行分组:

>>> df.dtypes
data1    float64
data2    float64
key1      object
key2      object
dtype: object
>>> grouped = df.groupby(df.dtypes, axis=1)
>>> dict(list(grouped))
{dtype('O'):   key1 key2
0    a  one
1    a  two
2    b  one
3    b  two
4    a  one, dtype('float64'):       data1     data2
0 -0.410673  0.519378
1 -2.120793  0.199074
2  0.642216 -0.143671
3  0.975133 -0.592994
4 -1.017495 -0.530459}

>>> grouped
<pandas.core.groupby.DataFrameGroupBy object at 0x041288F0>
>>> list(grouped)
[(dtype('float64'),       data1     data2
0 -0.410673  0.519378
1 -2.120793  0.199074
2  0.642216 -0.143671
3  0.975133 -0.592994
4 -1.017495 -0.530459), (dtype('O'),   key1 key2
0    a  one
1    a  two
2    b  one
3    b  two
4    a  one)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

7、选取一个或一组列 
对于由DataFrame产生的GroupBy对象,如果用一个(单个字符串)或一组(字符串数组)列名对其进行索引,就能实现选取部分列进行聚合的目的,即:

>>> df.groupby('key1')['data1']
<pandas.core.groupby.SeriesGroupBy object at 0x06615FD0>
>>> df.groupby('key1')['data2']
<pandas.core.groupby.SeriesGroupBy object at 0x06615CB0>
>>> df.groupby('key1')[['data2']]
<pandas.core.groupby.DataFrameGroupBy object at 0x06615F10>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

和以下代码是等效的:

>>> df['data1'].groupby([df['key1']])
<pandas.core.groupby.SeriesGroupBy object at 0x06615FD0>
>>> df[['data2']].groupby([df['key1']])
<pandas.core.groupby.DataFrameGroupBy object at 0x06615F10>
>>> df['data2'].groupby([df['key1']])
<pandas.core.groupby.SeriesGroupBy object at 0x06615E30>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

尤其对于大数据集,很可能只需要对部分列进行聚合。例如,在前面那个数据集中,如果只需计算data2列的平均值并以DataFrame形式得到结果,代码如下:

>>> df.groupby(['key1', 'key2'])[['data2']].mean()
              data2
key1 key2         
a    one  -0.005540
     two   0.199074
b    one  -0.143671
     two  -0.592994
>>> df.groupby(['key1', 'key2'])['data2'].mean()
key1  key2
a     one    -0.005540
      two     0.199074
b     one    -0.143671
      two    -0.592994
Name: data2, dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这种索引操作所返回的对象是一个已分组的DataFrame(如果传入的是列表或数组)或已分组的Series(如果传入的是标量形式的单个列明):

>>> s_grouped = df.groupby(['key1', 'key2'])['data2']
>>> s_grouped
<pandas.core.groupby.SeriesGroupBy object at 0x06615B10>
>>> s_grouped.mean()
key1  key2
a     one    -0.005540
      two     0.199074
b     one    -0.143671
      two    -0.592994
Name: data2, dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

8、通过字典或Series进行分组 
除数组以外,分组信息还可以其他形式存在,来看一个DataFrame示例:

>>> people = pd.DataFrame(np.random.randn(5, 5),
...     columns=['a', 'b', 'c', 'd', 'e'],
...     index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis']
... )
>>> people
               a         b         c         d         e
Joe     0.306336 -0.139431  0.210028 -1.489001 -0.172998
Steve   0.998335  0.494229  0.337624 -1.222726 -0.402655
Wes     1.415329  0.450839 -1.052199  0.731721  0.317225
Jim     0.550551  3.201369  0.669713  0.725751  0.577687
Travis -2.013278 -2.010304  0.117713 -0.545000 -1.228323
>>> people.ix[2:3, ['b', 'c']] = np.nan
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

假设已知列的分组关系,并希望根据分组计算列的总计:

>>> mapping = {'a':'red', 'b':'red', 'c':'blue',
...     'd':'blue', 'e':'red', 'f':'orange'}
>>> mapping
{'a': 'red', 'c': 'blue', 'b': 'red', 'e': 'red', 'd': 'blue', 'f': 'orange'}
>>> type(mapping)
<type 'dict'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

现在,只需将这个字典传给groupby即可:

>>> by_column = people.groupby(mapping, axis=1)
>>> by_column
<pandas.core.groupby.DataFrameGroupBy object at 0x066150F0>
>>> by_column.sum()
            blue       red
Joe    -1.278973 -0.006092
Steve  -0.885102  1.089908
Wes     0.731721  1.732554
Jim     1.395465  4.329606
Travis -0.427287 -5.251905
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Series也有同样的功能,它可以被看做一个固定大小的映射。对于上面那个例子,如果用Series作为分组键,则pandas会检查Series以确保其索引跟分组轴是对齐的:

>>> map_series = pd.Series(mapping)
>>> map_series
a       red
b       red
c      blue
d      blue
e       red
f    orange
dtype: object
>>> people.groupby(map_series, axis=1).count()
        blue  red
Joe        2    3
Steve      2    3
Wes        1    2
Jim        2    3
Travis     2    3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

9、通过函数进行分组 
相较于字典或Series,Python函数在定义分组映射关系时可以更有创意且更为抽象。任何被当做分组键的函数都会在各个索引值上被调用一次,其返回值就会被用作分组名称。

具体点说,以DataFrame为例,其索引值为人的名字。假设你希望根据人名的长度进行分组,虽然可以求取一个字符串长度数组,但其实仅仅传入len函数即可:

>> people.groupby(len).sum()
          a         b         c         d         e
3  2.272216  3.061938  0.879741 -0.031529  0.721914
5  0.998335  0.494229  0.337624 -1.222726 -0.402655
6 -2.013278 -2.010304  0.117713 -0.545000 -1.228323
  • 1
  • 2
  • 3
  • 4
  • 5

将函数跟数组、列表、字典、Series混合使用也不是问题,因为任何东西最终都会被转换为数组:

>>> key_list = ['one', 'one', 'one', 'two', 'two']
>>> people.groupby([len, key_list]).min()
              a         b         c         d         e
3 one  0.306336 -0.139431  0.210028 -1.489001 -0.172998
  two  0.550551  3.201369  0.669713  0.725751  0.577687
5 one  0.998335  0.494229  0.337624 -1.222726 -0.402655
6 two -2.013278 -2.010304  0.117713 -0.545000 -1.228323
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

10、根据索引级别分组 
层次化索引数据集最方便的地方在于它能够根据索引级别进行聚合。要实现该目的,通过level关键字传入级别编号或名称即可:

>>> columns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'],
...     [1, 3, 5, 1, 3]], names=['cty', 'tenor'])
>>> columns
MultiIndex
[US  1,     3,     5, JP  1,     3]
>>> hier_df = pd.DataFrame(np.random.randn(4, 5), columns=columns)
>>> hier_df
cty          US                            JP         
tenor         1         3         5         1         3
0     -0.166600  0.248159 -0.082408 -0.710841 -0.097131
1     -1.762270  0.687458  1.235950 -1.407513  1.304055
2      1.089944  0.258175 -0.749688 -0.851948  1.687768
3     -0.378311 -0.078268  0.247147 -0.018829  0.744540
>>> hier_df.groupby(level='cty', axis=1).count()
cty  JP  US
0     2   3
1     2   3
2     2   3
3     2   3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

5、python数据分析工具

https://www.cnblogs.com/prpl/p/5537417.html 
https://www.cnblogs.com/nxld/p/6058591.html

6、python中数据合并重塑

6.1、numpy数组拼接方法介绍

来源 
https://blog.csdn.net/zyl1042635242/article/details/43162031z 
数组拼接方法一 
思路:首先将数组转成列表,然后利用列表的拼接函数append()、extend()等进行拼接处理,最后将列表转成数组。

import numpy as np
a=np.array([1,2,5])
b=np.array([10,12,15])
a_list=list(a)
b_list=list(b)
a_list.extend(b_list)
print(a_list)
a=np.array(a_list)
print(a)
#[1, 2, 5, 10, 12, 15]
#[ 1  2  5 10 12 15]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

该方法只适用于简单的一维数组拼接,由于转换过程很耗时间,对于大量数据的拼接一般不建议使用。 
数组拼接方法二 
思路:numpy提供了numpy.append(arr, values, axis=None)函数。对于参数规定,要么一个数组和一个数值;要么两个数组,不能三个及以上数组直接append拼接。append函数返回的始终是一个一维数组。

import numpy as np
a=np.arange(5)
print(a)
print(np.append(a,10))
b=np.array([11,22,33])
print(b)
print(np.append(a,b))

a=np.array([[1, 2, 3],[4, 5, 6]])
print(a)
b=np.array([[7,8,9],[10,11,12]])
print(b)
print(np.append(a,b))
# [0 1 2 3 4]
# [ 0  1  2  3  4 10]
# [11 22 33]
# [ 0  1  2  3  4 11 22 33]
# [[1 2 3]
#  [4 5 6]]
# [[ 7  8  9]
#  [10 11 12]]
# [ 1  2  3  4  5  6  7  8  9 10 11 12]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

numpy的数组没有动态改变大小的功能,numpy.append()函数每次都会重新分配整个数组,并把原来的数组复制到新数组中。 
数组拼接方法三 
思路:numpy提供了numpy.concatenate((a1,a2,…), axis=0)函数。能够一次完成多个数组的拼接。其中a1,a2,…是数组类型的参数

import numpy as np

a=np.array([1,2,3])
b=np.array([11,22,33])
c=np.array([44,55,66])
print(np.concatenate((a,b,c),axis=0))#对于一维数组拼接,axis的值不影响最后的结果
# [ 1  2  3 11 22 33 44 55 66]

a=np.array([[1,2,3],[4,5,6]])
b=np.array([[11,21,31],[7,8,9]])
print(a)
print(b)
print(np.concatenate((a,b),axis=0))
print(np.concatenate((a,b),axis=1))#axis=1表示对应行的数组进行拼接
# [[1 2 3]
#  [4 5 6]]
# [[11 21 31]
#  [ 7  8  9]]
# [[ 1  2  3]
#  [ 4  5  6]
#  [11 21 31]
#  [ 7  8  9]]
# [[ 1  2  3 11 21 31]
#  [ 4  5  6  7  8  9]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

拼接只可以把单个的数据当成一个数,axis=0的时候当然是按行放;当axis=1里按列放;R中的dateframe,matlab中的matrix都是同样的道理。

对numpy.append()和numpy.concatenate()两个函数的运行时间进行比较,concatenate()效率更高,适合大规模的数据拼接。

6.2、PANDAS 数据合并与重塑

来源1来源2 
谈到pandas数据的行更新、表合并等操作,一般用到的方法有concat、join、merge。

6.2.1、concat

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
       keys=None, levels=None, names=None, verify_integrity=False)
  • 1
  • 2

concat函数是在pandas底下的方法,可以将数据根据不同的轴作简单的融合。 
参数说明 
objs: series,dataframe或者是panel构成的列示list 
axis: 需要合并链接的轴,0是行,1是列 
join:连接的方式 inner,或者outer

其他一些参数不常用,用的时候再补上说明。

6.2.1.1、相同字段的表首尾相接

这里写图片描述

# 先将表构成list,然后在作为concat的输入
In [4]: frames = [df1, df2, df3]
In [5]: result = pd.concat(frames)
  • 1
  • 2
  • 3

要在相接的时候在加上一个层次的key来识别数据源自于哪张表,可以增加key参数

In [6]: result = pd.concat(frames, keys=['x', 'y', 'z'])
  • 1

这里写图片描述

6.2.1.2、横向表拼接(行对齐)

axis 
当axis = 1的时候,concat就是行对齐,然后将不同列名称的两张表合并

In [9]: result = pd.concat([df1, df4], axis=1)
  • 1

这里写图片描述 
join 
加上join参数的属性,如果为’inner’得到的是两表的交集,如果是outer,得到的是两表的并集。

In [10]: result = pd.concat([df1, df4], axis=1, join='inner')
  • 1

这里写图片描述 
join_axes 
如果有join_axes的参数传入,可以指定根据那个轴来对齐数据 
例如根据df1表对齐数据,就会保留指定的df1表的轴,然后将df4的表与之拼接。相当于mysql的leftjoin和rightjoin。

In [11]: result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])
  • 1

这里写图片描述

6.2.1.3、append

append是series和dataframe的方法,使用它就是默认沿着列进行拼接(axis = 0,列对齐)
  • 1
In [12]: result = df1.append(df2)
  • 1

这里写图片描述

6.2.1.4、无视index的concat

如果两个表的index都没有实际含义,使用ignore_index参数,置true,合并的两个表就会根据列字段对齐,然后合并。最后再重新整理一个新的index。 
这里写图片描述

6.2.1.5、合并的同时增加区分数据组的键

前面提到的keys参数可以用来给合并后的表增加key来区分不同的表数据来源 
可以直接用key参数实现

In [27]: result = pd.concat(frames, keys=['x', 'y', 'z'])
  • 1

这里写图片描述 
传入字典来增加分组键

In [28]: pieces = {'x': df1, 'y': df2, 'z': df3}
In [29]: result = pd.concat(pieces)
  • 1
  • 2

这里写图片描述

6.2.1.6、在dataframe中加入新的行

append方法可以将 series 和 字典构造的数据作为dataframe的新一行插入。

In [34]: s2 = pd.Series(['X0', 'X1', 'X2', 'X3'], index=['A', 'B', 'C', 'D'])
In [35]: result = df1.append(s2, ignore_index=True)
  • 1
  • 2

这里写图片描述 
利用append将表格列字段不同的表合并 
““ 
如果遇到两张表的列字段本来就不一样,但又想将两个表合并,其中无效的值用nan来表示。那么可以使用ignore_index来实现。

```
In [36]: dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
   ....:          {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
   ....: 

In [37]: result = df1.append(dicts, ignore_index=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

6.2.2、merge

pandas的merge方法提供了一种类似于SQL的内存链接操作,官网文档提到它的性能会比其他开源语言的数据操作(例如R)要高效。 
和SQL语句的对比可以看这里 
merge的参数 
on:列名,join用来对齐的那一列的名字,用到这个参数的时候一定要保证左表和右表用来对齐的那一列都有相同的列名。 
left_on:左表对齐的列,可以是列名,也可以是和dataframe同样长度的arrays。 
right_on:右表对齐的列,可以是列名,也可以是和dataframe同样长度的arrays。 
left_index/ right_index: 如果是True的haunted以index作为对齐的key 
how:数据融合的方法。 
sort:根据dataframe合并的keys按字典顺序排序,默认是,如果置false可以提高表现。

merge的默认合并方法:
    merge用于表内部基于 index-on-indexindex-on-column(s) 的合并,但默认是基于index来合并。
  • 1
  • 2

6.2.2.1、复合key的合并方法

使用merge的时候可以选择多个key作为复合可以来对齐合并。
  • 1

通过on指定数据合并对齐的列

In [41]: left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
   ....:                      'key2': ['K0', 'K1', 'K0', 'K1'],
   ....:                      'A': ['A0', 'A1', 'A2', 'A3'],
   ....:                      'B': ['B0', 'B1', 'B2', 'B3']})
   ....: 

In [42]: right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
   ....:                       'key2': ['K0', 'K0', 'K0', 'K0'],
   ....:                       'C': ['C0', 'C1', 'C2', 'C3'],
   ....:                       'D': ['D0', 'D1', 'D2', 'D3']})
   ....: 

In [43]: result = pd.merge(left, right, on=['key1', 'key2'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里写图片描述 
没有指定how的话默认使用inner方法。

how的方法有: 
left

只保留左表的所有数据

In [44]: result = pd.merge(left, right, how='left', on=['key1', 'key2'])
  • 1

这里写图片描述 
right

只保留右表的所有数据

In [45]: result = pd.merge(left, right, how='right', on=['key1', 'key2'])
  • 1

这里写图片描述 
outer

保留两个表的所有信息

In [46]: result = pd.merge(left, right, how='outer', on=['key1', 'key2'])
  • 1

这里写图片描述 
inner

只保留两个表中公共部分的信息

In [47]: result = pd.merge(left, right, how='inner', on=['key1', 'key2'])
  • 1

这里写图片描述

6.2.2.2、indicator

v0.17.0 版本的pandas开始还支持一个indicator的参数,如果置True的时候,输出结果会增加一列 ’ _merge’。_merge列可以取三个值

  • left_only 只在左表中
  • right_only 只在右表中
  • both 两个表中都有

6.2.3、join方法

dataframe内置的join方法是一种快速合并的方法。它默认以index作为对齐的列。

6.2.3.1、how 参数

join中的how参数和merge中的how参数一样,用来指定表合并保留数据的规则。 
具体可见前面的 how 说明。

6.2.3.2、on 参数

在实际应用中如果右表的索引值正是左表的某一列的值,这时可以通过将 右表的索引 和 左表的列 对齐合并这样灵活的方式进行合并。

In [59]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
   ....:                      'B': ['B0', 'B1', 'B2', 'B3'],
   ....:                      'key': ['K0', 'K1', 'K0', 'K1']})
   ....: 

In [60]: right = pd.DataFrame({'C': ['C0', 'C1'],
   ....:                       'D': ['D0', 'D1']},
   ....:                       index=['K0', 'K1'])
   ....: 

In [61]: result = left.join(right, on='key')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里写图片描述

6.2.3.3、suffix后缀参数

如果和表合并的过程中遇到有一列两个表都同名,但是值不同,合并的时候又都想保留下来,就可以用suffixes给每个表的重复列名增加后缀。

In [79]: result = pd.merge(left, right, on='k', suffixes=['_l', '_r'])
  • 1

这里写图片描述

  • 另外还有lsuffix 和 rsuffix分别指定左表的后缀和右表的后缀。

6.2.3.4、组合多个dataframe

一次组合多个dataframe的时候可以传入元素为dataframe的列表或者tuple。一次join多个,一次解决多次烦恼~

In [83]: right2 = pd.DataFrame({'v': [7, 8, 9]}, index=['K1', 'K1', 'K2'])
In [84]: result = left.join([right, right2])
  • 1
  • 2

这里写图片描述

6.2.4、更新表的nan值

6.2.4.1、combine_first

如果一个表的nan值,在另一个表相同位置(相同索引和相同列)可以找到,则可以通过combine_first来更新数据

6.2.4.2、update

如果要用一张表中的数据来更新另一张表的数据则可以用update来实现

6.2.4.3、combine_first 和 update 的区别

使用combine_first会只更新左表的nan值。而update则会更新左表的所有能在右表中找到的值(两表位置相对应)。 
示例代码参考来源——官网

猜你喜欢

转载自blog.csdn.net/yizhuanlu9607/article/details/80583593
今日推荐